Introduction

WOFF (Web Open Font Format) is the standard container for delivering fonts on the web. WOFF 1 wraps a TrueType or CFF font with zlib compression; WOFF 2 applies Brotli compression instead, typically achieving 20-30% better compression ratios. Both formats are supported by every modern browser and remain the recommended delivery format for web typography.

Aspose.Font FOSS for Python now exposes WOFF and WOFF2 through the unified Font class. The class provides the same set of properties (font_name, font_family, num_glyphs), an optional metadata_xml block, an inner_font accessor that returns the underlying TtfFont, and a to_bytes() method for format conversion.

The library is published on PyPI as aspose-font and licensed under the MIT License with no mandatory commercial dependencies.


Key Features

Loading WOFF and WOFF2 Fonts

Use FontLoader.open to load a WOFF or WOFF2 file. The loader detects the format from the file’s magic bytes automatically:

from aspose_font import FontLoader

# Load WOFF 1
woff = FontLoader.open("MyFont.woff")
print(f"Name   : {woff.font_name}")
print(f"Family : {woff.font_family}")
print(f"Style  : {woff.font_style}")
print(f"Glyphs : {woff.num_glyphs}")
print(f"Type   : {woff.font_type}")

# Load WOFF 2
woff2 = FontLoader.open("MyFont.woff2")
print(f"Name   : {woff2.font_name}")
print(f"Glyphs : {woff2.num_glyphs}")

FontLoader.open returns a WoffFont for .woff files and a Woff2Font for .woff2 files. Both classes implement the same Font base interface so code that reads properties is identical for both formats.


Inspecting WOFF Metadata

WOFF files may include an optional XML metadata block containing licensing information, credits, and a font description. Access it through the metadata_xml property:

from aspose_font.loader import FontLoader

font = FontLoader.open("MyFont.woff")
xml = getattr(font, "metadata_xml", None)
if xml:
    print("WOFF metadata XML:")
    print(xml[:500])
else:
    print("No metadata block in this WOFF file")

The metadata_xml property returns a str with the raw XML, or None if the font does not contain a metadata block. Both WoffFont and Woff2Font expose this property.


Accessing Inner TTF Tables

WOFF and WOFF2 wrap a TrueType font. The inner_font property provides the underlying TtfFont with full access to its OpenType table set:

from aspose_font.loader import FontLoader

font = FontLoader.open("MyFont.woff")
inner = getattr(font, "inner_font")
tables = inner.ttf_tables        # TtfTableSet

print(f"Units/em    : {tables.head.units_per_em}")
print(f"Ascender    : {tables.hhea.ascender}")
print(f"Num glyphs  : {tables.maxp.num_glyphs}")
print(f"Family name : {tables.name.best_name(1)}")

Through inner.ttf_tables you can access all standard OpenType tables: head, hhea, maxp, os2, name, and post. For tables without a named accessor, use inner.get_blob(tag) to retrieve raw bytes by OpenType tag.

Kern Pairs from a WOFF Font

get_kern_pairs() returns all kern pairs embedded in the font. Each KernPair carries left (GlyphId), right (GlyphId), and value (int, in font units):

from aspose_font import FontLoader

font = FontLoader.open("MyFont.woff")
pairs = font.get_kern_pairs()
print(f"Kern pairs: {len(pairs)}")

for pair in pairs[:5]:
    print(f"  {pair.left} + {pair.right} = {pair.value}")

Kern pairs are stored in the inner TTF’s kern table. Fonts that provide OpenType GPOS kern features instead of a kern table will still return an empty list from this method.


Format Conversion

FontConverter.convert converts between font formats. Use the FontType enum to specify the target format, then call to_bytes() to serialise:

from aspose_font.loader import FontLoader
from aspose_font.converter import FontConverter
from aspose_font import FontType
from pathlib import Path

# TTF -> WOFF
ttf = FontLoader.open("MyFont.ttf")
woff = FontConverter.convert(ttf, FontType.WOFF)
Path("MyFont.woff").write_bytes(woff.to_bytes(FontType.WOFF))

# TTF -> WOFF2 (Brotli-compressed)
woff2 = FontConverter.convert(ttf, FontType.WOFF2)
Path("MyFont.woff2").write_bytes(woff2.to_bytes(FontType.WOFF2))

# WOFF -> WOFF2
existing_woff = FontLoader.open("MyFont.woff")
converted = FontConverter.convert(existing_woff, FontType.WOFF2)
Path("MyFont-from-woff.woff2").write_bytes(converted.to_bytes(FontType.WOFF2))

# WOFF2 -> WOFF (decompress back to WOFF 1)
existing_woff2 = FontLoader.open("MyFont.woff2")
woff1 = FontConverter.convert(existing_woff2, FontType.WOFF)
Path("MyFont-from-woff2.woff").write_bytes(woff1.to_bytes(FontType.WOFF))

All four conversion paths (TTF to WOFF, TTF to WOFF2, WOFF to WOFF2, WOFF2 to WOFF) are supported by the same FontConverter.convert API.


Building a Web Font Package

WebFontBuilder.build generates a complete web font package from a single TTF source, returning a WebFontBundle with the CSS, HTML, and font assets. Call write_to on the bundle to save the package to disk:

from aspose_font.web import WebFontBuilder
from aspose_font.loader import FontLoader

# Load a TTF source font
font = FontLoader.open("MyFont.ttf")

# Build the web font bundle (WOFF + WOFF2 assets, CSS, HTML)
bundle = WebFontBuilder.build(
    font=font,
    file_stem="MyFont",
    include_woff=True,
    font_display="swap",
    preview_text="The quick brown fox",
    instance_coordinates=None,
)

# Write the bundle's assets, CSS, and HTML to disk
written_paths = bundle.write_to("web-output")
print(f"Wrote {len(written_paths)} files to web-output/")

write_to returns the list of file paths it wrote. The font_display parameter maps directly to the CSS font-display descriptor and accepts "auto", "block", "swap", "fallback", or "optional".


Quick Start

Install the library:

asposefoss/font is not yet published — build from source until it ships. See the project README for build instructions.

Load a WOFF font and convert it to WOFF2:

from aspose_font.loader import FontLoader
from aspose_font.converter import FontConverter
from aspose_font import FontType
from pathlib import Path

# Load WOFF
font = FontLoader.open("MyFont.woff")
print(f"Font   : {font.font_name}")
print(f"Glyphs : {font.num_glyphs}")
print(f"Type   : {font.font_type}")

# Inspect metadata (if present) — WoffFont-specific property
xml = getattr(font, "metadata_xml", None)
print(f"Has metadata: {xml is not None}")

# Access inner OpenType tables — WoffFont-specific property
inner = getattr(font, "inner_font")
tables = inner.ttf_tables
print(f"Units/em: {tables.head.units_per_em}")

# Convert to WOFF2
woff2 = FontConverter.convert(font, FontType.WOFF2)
Path("MyFont.woff2").write_bytes(woff2.to_bytes(FontType.WOFF2))
print("Converted to WOFF2")

Supported Web Font Formats

FormatExtensionLoadConvert to WOFFConvert to WOFF2
TTF.ttfYesYesYes
OTF.otfYesYesYes
WOFF.woffYesYes
WOFF2.woff2YesYes
EOT.eotYesYesYes
CFF.cffYesYesYes
TYPE1.pfb/.pfaYesYesYes

All source formats support conversion to WOFF and WOFF2 via FontConverter.convert.


Open Source and Licensing

Aspose.Font FOSS for Python is released under the MIT License. You can use it in personal, commercial, and open-source projects at no cost. The source code is available on GitHub and the package is distributed via PyPI as aspose-font.


Getting Started