{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Font table\n\nMatplotlib's font support is provided by the FreeType library.\n\nHere, we use `~.Axes.table` to draw a table that shows the glyphs by Unicode\ncodepoint. For brevity, the table only contains the first 256 glyphs.\n\nThe example is a full working script. You can download it and use it to\ninvestigate a font by running ::\n\n python font_table.py /path/to/font/file\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import os\nfrom pathlib import Path\nimport unicodedata\n\nimport matplotlib.pyplot as plt\n\nimport matplotlib.font_manager as fm\nfrom matplotlib.ft2font import FT2Font\n\n\ndef print_glyphs(path):\n \"\"\"\n Print the all glyphs in the given font file to stdout.\n\n Parameters\n ----------\n path : str or None\n The path to the font file. If None, use Matplotlib's default font.\n \"\"\"\n if path is None:\n path = fm.findfont(fm.FontProperties()) # The default font.\n\n font = FT2Font(path)\n\n charmap = font.get_charmap()\n max_indices_len = len(str(max(charmap.values())))\n\n print(\"The font face contains the following glyphs:\")\n for char_code, glyph_index in charmap.items():\n char = chr(char_code)\n name = unicodedata.name(\n char,\n f\"{char_code:#x} ({font.get_glyph_name(glyph_index)})\")\n print(f\"{glyph_index:>{max_indices_len}} {char} {name}\")\n\n\ndef draw_font_table(path):\n \"\"\"\n Draw a font table of the first 255 chars of the given font.\n\n Parameters\n ----------\n path : str or None\n The path to the font file. If None, use Matplotlib's default font.\n \"\"\"\n if path is None:\n path = fm.findfont(fm.FontProperties()) # The default font.\n\n font = FT2Font(path)\n # A charmap is a mapping of \"character codes\" (in the sense of a character\n # encoding, e.g. latin-1) to glyph indices (i.e. the internal storage table\n # of the font face).\n # In FreeType>=2.1, a Unicode charmap (i.e. mapping Unicode codepoints)\n # is selected by default. Moreover, recent versions of FreeType will\n # automatically synthesize such a charmap if the font does not include one\n # (this behavior depends on the font format; for example it is present\n # since FreeType 2.0 for Type 1 fonts but only since FreeType 2.8 for\n # TrueType (actually, SFNT) fonts).\n # The code below (specifically, the ``chr(char_code)`` call) assumes that\n # we have indeed selected a Unicode charmap.\n codes = font.get_charmap().items()\n\n labelc = [f\"{i:X}\" for i in range(16)]\n labelr = [f\"{i:02X}\" for i in range(0, 16*16, 16)]\n chars = [[\"\" for c in range(16)] for r in range(16)]\n\n for char_code, glyph_index in codes:\n if char_code >= 256:\n continue\n row, col = divmod(char_code, 16)\n chars[row][col] = chr(char_code)\n\n fig, ax = plt.subplots(figsize=(8, 4))\n ax.set_title(os.path.basename(path))\n ax.set_axis_off()\n\n table = ax.table(\n cellText=chars,\n rowLabels=labelr,\n colLabels=labelc,\n rowColours=[\"palegreen\"] * 16,\n colColours=[\"palegreen\"] * 16,\n cellColours=[[\".95\" for c in range(16)] for r in range(16)],\n cellLoc='center',\n loc='upper left',\n )\n for key, cell in table.get_celld().items():\n row, col = key\n if row > 0 and col > -1: # Beware of table's idiosyncratic indexing...\n cell.set_text_props(font=Path(path))\n\n fig.tight_layout()\n plt.show()\n\n\nif __name__ == \"__main__\":\n from argparse import ArgumentParser\n\n parser = ArgumentParser(description=\"Display a font table.\")\n parser.add_argument(\"path\", nargs=\"?\", help=\"Path to the font file.\")\n parser.add_argument(\"--print-all\", action=\"store_true\",\n help=\"Additionally, print all chars to stdout.\")\n args = parser.parse_args()\n\n if args.print_all:\n print_glyphs(args.path)\n draw_font_table(args.path)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }