{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n.. redirect-from:: /users/fonts\n.. redirect-from:: /users/explain/fonts\n\n\n# Fonts in Matplotlib\n\nMatplotlib needs fonts to work with its text engine, some of which are shipped\nalongside the installation. The default font is [DejaVu Sans](https://dejavu-fonts.github.io) which covers most European writing systems.\nHowever, users can configure the default fonts, and provide their own custom\nfonts. See `Customizing text properties ` for\ndetails and `font-nonlatin` in particular for glyphs not supported by\nDejaVu Sans.\n\nMatplotlib also provides an option to offload text rendering to a TeX engine\n(``usetex=True``), see `Text rendering with LaTeX\n`.\n\n## Fonts in PDF and PostScript\n\nFonts have a long (and sometimes incompatible) history in computing, leading to\ndifferent platforms supporting different types of fonts. In practice,\nMatplotlib supports three font specifications (in addition to pdf 'core fonts',\nwhich are explained later in the guide):\n\n.. list-table:: Type of Fonts\n :header-rows: 1\n\n * - Type 1 (PDF)\n - Type 3 (PDF/PS)\n - TrueType (PDF)\n * - One of the oldest types, introduced by Adobe\n - Similar to Type 1 in terms of introduction\n - Newer than previous types, used commonly today, introduced by Apple\n * - Restricted subset of PostScript, charstrings are in bytecode\n - Full PostScript language, allows embedding arbitrary code\n (in theory, even render fractals when rasterizing!)\n - Include a virtual machine that can execute code!\n * - These fonts support font hinting\n - Do not support font hinting\n - Hinting supported (virtual machine processes the \"hints\")\n * - Non-subsetted through Matplotlib\n - Subsetted via external module ttconv\n - Subsetted via external module\n [fontTools](https://github.com/fonttools/fonttools)_\n\n

Note

Adobe disabled__ support for authoring with Type 1 fonts in January 2023.\n\n __ https://helpx.adobe.com/fonts/kb/postscript-type-1-fonts-end-of-support.html

\n\nOther font specifications which Matplotlib supports:\n\n- Type 42 fonts (PS):\n\n - PostScript wrapper around TrueType fonts\n - 42 is the [Answer to Life, the Universe, and Everything!](https://en.wikipedia.org/wiki/Answer_to_Life,_the_Universe,_and_Everything)\n - Matplotlib uses the external library\n [fontTools](https://github.com/fonttools/fonttools)_ to subset these types of\n fonts\n\n- OpenType fonts:\n\n - OpenType is a new standard for digital type fonts, developed jointly by\n Adobe and Microsoft\n - Generally contain a much larger character set!\n - Limited support with Matplotlib\n\n### Font subsetting\n\nThe PDF and PostScript formats support embedding fonts in files, allowing the\ndisplay program to correctly render the text, independent of what fonts are\ninstalled on the viewer's computer and without the need to pre-rasterize the text.\nThis ensures that if the output is zoomed or resized the text does not become\npixelated. However, embedding full fonts in the file can lead to large output\nfiles, particularly with fonts with many glyphs such as those that support CJK\n(Chinese/Japanese/Korean).\n\nThe solution to this problem is to subset the fonts used in the document and\nonly embed the glyphs actually used. This gets both vector text and small\nfiles sizes. Computing the subset of the font required and writing the new\n(reduced) font are both complex problem and thus Matplotlib relies on\n[fontTools](https://fonttools.readthedocs.io/en/latest/)_ and a vendored fork\nof ttconv.\n\nCurrently Type 3, Type 42, and TrueType fonts are subsetted. Type 1 fonts are not.\n\n### Core Fonts\n\nIn addition to the ability to embed fonts, as part of the [PostScript](https://en.wikipedia.org/wiki/PostScript_fonts#Core_Font_Set) and [PDF\nspecification](https://docs.oracle.com/cd/E96927_01/TSG/FAQ/What%20are%20the%2014%20base%20fonts%20distributed%20with%20Acroba.html)\nthere are 14 Core Fonts that compliant viewers must ensure are available. If\nyou restrict your document to only these fonts you do not have to embed any\nfont information in the document but still get vector text.\n\nThis is especially helpful to generate *really lightweight* documents::\n\n # trigger core fonts for PDF backend\n plt.rcParams[\"pdf.use14corefonts\"] = True\n # trigger core fonts for PS backend\n plt.rcParams[\"ps.useafm\"] = True\n\n chars = \"AFM ftw!\"\n fig, ax = plt.subplots()\n ax.text(0.5, 0.5, chars)\n\n fig.savefig(\"AFM_PDF.pdf\", format=\"pdf\")\n fig.savefig(\"AFM_PS.ps\", format=\"ps\")\n\n## Fonts in SVG\n\nText can output to SVG in two ways controlled by :rc:`svg.fonttype`:\n\n- as a path (``'path'``) in the SVG\n- as string in the SVG with font styling on the element (``'none'``)\n\nWhen saving via ``'path'`` Matplotlib will compute the path of the glyphs used\nas vector paths and write those to the output. The advantage of doing so is\nthat the SVG will look the same on all computers independent of what fonts are\ninstalled. However the text will not be editable after the fact.\nIn contrast, saving with ``'none'`` will result in smaller files and the\ntext will appear directly in the markup. However, the appearance may vary\nbased on the SVG viewer and what fonts are available.\n\n## Fonts in Agg\n\nTo output text to raster formats via Agg, Matplotlib relies on [FreeType](https://www.freetype.org/). Because the exact rendering of the glyphs\nchanges between FreeType versions we pin to a specific version for our image\ncomparison tests.\n\n## How Matplotlib selects fonts\n\nInternally, using a font in Matplotlib is a three step process:\n\n1. a `.FontProperties` object is created (explicitly or implicitly)\n2. based on the `.FontProperties` object the methods on `.FontManager` are used\n to select the closest \"best\" font Matplotlib is aware of (except for\n ``'none'`` mode of SVG).\n3. the Python proxy for the font object is used by the backend code to render\n the text -- the exact details depend on the backend via `.font_manager.get_font`.\n\nThe algorithm to select the \"best\" font is a modified version of the algorithm\nspecified by the [CSS1 Specifications](http://www.w3.org/TR/1998/REC-CSS2-19980512/) which is used by web browsers.\nThis algorithm takes into account the font family name (e.g. \"Arial\", \"Noto\nSans CJK\", \"Hack\", ...), the size, style, and weight. In addition to family\nnames that map directly to fonts there are five \"generic font family names\"\n(serif, monospace, fantasy, cursive, and sans-serif) that will internally be\nmapped to any one of a set of fonts.\n\nCurrently the public API for doing step 2 is `.FontManager.findfont` (and that\nmethod on the global `.FontManager` instance is aliased at the module level as\n`.font_manager.findfont`), which will only find a single font and return the absolute\npath to the font on the filesystem.\n\n## Font fallback\n\nThere is no font that covers the entire Unicode space thus it is possible for the\nusers to require a mix of glyphs that cannot be satisfied from a single font.\nWhile it has been possible to use multiple fonts within a Figure, on distinct\n`.Text` instances, it was not previous possible to use multiple fonts in the\nsame `.Text` instance (as a web browser does). As of Matplotlib 3.6 the Agg,\nSVG, PDF, and PS backends will \"fallback\" through multiple fonts in a single\n`.Text` instance:\n\n.. plot::\n :include-source:\n :caption: The string \"There are \u51e0\u4e2a\u6c49\u5b57 in between!\" rendered with 2 fonts.\n\n fig, ax = plt.subplots()\n ax.text(\n .5, .5, \"There are \u51e0\u4e2a\u6c49\u5b57 in between!\",\n family=['DejaVu Sans', 'Noto Sans CJK JP', 'Noto Sans TC'],\n ha='center'\n )\n\nInternally this is implemented by setting The \"font family\" on\n`.FontProperties` objects to a list of font families. A (currently)\nprivate API extracts a list of paths to all of the fonts found and then\nconstructs a single `.ft2font.FT2Font` object that is aware of all of the fonts.\nEach glyph of the string is rendered using the first font in the list that\ncontains that glyph.\n\nA majority of this work was done by Aitik Gupta supported by Google Summer of\nCode 2021.\n" ] } ], "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 }