summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2014-09-17 08:30:55 +0200
committerBehdad Esfahbod <behdad@behdad.org>2014-09-17 08:30:55 +0200
commitd88c6d90f2537a602c34f3b21c9f97ab9a20196d (patch)
treeac94ff04bc70c2bcfe9f1b7e35da4baf822392e4
parent155410efbd93813e8f444f6b9eaf31917159cc28 (diff)
[fonttools] Flesh out
-rw-r--r--fonttools/behdad.pngbin11176 -> 80676 bytes
-rwxr-xr-xfonttools/fonttools_slides.py424
-rw-r--r--fonttools/fonttools_theme.py6
-rw-r--r--fonttools/snippets/drop_glyphnames.py8
-rw-r--r--fonttools/snippets/merging.txt11
-rw-r--r--fonttools/snippets/rename_glyphs.py12
-rw-r--r--fonttools/snippets/subsetting.txt32
-rw-r--r--fonttools/snippets/tofu.ttx16
-rw-r--r--fonttools/snippets/ttx.ttx204
-rw-r--r--fonttools/snippets/unencoded.py12
-rw-r--r--pangopygments.py9
-rwxr-xr-xslippy.py1
12 files changed, 648 insertions, 87 deletions
diff --git a/fonttools/behdad.png b/fonttools/behdad.png
index b9ed80f..7a07e71 100644
--- a/fonttools/behdad.png
+++ b/fonttools/behdad.png
Binary files differ
diff --git a/fonttools/fonttools_slides.py b/fonttools/fonttools_slides.py
index a95d6de..1bebe92 100755
--- a/fonttools/fonttools_slides.py
+++ b/fonttools/fonttools_slides.py
@@ -23,9 +23,16 @@
# The more useful of them here are put_text, put_image, and
# set_allocation. See their pydocs.
+title_font="Cinzel"
+head_font="Julius Sans One Bold"
+body_font="Merriweather Sans Light"
+
slides = []
def slide_add(f, data=None, width=800, height=600):
- #slides[:0] = [(f, data, width, height)]
+ if data is None:
+ data = {}
+ if "desc" not in data:
+ data['desc'] = body_font
slides.append ((f, data, width, height))
return f
@@ -39,6 +46,7 @@ whois = 0
def who(name):
global whois
whois = name
+
# And convenience functions to add a slide. Can be
# used as a function decorator, or called directly.
def slide_who(f, who, data=None):
@@ -48,45 +56,28 @@ def slide_who(f, who, data=None):
data = {}
data['who'] = who
return slide_add (f, data)
+
def slide(f, data=None):
return slide_who (f, whois, data=data)
-def slide_noone(f, data=None):
+
+def slide_heading(f, data=None):
+ if data is None:
+ data = {}
+ if 'desc' not in data:
+ data['desc'] = head_font
if data and 'who' in data:
return slide_who (f, data['who'], data=data)
else:
return slide_who (f, 0, data=data)
-#
-# Slides start here
-#
-
-who (behdad)
-
-@slide
-def title_slide (r):
- r.move_to (400, 250)
- r.put_text ("<b>FontTools</b>\n"+
- "<span font_desc='30'>"+
- "reviving an Open Source project &amp;\n"+
- "<span strikethrough='true'>re</span>building a thriving community"+
- "</span>", valign=0, halign=0, desc="100")
-
- r.move_to (400, 550)
- r.put_text ("""Behdad Esfahbod\n<span font_desc="monospace 16">behdad@google.com\nhttp://behdad.org</span>""",
- desc="20", halign=0, valign=-1)
-
-def list_slide (l, data=None):
+def bullet_list_slide (title, items):
def s (r):
- return '\n'.join (l)
- #yield l[0]
- #for i in l[1:]:
- # yield '\n'+i
- s.__name__ = l[0]
+ ts = "<span font_desc='"+head_font+"'>"+title+"</span>\n"
+ return ts + '\n'.join ("• " + item for item in items)
+ s.__name__ = title
+ data={'desc': body_font, 'align': pango.ALIGN_LEFT}
slide (s, data)
-slide_noone("History")
-slide_noone("Where")
-
def image_slide (f, width=600, height=600, imgwidth=0, imgheight=0, xoffset=0, yoffset=0, data=None):
def s (r):
r.move_to (400+xoffset, 300+yoffset)
@@ -105,33 +96,16 @@ def draw_image (r, f, width=600, height=600, imgwidth=0, imgheight=0, xoffset=0,
y = (600 - height) * .5
r.set_allocation (x, y, width, height)
-slide_noone("<b>Demo\ntime!</b>")
-
-# Demo!
-
-slide_noone("<b>Limitations</b>")
-slide("Memory\nfootprint")
-slide("Speed+memory\nfont-dependent")
-
-slide_noone("<b>Advantages</b>")
-slide("Memory\nfootprint")
-slide("Subpixel\npositioning")
-slide("Pinch-to-zoom")
-
-list_slide ([
- "<b>Challenges</b>",
- "• Shader size / complexity",
- "• Pixel cost",
- "• Conditionals",
- "• Dependent texture lookups",
- "• Variable loop iterations",
- "• Interpolation accuracy",
- ], data={'align': pango.ALIGN_LEFT})
-
-def source_slide(s, lang="python"):
+def source_slide(s, lang):
s = highlight(s, lang)
s = "<span font_desc='monospace'>" + s + "</span>"
- slide_noone (s, data={'align': pango.ALIGN_LEFT})
+ slide_heading (s, data={'align': pango.ALIGN_LEFT})
+
+def python_slide(s):
+ source_slide(s, lang="py")
+
+def xml_slide(s):
+ source_slide(s, lang="xml")
def patch_slide(s):
lines = s.split ("\n")
@@ -150,7 +124,7 @@ def patch_slide(s):
s = '\n'.join (new_lines)
s = "<span font_desc='monospace'>" + s + "</span>"
- slide_noone (s, data={'align': pango.ALIGN_LEFT})
+ slide_heading (s, data={'align': pango.ALIGN_LEFT})
def commit_slide(s, who=None):
lines = s.split ("\n")
@@ -166,31 +140,321 @@ def commit_slide(s, who=None):
s = '\n'.join (new_lines)
s = "<span font_desc='monospace'>" + s + "</span>"
if who:
- slide_noone (s, data={'align': pango.ALIGN_LEFT, 'who': who})
+ slide_heading (s, data={'align': pango.ALIGN_LEFT, 'who': who})
else:
- slide_noone (s, data={'align': pango.ALIGN_LEFT})
-
-list_slide ([
- "<b>Code: libglyphy</b>",
- "• ~400 lines *.h",
- "• ~2500 lines *.cc *.hh",
- "• ~370 lines *.glsl",
- "• No dependencies",
- ], data={'align': pango.ALIGN_LEFT})
-list_slide ([
- "<b>Code: glyphy-demo</b>",
- "• ~2800 lines *.cc *.h",
- "• ~150 lines *.glsl",
- "• FreeType, GLUT",
- ], data={'align': pango.ALIGN_LEFT})
-list_slide ([
- "<b>More work</b>",
- "• Subpixel-rendering",
- "• Anisotropic-antialiasing",
- ], data={'align': pango.ALIGN_LEFT})
-
-slide("<b>Gallery!</b>")
-slide("<b>Q?</b>")
+ slide_heading (s, data={'align': pango.ALIGN_LEFT})
+
+
+#
+# Slides start here
+#
+
+who (behdad)
+
+@slide
+def title_slide (r):
+ r.move_to (400, 250)
+ r.put_text ("<span font_desc='"+title_font+" bold'>FontTools</span>\n"+
+ "<span font_desc='"+head_font+" 30'>"+
+ "reviving an Open Source project,\n"+
+ "<span strikethrough='true'>re</span>building a thriving community"+
+ "</span>", valign=0, halign=0, desc=title_font+" 100")
+
+ r.move_to (400, 550)
+ r.put_text ("""Behdad Esfahbod""", desc=body_font+" 20", halign=0, valign=-1)
+
+bullet_list_slide("History", [
+ "Started in 1999ish",
+ "by Just van Rossum",
+ "of LettError fame",
+ "Slowed down by 2004",
+ "I picked it up last year"])
+bullet_list_slide("What is it?", [
+ "Two things: TTX and fontTools",
+ "TTX converts fonts to XML and back",
+ "fontTools is a Python library",
+ "Font engineer's calculator",
+ "Closely reflecting OpenType tables",
+ "Minimum abstractions"])
+
+slide_heading("TTX")
+xml_slide("""
+<?xml version="1.0" encoding="utf-8"?>
+<ttFont sfntVersion="\\x00\\x01\\x00\\x00" ttLibVersion="2.5">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="T"/>
+ <GlyphID id="2" name="X"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.001"/>
+ <checkSumAdjustment value="0x22ff1f02"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00001011"/>
+ <unitsPerEm value="1000"/>
+ ...
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="863"/>
+ <descent value="-228"/>
+ <lineGap value="0"/>
+ ...
+ </hhea>
+""")
+xml_slide("""
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="3"/>
+ <maxPoints value="68"/>
+ <maxContours value="7"/>
+ ...
+ </maxp>
+
+ <OS_2>
+ <version value="3"/>
+ <xAvgCharWidth value="560"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000000"/>
+ ...
+ </OS_2>
+""")
+xml_slide("""
+ <hmtx>
+ <mtx name=".notdef" width="260" lsb="0"/>
+ <mtx name="T" width="576" lsb="22"/>
+ <mtx name="X" width="584" lsb="26"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
+ <map code="0x58" name="X"/><!-- LATIN CAPITAL LETTER X -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+""")
+xml_slide("""
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="T" xMin="22" yMin="0" xMax="554" yMax="715">
+ <contour>
+ <pt x="264" y="673" on="1"/>
+ <pt x="22" y="673" on="1"/>
+ <pt x="22" y="715" on="1"/>
+ <pt x="554" y="715" on="1"/>
+ <pt x="554" y="673" on="1"/>
+ <pt x="312" y="673" on="1"/>
+ <pt x="312" y="0" on="1"/>
+ <pt x="264" y="0" on="1"/>
+ </contour>
+ <instructions><assembly>
+ </assembly></instructions>
+ </TTGlyph>
+
+ <TTGlyph name="X" xMin="26" yMin="0" xMax="558" yMax="715">
+ ...
+ </TTGlyph>
+
+ </glyf>
+""")
+xml_slide("""
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Julius Sans One
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
+""")
+
+slide_heading("fontTools")
+bullet_list_slide("<span font_desc='monospace' foreground='#080'>from <span foreground='#00f'><b>fontTools</b></span> import</span>", [
+ "afmLib",
+ "cffLib",
+ "<span strikethrough='true'>fondLib</span>",
+ "<span strikethrough='true'>nfntLib</span>",
+ "t1Lib",
+ "<b>ttLib</b>",
+ ])
+python_slide(open("snippets/unencoded.py").read())
+python_slide("""
+set(['A.salt',
+ 'B.salt',
+ 'E.salt',
+ 'E_x',
+ 'F_i',
+ 'N.salt',
+ 'NULL',
+ 'T_h',
+ 'T_i',
+ 'a.end',
+ ...
+ 'y_z'])
+""")
+
+bullet_list_slide("Framework", [
+ "Compiler / decompiler",
+ "XML serialization",
+ "Optimizer",
+ "Library",
+ "A tool to build products with",
+ "Not an end product",
+])
+bullet_list_slide("Philosophy", [
+ "Minimal abstraction",
+ "Hide byte layout, redundancy, etc",
+ "Platform to build on",
+])
+bullet_list_slide("Why?", [
+ "Free Software",
+ "Python (2.7+ &amp; 3.x)",
+ "Portable",
+ "No dependencies",
+ "Non-destructive",
+ "Batch-friendly",
+])
+bullet_list_slide("What for?", [
+ "Figuring out what's inside a font",
+ "Diff'ing font versions",
+ "Final steps of producing fonts",
+ "Hotfixing existing fonts",
+ "Reporting and analysis over <i>many</i> fonts",
+ "Server-side reporting and manipulation",
+ "Readable VCS-friendly font source code",
+ "Subsetting and merging fonts",
+])
+bullet_list_slide("Hotfixing", [
+ "XML and back",
+ "Python recipes",
+ "Interactive Python",
+])
+python_slide(open("snippets/drop_glyphnames.py").read())
+python_slide(open("snippets/rename_glyphs.py").read())
+
+bullet_list_slide("New work", [
+ "Bitmap tables, color tables, misc tables",
+ "WOFF1 read and write",
+ "More stable XML format",
+ "More optimized font files",
+ "Bug fixes; many of them",
+ "Major speed-up",
+ "New tools",
+])
+
+bullet_list_slide("Tools", [
+ "pyftsubset",
+ "pyftmerge",
+ "pyftinspect",
+])
+bullet_list_slide("pyftsubset", [
+ "OpenType font subsetter &amp; optimizer",
+ "TrueType and CFF flavored",
+ "SFNT and WOFF1",
+ "Full OpenType Layout support",
+ "File-size optimizations",
+ "Designed for webfont productions",
+ "Used for sub-family instantiation",
+])
+source_slide(open("snippets/subsetting.txt").read(), "text")
+bullet_list_slide("pyftmerge", [
+ "Font merging tool",
+ "Very early prototype",
+ "Fonts having same format, upem",
+ "TrueType-flavored only",
+ "Retains hinting from one font",
+ "Handles conflicting characters",
+ "Designed for Noto",
+ "Used for merging Latin and non-Latin",
+])
+source_slide(open("snippets/merging.txt").read(), "text")
+
+# 1. Feel free to mention in your talk Yannis Haralambous' book "Fonts & Encodings" [1], simply because it can be seen as a "user manual for TTX". It talks extensively about the various SFNT tables, and illustrates them using TTX XML structures. So, while fontTools itself has very lacking documentation*, the book is actually a great companion. When I read the book and I look at the .ttx XML representation of a font, I have good chances to actually understand how it all works.
+
+slide_heading("FontTools")
+bullet_list_slide("Strengths", [
+ "Supports wide array of tables",
+ "Low-level, non-destructive",
+ "Python",
+ "Self-documenting",
+ "Optimized output",
+ "Extensible",
+ "Supports all color tables",
+])
+bullet_list_slide("Weaknesses", [
+ "Supports wide array of tables",
+ "Low-level, non-destructive",
+ "Python",
+ "Undocumented",
+ "Always optimizes output",
+ "Not well-extensible",
+ "Supports many legacy tables",
+])
+bullet_list_slide("Users", [
+ "Google Fonts; misc foundries",
+ "Font Bakery, AFDKO, etc",
+ "Adam Twardoch; others",
+ "...",
+])
+bullet_list_slide("Community", [
+ "https://github.com/behdad/fonttools/",
+ "https://groups.google.com/forum/#!forum/fonttools",
+ "http://sourceforge.net/projects/fonttools/",
+])
+
+bullet_list_slide("Future work", [
+ "More font optimization",
+ "Better input: .fea / UFO",
+ "Lint tool",
+ "TrueType / CFF conversion",
+ "Subsetting more tables",
+ "Better merging",
+])
+bullet_list_slide("Future work: optimization", [
+ "Optimal packing: glyf flags / PUSH / etc",
+ "CFF outline operation specializer",
+ "CFF subroutinizer",
+ "TrueType outline optimizer? (fontcrunch)",
+ "TrueType bytecode analysis",
+ "UPEM reduction",
+])
+
+slide("<b>Q?</b>", data={"desc":title_font})
+python_slide('')
+
+xml_slide(open("snippets/tofu.ttx").read())
if __name__ == "__main__":
import slippy
diff --git a/fonttools/fonttools_theme.py b/fonttools/fonttools_theme.py
index 5c5bbf3..078c9de 100644
--- a/fonttools/fonttools_theme.py
+++ b/fonttools/fonttools_theme.py
@@ -20,7 +20,7 @@ import cairo
avatar_margin = .10
logo_margin = .01
-footer_margin = .04
+footer_margin = .05
padding = .000
bubble_rad = .25
@@ -76,7 +76,7 @@ def prepare_page (renderer):
cr.move_to (.5 * width, height-p2)
b = 150.
cr.set_source_rgb (0x9b/b, 0x84/b, 0x66/b)
- renderer.put_text ("ATypI Barcelona, 17 September 2014", height=f-p2, valign=-1, desc="bold")
+ renderer.put_text ("ATypI Barcelona, 17 September 2014", height=f-p2, valign=-1, desc="cinzel")
# Cartoon icons for speakers
who = renderer.data.get ('who', None)
@@ -135,7 +135,7 @@ def draw_bubble (renderer, x, y, w, h, data={}):
cr.restore ()
cr.clip ()
- cr.set_source_rgba (1, 1, 1, .95)
+ cr.set_source_rgba (1, 1, 1, .94)
cr.paint ()
b = 700.
diff --git a/fonttools/snippets/drop_glyphnames.py b/fonttools/snippets/drop_glyphnames.py
new file mode 100644
index 0000000..46fcb99
--- /dev/null
+++ b/fonttools/snippets/drop_glyphnames.py
@@ -0,0 +1,8 @@
+import fontTools.ttLib
+
+font = fontTools.ttLib.TTFont(inpath)
+post = font['post']
+
+post.fomratType = 3.0
+
+font.save(outpath)
diff --git a/fonttools/snippets/merging.txt b/fonttools/snippets/merging.txt
new file mode 100644
index 0000000..20426b8
--- /dev/null
+++ b/fonttools/snippets/merging.txt
@@ -0,0 +1,11 @@
+$ pyftmerge NotoSansDevanagari-Regular.ttf NotoSansBengali-Regular.ttf
+$ ls -l
+-rw-r--r-- 1 behdad eng 266580 Sep 17 08:19 merged.ttf
+-rw-r--r-- 1 behdad eng 188664 Sep 17 08:18 NotoSansBengali-Regular.ttf
+-rw-r--r-- 1 behdad eng 177672 Sep 17 08:18 NotoSansDevanagari-Regular.ttf
+
+$ pyftmerge NotoSansBengali-Regular.ttf NotoSansDevanagari-Regular.ttf
+$ ls -l
+-rw-r--r-- 1 behdad eng 293276 Sep 17 08:21 merged.ttf
+-rw-r--r-- 1 behdad eng 188664 Sep 17 08:18 NotoSansBengali-Regular.ttf
+-rw-r--r-- 1 behdad eng 177672 Sep 17 08:18 NotoSansDevanagari-Regular.ttf
diff --git a/fonttools/snippets/rename_glyphs.py b/fonttools/snippets/rename_glyphs.py
new file mode 100644
index 0000000..2c88a74
--- /dev/null
+++ b/fonttools/snippets/rename_glyphs.py
@@ -0,0 +1,12 @@
+import fontTools.ttLib
+
+font = fontTools.ttLib.TTFont(inpath)
+glyphnames = font.getGlyphOrder()
+
+# ...do the actual renaming in glyphnames...
+
+font = fontTools.ttLib.TTFont(inpath) # load again
+font.setGlyphOrder(glyphnames)
+post = font['post'] # make sure post table is loaded
+
+font.save(outpath)
diff --git a/fonttools/snippets/subsetting.txt b/fonttools/snippets/subsetting.txt
new file mode 100644
index 0000000..767c238
--- /dev/null
+++ b/fonttools/snippets/subsetting.txt
@@ -0,0 +1,32 @@
+$ pyftsubset Lobster.ttf --text=Lobster --glyph-names --verbose
+Text: 'Lobster'
+Unicodes: []
+Glyphs: []
+Gids: []
+cmap pruned
+glyf pruned
+...
+Added gid0 to subset
+Closing glyph list over 'GSUB': 8 glyphs before
+Glyph names: ['.notdef', 'L', 'b', 'e', 'o', 'r', 's', 't']
+Closed glyph list over 'GSUB': 16 glyphs after
+Glyph names: ['.notdef', 'L', 'b', 'b_s', 'b_s.end', 'e', 'e.end', 'o',
+ 'o.end', 'o_s', 'o_s.end', 'r', 's', 's.end', 't', 't.end']
+Retaining 16 glyphs:
+head subsetting not needed
+...
+hmtx subsetted
+cmap subsetted
+glyf subsetted
+kern subsetted to empty; dropped
+name subsetting not needed
+GDEF subsetted
+GPOS subsetted
+GSUB subsetted
+...
+glyf pruned
+GDEF pruned
+GPOS pruned
+GSUB pruned
+Input font: 140856 bytes: Lobster.ttf
+Subset font: 4648 bytes: Lobster.ttf.subset
diff --git a/fonttools/snippets/tofu.ttx b/fonttools/snippets/tofu.ttx
new file mode 100644
index 0000000..f94f414
--- /dev/null
+++ b/fonttools/snippets/tofu.ttx
@@ -0,0 +1,16 @@
+ <cmap raw="1">
+ <!-- Hand-coded format13 table mapping all Unicode
+ characters to glyph00001. -->
+ <hexdata>
+ 0000 0001 <!-- version numTables -->
+ 0003 000A <!-- platformID encodingID -->
+ 0000000C <!-- offset -->
+ 000D 0000 <!-- format reserved -->
+ 0000001C <!-- length -->
+ 00000000 <!-- language -->
+ 00000001 <!-- nGroups -->
+ 00000001 <!-- startCharCode -->
+ 0010FFFE <!-- endCharCode -->
+ 00000001 <!-- glyphID -->
+ </hexdata>
+ </cmap>
diff --git a/fonttools/snippets/ttx.ttx b/fonttools/snippets/ttx.ttx
new file mode 100644
index 0000000..0c7520a
--- /dev/null
+++ b/fonttools/snippets/ttx.ttx
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="2.5">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="T"/>
+ <GlyphID id="2" name="X"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.001"/>
+ <checkSumAdjustment value="0x22ff1f02"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00001011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Sat Oct 6 04:04:08 2012"/>
+ <modified value="Sat Oct 6 04:04:08 2012"/>
+ <xMin value="-44"/>
+ <yMin value="-228"/>
+ <xMax value="1469"/>
+ <yMax value="863"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="8"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="1.0"/>
+ <ascent value="863"/>
+ <descent value="-228"/>
+ <lineGap value="0"/>
+ <advanceWidthMax value="1059"/>
+ <minLeftSideBearing value="-44"/>
+ <minRightSideBearing value="-586"/>
+ <xMaxExtent value="1469"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="3"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="3"/>
+ <maxPoints value="68"/>
+ <maxContours value="7"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="2"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="1"/>
+ <maxFunctionDefs value="1"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="64"/>
+ <maxSizeOfInstructions value="0"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <version value="3"/>
+ <xAvgCharWidth value="560"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000000"/>
+ <ySubscriptXSize value="650"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="650"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="350"/>
+ <yStrikeoutSize value="50"/>
+ <yStrikeoutPosition value="298"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="2"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="10000000 00000000 00000000 00101111"/>
+ <ulUnicodeRange2 value="01000000 00000000 00000000 01001010"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="T26\x00"/>
+ <fsSelection value="00000000 01000000"/>
+ <fsFirstCharIndex value="32"/>
+ <fsLastCharIndex value="64258"/>
+ <sTypoAscender value="863"/>
+ <sTypoDescender value="-228"/>
+ <sTypoLineGap value="0"/>
+ <usWinAscent value="863"/>
+ <usWinDescent value="228"/>
+ <ulCodePageRange1 value="00100000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="649"/>
+ <sCapHeight value="715"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContex value="2"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="260" lsb="0"/>
+ <mtx name="T" width="576" lsb="22"/>
+ <mtx name="X" width="584" lsb="26"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="3" platEncID="1" language="0">
+ <map code="0x54" name="T"/><!-- LATIN CAPITAL LETTER T -->
+ <map code="0x58" name="X"/><!-- LATIN CAPITAL LETTER X -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="T" xMin="22" yMin="0" xMax="554" yMax="715">
+ <contour>
+ <pt x="264" y="673" on="1"/>
+ <pt x="22" y="673" on="1"/>
+ <pt x="22" y="715" on="1"/>
+ <pt x="554" y="715" on="1"/>
+ <pt x="554" y="673" on="1"/>
+ <pt x="312" y="673" on="1"/>
+ <pt x="312" y="0" on="1"/>
+ <pt x="264" y="0" on="1"/>
+ </contour>
+ <instructions><assembly>
+ </assembly></instructions>
+ </TTGlyph>
+
+ <TTGlyph name="X" xMin="26" yMin="0" xMax="558" yMax="715">
+ <contour>
+ <pt x="53" y="715" on="1"/>
+ <pt x="112" y="715" on="1"/>
+ <pt x="304" y="401" on="1"/>
+ <pt x="504" y="715" on="1"/>
+ <pt x="557" y="715" on="1"/>
+ <pt x="327" y="364" on="1"/>
+ <pt x="558" y="0" on="1"/>
+ <pt x="500" y="0" on="1"/>
+ <pt x="294" y="332" on="1"/>
+ <pt x="79" y="0" on="1"/>
+ <pt x="26" y="0" on="1"/>
+ <pt x="270" y="370" on="1"/>
+ </contour>
+ <instructions><assembly>
+ </assembly></instructions>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Julius Sans One
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="-75"/>
+ <underlineThickness value="50"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+</ttFont>
diff --git a/fonttools/snippets/unencoded.py b/fonttools/snippets/unencoded.py
new file mode 100644
index 0000000..a2c678e
--- /dev/null
+++ b/fonttools/snippets/unencoded.py
@@ -0,0 +1,12 @@
+import fontTools.ttLib
+
+font = fontTools.ttLib.TTFont("Lobster.ttf")
+cmap = font['cmap']
+
+encoded = set()
+for subtable in cmap.tables:
+ encoded.update(subtable.cmap.values())
+unencoded = set(font.getGlyphOrder()).difference(encoded)
+
+import pprint
+pprint.pprint(unencoded)
diff --git a/pangopygments.py b/pangopygments.py
index 413f629..b9823c9 100644
--- a/pangopygments.py
+++ b/pangopygments.py
@@ -70,6 +70,7 @@ __LEXERS = {
'py': lexers.PythonLexer,
'scala': lexers.ScalaLexer,
'glsl': lexers.GLShaderLexer,
+ 'xml': lexers.XmlLexer,
}
def highlight(snippet, lang):
@@ -81,11 +82,11 @@ def highlight(snippet, lang):
# Pygments messes up initial and final newlines; fix up
begin = ''
- if snippet[0] == '\n':
+ if snippet[:1] == '\n':
begin = '\n'
snippet = snippet[1:]
end = ''
- if snippet[-1] == '\n':
+ if snippet[-1:] == '\n':
end = '\n'
snippet = snippet[:-1]
@@ -94,8 +95,8 @@ def highlight(snippet, lang):
else:
print("Language %s is not supported." % lang)
- if snippet[0] == '\n' and start == '\n':
- start = ''
+ if snippet[0] == '\n' and begin == '\n':
+ begin = ''
if snippet[-1] == '\n' and end == '\n':
end = ''
diff --git a/slippy.py b/slippy.py
index b036b1e..71cbfe3 100755
--- a/slippy.py
+++ b/slippy.py
@@ -441,6 +441,7 @@ class Slide:
layout = renderer.create_layout (self.text)
layout.set_alignment (self.data.get ('align', pango.ALIGN_CENTER))
+ layout.set_font_description (pango.FontDescription(self.data.get ('desc', "Sans")))
lw, lh = renderer.fit_layout (layout, w, h)
ext = self.extents