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 are the recommended delivery format for web typography.
Aspose.Font FOSS for Python exposes WOFF and WOFF2 through the WoffFont and
Woff2Font classes. Both classes share the same API: they expose font 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 magic bytes automatically:
from aspose_font.loader 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")
# metadata_xml is a WoffFont-specific property
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 containing the raw XML, or None if
the font does not include 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 gives you the
underlying TtfFont with full access to its OpenType table set:
from aspose_font.loader import FontLoader
font = FontLoader.open("MyFont.woff")
# inner_font is a WoffFont-specific property returning the TtfFont
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_font.ttf_tables you can access all standard OpenType tables:
head, hhea, maxp, os2, name, and post. For tables without a named
accessor, use inner_font.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.loader 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 with OpenType
GPOS kern features instead of a kern table will 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. It produces WOFF, WOFF2, and an optional preview SVG in one call:
from aspose_font.web import WebFontBuilder
from aspose_font.loader import FontLoader
from pathlib import Path
# Load a TTF source font
font = FontLoader.open("MyFont.ttf")
# Build WOFF + WOFF2 output files
WebFontBuilder.build(
font=font,
file_stem="MyFont",
include_woff=True,
font_display="swap",
preview_text="The quick brown fox",
instance_coordinates=None,
output_dir=Path("web-output"),
)
After the call, web-output/ contains MyFont.woff, MyFont.woff2, and
optionally a MyFont-preview.svg. 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:
pip install "aspose-font>=1.0.0"
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
| Format | Extension | Load | Convert to WOFF | Convert to WOFF2 |
|---|---|---|---|---|
| TTF | .ttf | Yes | Yes | Yes |
| OTF | .otf | Yes | Yes | Yes |
| WOFF | .woff | Yes | — | Yes |
| WOFF2 | .woff2 | Yes | Yes | — |
| EOT | .eot | Yes | Yes | Yes |
| CFF | .cff | Yes | Yes | Yes |
| TYPE1 | .pfb/.pfa | Yes | Yes | Yes |
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.