Embedding a font in a PPTX: the file that LibreOffice used, and the two it silently ignored A developer building a PPTX exporter found that LibreOffice 26.8.0.3 only honors an embedded font when the fntdata part is an EOT wrapper with Flags 0 and the presentation carries embedTrueTypeFonts="1"; a raw TTF or a missing attribute caused silent fallback to substitute fonts. The developer also measured subsetting trade-offs, reporting that a 2,350-syllable Hangul subset of Pretendard Regular shrank the embedded font from 1,117,566 bytes to 233,993 bytes while losing zero characters across 64,465 (font, character) pairs in a 41-theme test. PowerPoint behavior remains unverified, so the feature is off by default. I've been writing a PPTX exporter, and I wanted the font to travel with the file. When the person opening it doesn't have the font installed, the text falls back to some default and the line breaks drift. PPTX can carry fonts. The part is called a fntdata file, and from the spec and a few open source implementations I pieced together that it should be an EOT wrapper Embedded OpenType around the TTF. Before writing any real code I ran one slide through four variants to see which one the renderer would honor. The setup: one chart slide that uses VT323, a font I did not have installed on this computer. I rendered each variant to PDF with LibreOffice 26.8.0.3 and ran pdffonts to see which font actually got drawn. | What I put in the file | Font in the PDF | |---|---| | Nothing | Fallback fonts FrankRuhlHofshi-Bold, LinuxLibertineG | | EOT with Flags 0, plus embedTrueTypeFonts="1" on the presentation | VT323-Regular | | The raw TTF as the fntdata, plus embedTrueTypeFonts="1" | Fallback, silently ignored | | EOT with Flags 0, no embedTrueTypeFonts attribute | Fallback, silently ignored | Only the second row worked, the one where both pieces were present. In the other two attempts the text fell back to a substitute font, the same outcome as embedding nothing at all. A few details that cost me time: embedTrueTypeFonts="1" . Its import code only reads the embedded font list when that attribute is true, and always treats the data as EOT. That matches what the table shows. typeface attribute all matched. On size, the font is the expensive part. Pretendard Regular after deflate, which is roughly what the zip does to it: | Characters kept | Size | |---|---| | Whole font | 1,117,566 bytes | | All 11,172 Hangul syllables plus ASCII and Latin-1 | 931,592 bytes | | The 2,350 common Hangul syllables plus ASCII and Latin-1 | 233,993 bytes | | Only the 30 characters used on the slide | 4,619 bytes | I went with the 2,350 set. On a test over 41 themes with 177 layouts each, the subset lost zero characters out of 64,465 font, character pairs. The catch is that if the recipient types a syllable outside those 2,350, only that character falls back to the default font. Microsoft's documentation says the same about subset embedding, that it limits editing. Here is what I did not check. I don't have PowerPoint on this computer, so everything above is LibreOffice behavior. I don't know whether PowerPoint accepts an uncompressed EOT. Comments in one open source project say a raw TTF makes Windows PowerPoint fall back to Calibri, and the same comments mention PowerPoint rejecting a whole file as corrupt after an XOR obfuscation attempt on a font part. Those are their observations, not mine, so I'm keeping the feature off by default until someone opens the file in PowerPoint on a machine without the font. Keynote and PowerPoint for the web are also untested. If you've opened an uncompressed Flags 0 EOT fntdata in Windows or Mac PowerPoint on a machine without the font, did it load the font, or did it quietly fall back? This post was written with AI assistance and checked by me against my experiment notes.