{
  "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.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}