Draw Font Table with Matplotlib

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

Matplotlib is a popular data visualization library in Python. It provides font support through the FreeType library. In this lab, we will learn how to draw a font table of the first 255 characters of a given font using Matplotlib's Axes.table.

VM Tips

After the VM startup is done, click the top left corner to switch to the Notebook tab to access Jupyter Notebook for practice.

Sometimes, you may need to wait a few seconds for Jupyter Notebook to finish loading. The validation of operations cannot be automated because of limitations in Jupyter Notebook.

If you face issues during learning, feel free to ask Labby. Provide feedback after the session, and we will promptly resolve the problem for you.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("`Python`")) -.-> python/BasicConceptsGroup(["`Basic Concepts`"]) matplotlib(("`Matplotlib`")) -.-> matplotlib/BasicConceptsGroup(["`Basic Concepts`"]) matplotlib(("`Matplotlib`")) -.-> matplotlib/PlotCustomizationGroup(["`Plot Customization`"]) python(("`Python`")) -.-> python/ControlFlowGroup(["`Control Flow`"]) python(("`Python`")) -.-> python/DataStructuresGroup(["`Data Structures`"]) python(("`Python`")) -.-> python/FunctionsGroup(["`Functions`"]) python(("`Python`")) -.-> python/ModulesandPackagesGroup(["`Modules and Packages`"]) python(("`Python`")) -.-> python/PythonStandardLibraryGroup(["`Python Standard Library`"]) python(("`Python`")) -.-> python/DataScienceandMachineLearningGroup(["`Data Science and Machine Learning`"]) python/BasicConceptsGroup -.-> python/comments("`Comments`") matplotlib/BasicConceptsGroup -.-> matplotlib/importing_matplotlib("`Importing Matplotlib`") matplotlib/BasicConceptsGroup -.-> matplotlib/figures_axes("`Understanding Figures and Axes`") matplotlib/PlotCustomizationGroup -.-> matplotlib/adding_tables("`Adding Tables`") python/BasicConceptsGroup -.-> python/variables_data_types("`Variables and Data Types`") python/BasicConceptsGroup -.-> python/strings("`Strings`") python/BasicConceptsGroup -.-> python/type_conversion("`Type Conversion`") python/ControlFlowGroup -.-> python/conditional_statements("`Conditional Statements`") python/ControlFlowGroup -.-> python/for_loops("`For Loops`") python/ControlFlowGroup -.-> python/break_continue("`Break and Continue`") python/ControlFlowGroup -.-> python/list_comprehensions("`List Comprehensions`") python/DataStructuresGroup -.-> python/lists("`Lists`") python/DataStructuresGroup -.-> python/tuples("`Tuples`") python/DataStructuresGroup -.-> python/dictionaries("`Dictionaries`") python/FunctionsGroup -.-> python/function_definition("`Function Definition`") python/ModulesandPackagesGroup -.-> python/importing_modules("`Importing Modules`") python/ModulesandPackagesGroup -.-> python/using_packages("`Using Packages`") python/ModulesandPackagesGroup -.-> python/standard_libraries("`Common Standard Libraries`") python/PythonStandardLibraryGroup -.-> python/os_system("`Operating System and System`") python/DataScienceandMachineLearningGroup -.-> python/data_visualization("`Data Visualization`") python/FunctionsGroup -.-> python/build_in_functions("`Build-in Functions`") subgraph Lab Skills python/comments -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} matplotlib/importing_matplotlib -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} matplotlib/figures_axes -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} matplotlib/adding_tables -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/variables_data_types -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/strings -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/type_conversion -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/conditional_statements -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/for_loops -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/break_continue -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/list_comprehensions -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/lists -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/tuples -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/dictionaries -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/function_definition -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/importing_modules -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/using_packages -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/standard_libraries -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/os_system -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/data_visualization -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} python/build_in_functions -.-> lab-48745{{"`Draw Font Table with Matplotlib`"}} end

Print the glyphs in a font

In this step, we will define a function print_glyphs that prints all the glyphs in a given font file to stdout.

import os
import unicodedata
import matplotlib.font_manager as fm
from matplotlib.ft2font import FT2Font

def print_glyphs(path):
    """
    Print the all glyphs in the given font file to stdout.

    Parameters
    ----------
    path : str or None
        The path to the font file.  If None, use Matplotlib's default font.
    """
    if path is None:
        path = fm.findfont(fm.FontProperties())  ## The default font.

    font = FT2Font(path)

    charmap = font.get_charmap()
    max_indices_len = len(str(max(charmap.values())))

    print("The font face contains the following glyphs:")
    for char_code, glyph_index in charmap.items():
        char = chr(char_code)
        name = unicodedata.name(
                char,
                f"{char_code:#x} ({font.get_glyph_name(glyph_index)})")
        print(f"{glyph_index:>{max_indices_len}} {char} {name}")

Draw a font table

In this step, we will define a function draw_font_table that draws a font table of the first 255 characters of the given font.

import os
from pathlib import Path
import unicodedata
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib.ft2font import FT2Font

def draw_font_table(path):
    """
    Draw a font table of the first 255 chars of the given font.

    Parameters
    ----------
    path : str or None
        The path to the font file.  If None, use Matplotlib's default font.
    """
    if path is None:
        path = fm.findfont(fm.FontProperties())  ## The default font.

    font = FT2Font(path)

    ## Get the charmap of the font
    codes = font.get_charmap().items()

    ## Create the labels and cells of the table
    labelc = [f"{i:X}" for i in range(16)]
    labelr = [f"{i:02X}" for i in range(0, 16*16, 16)]
    chars = [["" for c in range(16)] for r in range(16)]

    for char_code, glyph_index in codes:
        if char_code >= 256:
            continue
        row, col = divmod(char_code, 16)
        chars[row][col] = chr(char_code)

    ## Draw the table using Matplotlib's Axes.table
    fig, ax = plt.subplots(figsize=(8, 4))
    ax.set_title(os.path.basename(path))
    ax.set_axis_off()

    table = ax.table(
        cellText=chars,
        rowLabels=labelr,
        colLabels=labelc,
        rowColours=["palegreen"] * 16,
        colColours=["palegreen"] * 16,
        cellColours=[[".95" for c in range(16)] for r in range(16)],
        cellLoc='center',
        loc='upper left',
    )

    ## Set the font of the table cells to the font of the given path
    for key, cell in table.get_celld().items():
        row, col = key
        if row > 0 and col > -1:  ## Beware of table's idiosyncratic indexing...
            cell.set_text_props(font=Path(path))

    fig.tight_layout()
    plt.show()

Display the font table

In this step, we will use argparse to parse the path to the font file from the command-line arguments. Then we will call print_glyphs to print all the glyphs in the font file, and draw_font_table to draw the font table of the first 255 characters of the font.

if __name__ == "__main__":
    from argparse import ArgumentParser

    parser = ArgumentParser(description="Display a font table.")
    parser.add_argument("path", nargs="?", help="Path to the font file.")
    parser.add_argument("--print-all", action="store_true",
                        help="Additionally, print all chars to stdout.")
    args = parser.parse_args()

    if args.print_all:
        print_glyphs(args.path)
    draw_font_table(args.path)

Summary

In this lab, we learned how to draw a font table of the first 255 characters of a font file using Matplotlib's Axes.table. We defined functions to print all the glyphs in a font file and to draw the font table. We also used argparse to parse the path to the font file from the command-line arguments.

Other Python Tutorials you may like