mcfonts.utils.exporting.opentype

Functions for exporting into OpenType XML-representable data (TTX).

Contains functions for transforming and handling OpenType font XML data..

Module Contents

Functions

add_namerecord_to_font(font_xml, data, name_id)

Set a namerecord in a font.

allocate_character(font_xml, character)

Allocate a Unicode character in a font.

generate_ulunicoderange(characters)

Given a set of characters, return a list of ulUnicodeRanges, with bits set appropriately.

include_glyph(font_xml, glyph, character, ...)

Include glyph into the font XML.

make_cmap(font_xml[, format_4, format_12])

Insert cmap subtables in font_xml. These are used for mapping glyph IDs to Unicode codepoints.

sanitize_font_name(font_name)

Ensure sanitized_font_name is a valid PostScript font name.

set_cfffont_name(font_xml, font_name, family_name)

Set the font's appropriate CFF name in 'CFF ' tables.

set_font_name(font_xml, font_name)

Set the font's name to font_xml in all appropriate places.

set_font_times(font_xml)

Set the font's created and modified times, in the format of %a %b %d %X %Y.

set_notdef_in_font(font_xml, program)

Set the .notdef character of the font.

set_program_to_character(font_xml, program, character)

Set a program to a character.

set_space_to_character(font_xml, character, width[, ...])

Add/set a space character to the font, only defining its width.

set_ulunicoderange(font_xml, characters)

Generate the ulUnicodeRanges corresponding to characters and set them in font_xml.

Attributes

EXCLUDED_FONT_NAME_CHARS

ULUNICODERANGE_BIT_MAP

A mapping of (block codepoint start, block codepoint end) to ulUnicodeRange bit.

XML_FONT_TEMPLATE

Bytes of a blank TTF XML, with a .notdef glyph already embedded.

mcfonts.utils.exporting.opentype.EXCLUDED_FONT_NAME_CHARS
mcfonts.utils.exporting.opentype.ULUNICODERANGE_BIT_MAP : dict[tuple[int, int], int]

A mapping of (block codepoint start, block codepoint end) to ulUnicodeRange bit. It is best to store a single 128 bit number and then split it up for processing later. See https://learn.microsoft.com/en-us/typography/opentype/spec/os2#ur.

mcfonts.utils.exporting.opentype.XML_FONT_TEMPLATE : bytes = b'<?xml version="1.0" encoding="UTF-8"?>\n<ttFont sfntVersion="OTTO" ttLibVersion="4.34">\n ...

Bytes of a blank TTF XML, with a .notdef glyph already embedded. You must call lxml.etree.XML() with this.

mcfonts.utils.exporting.opentype.add_namerecord_to_font(font_xml, data, name_id)

Set a namerecord in a font.

This doesn't check if such a namerecord already exists; this will add new namerecords.

All are encoded at (0, 4) and (3, 1), Unicode 2.0+ full.

Parameters:
font_xml : lxml.etree._Element

The font XML.

data : str

Whatever string to add.

name_id : int

The ID of the namerecord.

Returns:

Nothing, font is modified in-place.

Return type:

None

mcfonts.utils.exporting.opentype.allocate_character(font_xml, character)

Allocate a Unicode character in a font.

This doesn't assign any character data or widths.

Parameters:
font_xml : lxml.etree._Element

The font XML.

character : str

A single character.

Raises:

mcfonts.exceptions.GlyphLimitError -- If there are more than 65,535 glyphs in the font; can't add more.

Return type:

None

mcfonts.utils.exporting.opentype.generate_ulunicoderange(characters)

Given a set of characters, return a list of ulUnicodeRanges, with bits set appropriately.

See https://learn.microsoft.com/en-us/typography/opentype/spec/os2#ur.

>>> generate_ulunicoderange({"A", "B", "☀", "᯿", "�"})
[
    '00000000 00000000 00000000 00000000',
    '00000000 00000000 00000000 00100000',
    '00000000 00000000 01000000 00000000',
    '00000000 00000000 00000000 00000001',
]
Parameters:
characters : set[str]

A set of characters.

Returns:

A list of ulUnicodeRanges, as strings, in order from 1 to 4.

Return type:

list[str]

mcfonts.utils.exporting.opentype.include_glyph(font_xml, glyph, character, allocated_characters)

Include glyph into the font XML.

Different Glyph subtypes have different methods of being imported; this function centralizes those varying methods.

Parameters:
font_xml : lxml.etree._Element

A font XML.

glyph : mcfonts.glyphs.Glyph

An instance of mcfont.glyphs.Glyph.

character : str

The character to assign this glyph to.

allocated_characters : set[str]

A set of the characters already included in the font XML.

Return type:

None

mcfonts.utils.exporting.opentype.make_cmap(font_xml, format_4=True, format_12=True)

Insert cmap subtables in font_xml. These are used for mapping glyph IDs to Unicode codepoints.

If format_4, cmap_format_4 will be added. If format_12, cmap_format_12 will be added.

Parameters:
font_xml : lxml.etree._Element

A font XML.

format_4 : bool

Whether to insert a cmap format 4 subtable. See https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#format-4-segment-mapping-to-delta-values.

format_12 : bool

Whether to insert a cmap format 12 subtable. See https://learn.microsoft.com/en-us/typography/opentype/spec/cmap#format-12-segmented-coverage.

Return type:

None

mcfonts.utils.exporting.opentype.sanitize_font_name(font_name)

Ensure sanitized_font_name is a valid PostScript font name.

A PostScript font name can't:

  • Contain (){}[]<;>%/ or space

  • Be longer than 63 characters

  • Have non-ASCII characters

>>> sanitize_font_name("☀ This is a really long name!")
'_This_is_a_really_long_name!'
>>> sanitize_font_name("(secret info) [do not leak]")
'_secret_info___do_not_leak_'
>>> sanitize_font_name("a really long name with over 63 characters I guarantee it you won't believe it")
'a_really_long_name_with_over_63_characters_I_guarantee_it_you_w'
Parameters:
font_name : str

The font name to sanitize.

Returns:

A valid PostScript font name.

Return type:

str

mcfonts.utils.exporting.opentype.set_cfffont_name(font_xml, font_name, family_name)

Set the font's appropriate CFF name in 'CFF ' tables.

This is different from changing the 'name' tables, see add_namerecord_to_font() instead.

Parameters:
font_xml : lxml.etree._Element

The font XML.

font_name : str

The name of the font (doesn't include "Regular" or related weights).

family_name : str

The family name of the font (doesn't include "Regular" or related weights).

Returns:

Nothing, font is modified in-place.

Return type:

None

mcfonts.utils.exporting.opentype.set_font_name(font_xml, font_name)

Set the font's name to font_xml in all appropriate places.

This is different from set_cfffont_name(), which sets the name for only CFF tables.

Parameters:
font_xml : lxml.etree._Element

The font XML.

font_name : str

The name of the font.

Return type:

None

mcfonts.utils.exporting.opentype.set_font_times(font_xml)

Set the font's created and modified times, in the format of %a %b %d %X %Y.

Parameters:
font_xml : lxml.etree._Element

The font XML.

Returns:

Nothing, font is modified in-place.

Return type:

None

mcfonts.utils.exporting.opentype.set_notdef_in_font(font_xml, program)

Set the .notdef character of the font.

Note

The default font template already has a default notdef, so use this for setting it to something else.

Parameters:
font_xml : lxml.etree._Element

The font XML.

program : list[str]

A list of strings of the glyph's program.

Returns:

Nothing, font is modified in-place.

Return type:

None

mcfonts.utils.exporting.opentype.set_program_to_character(font_xml, program, character, replace=True)

Set a program to a character.

This is how character data is added to the font. The character must be allocated already; that isn't done in this function.

If the character isn't in the font, add it. If it's and replace is True, set it to the new character data. Otherwise, do nothing.

Parameters:
font_xml : lxml.etree._Element

The font XML.

program : list[str | int]

A list of strings of the glyph's program.

character : str

A single character.

replace : bool

If the character already has data, overwrite.

Returns:

Nothing, font is modified in-place.

Raises:

GlyphLimitError -- If there are more than 65,535 glyphs in the font; can't add more.

mcfonts.utils.exporting.opentype.set_space_to_character(font_xml, character, width, replace=True)

Add/set a space character to the font, only defining its width.

The character must be allocated already. That isn't done in this function.

If the glyph isn't in the font, add it. If it's and replace is True, set it to the new value. Otherwise, do nothing.

Parameters:
font_xml : lxml.etree._Element

The font XML.

character : str

A single character.

width : int

The width of the space, unscaled.

replace : bool

If the character already has data, overwrite.

Returns:

Nothing, font is modified in-place.

Raises:

GlyphLimitError -- If there are more than 65,535 glyphs in the font; can't add more.

Return type:

None

mcfonts.utils.exporting.opentype.set_ulunicoderange(font_xml, characters)

Generate the ulUnicodeRanges corresponding to characters and set them in font_xml.

Parameters:
font_xml : lxml.etree._Element

A font XML.

characters : set[str]

A set of characters to generate ulUnicodeRanges for.

Return type:

None


Last update: 2023 November 30