---
title: "OpenType vs TrueType"
url: https://recursiveai.org/onefont/articles/opentype-vs-truetype/
description: "OpenType vs TrueType from the specification: the same file structure and features, quadratic vs cubic outlines, .otf vs .ttf, and how to check any font in C#."
date: 2026-10-26
author: OneFont team
---

# OpenType vs TrueType

OpenType vs TrueType from the specification: the same file structure and features, quadratic vs cubic outlines, .otf vs .ttf, and how to check any font in C#.

October 26, 2026 · OneFont team

OpenType vs TrueType is mostly a difference in how the letter shapes are drawn, not in what the font can do. OpenType is the font format; a “TrueType font” today is an OpenType font whose outlines are TrueType curves (quadratic Béziers in a `glyf` table), while a font usually called “OpenType”, or OpenType-CFF, stores PostScript-style cubic Béziers in a `CFF` table. Both use the same file structure, the same metric and naming tables, the same OpenType layout features (ligatures, kerning, small caps, Arabic and Indic shaping) and the same limit of 65,535 glyphs. Neither is better in general. Use the one your foundry ships, or the one your tools need. This page explains the differences from the OpenType specification and shows how to check what a font file really contains with a few lines of C#.

## OpenType vs TrueType at a glance

|  | TrueType outlines (.ttf, .otf) | CFF outlines (.otf) |
|---|---|---|
| File structure | The same: the sfnt table directory followed by tables |  |
| First four bytes (`sfntVersion`) | `0x00010000` | `OTTO` |
| Outline table | `glyf` with `loca` | `CFF ` (or `CFF2` in variable fonts) |
| Curves | Quadratic Bézier: one control point per curve | Cubic Bézier: two control points per curve |
| Layout features (`GSUB`, `GPOS`, `GDEF`) | The same tables, used the same way |  |
| Maximum number of glyphs | 65,535 for both: `numGlyphs` in the `maxp` table is a 16-bit number |  |
| File extension | `.ttf` or `.otf` | `.otf` |
| Collections (several fonts in one file) | `.ttc` or `.otc` |  |

Sources, all from Microsoft’s [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/): the [font file](https://learn.microsoft.com/en-us/typography/opentype/spec/otff) chapter (“OpenType fonts that contain TrueType outlines should use the value of 0x00010000 for sfntVersion. OpenType fonts containing CFF data (version 1 or 2) should use 0x4F54544F (‘OTTO’…)”), the [maxp table](https://learn.microsoft.com/en-us/typography/opentype/spec/maxp), the [CFF2 table](https://learn.microsoft.com/en-us/typography/opentype/spec/cff2) (“cubic (3rd-order) Bézier curves”) and the [recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/recom) on filenames. The quadratic curves of TrueType are described in Apple’s [TrueType Reference Manual](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html).

## What “TrueType” and “OpenType” mean

The names cause most of the confusion. OpenType is built on TrueType’s file layout, a directory of named tables: the specification calls the TrueType sfnt “wrapper” “a key characteristic of the OpenType format”. Inside that wrapper an OpenType font holds either TrueType outlines or Compact Font Format (CFF) outlines, which come from Adobe’s PostScript fonts, and either kind can carry the layout tables that handle ligatures, contextual forms and complex scripts.

So in practice:

- “TrueType font” means an OpenType font with `glyf` outlines, whatever its extension.
- “OpenType font” in a font menu or a store usually means one with CFF outlines, but every TrueType-flavored font is also OpenType.
- The extension doesn’t decide anything. The specification allows `.otf` for TrueType outlines, and says a file with only CFF outlines should be `.otf`. Read the first four bytes to know (below).
- Features such as ligatures, small caps, old-style figures and Arabic joining live in `GSUB` and `GPOS`, which both flavors carry. A font without them, of either flavor, doesn’t have those features.

## Is OpenType or TrueType better?

For most uses, neither. In the check below, the two builds of the same family have the same glyphs and shape a word identically. The differences that can matter:

- **Curves.** A cubic curve can describe a shape with fewer points. In Adobe’s Source Sans 3 Regular, the “S” is 12 cubic curves in the CFF build and 29 quadratic curves in the TrueType build (measured below). Converting cubic outlines to quadratic approximates each curve with one or more quadratic ones, so a conversion is close to the original but not exact.
- **File size.** Source Sans 3 Regular 3.052 is 334,924 bytes as `.otf` and 431,196 bytes as `.ttf`.
- **Hinting.** Hints, which adjust outlines to the pixel grid at small sizes, work differently in the two flavors: TrueType carries instructions for each glyph, CFF carries hints that the rasterizer interprets. How much this matters depends on the platform and its rasterizer.
- **Tools.** If an app rejects a font, or a library reads only `glyf` outlines, try the other build.
- **On the web,** [WOFF2](https://www.w3.org/TR/WOFF2/) compresses fonts of either flavor: it has its own processing for both the `glyf` and the `CFF` table.

A practical rule: use the build your tools or platform ask for, and when they accept both, expect the same text either way. When you need the other flavor, get the foundry’s own build rather than converting the file yourself.

## Check what a font file contains in C#

This program reads the CFF and TrueType builds of [Source Sans 3](https://github.com/adobe-fonts/source-sans/releases/tag/3.052R) (release 3.052R, SIL Open Font License) with OneFont, a font and text-shaping library for .NET written in C#. It prints each file’s signature, its tables, the curve types of one glyph, and how a word shapes:

*Terminal · NuGet*

```
dotnet new console -o FontCheck
cd FontCheck
dotnet add package RecursiveAI.OneFont --version 1.3.0
```

*Program.cs · OneFont 1.3.0 · .NET 10*

```
using System.Buffers.Binary;
using OneFont;
 
foreach (string path in new[] { "SourceSans3-Regular.otf", "SourceSans3-Regular.ttf" })
{
    byte[] data = File.ReadAllBytes(path);
 
    // The first four bytes say which outlines are inside, whatever the extension says:
    // "OTTO" = CFF (PostScript) outlines, 0x00010000 = TrueType (glyf) outlines.
    uint tag = BinaryPrimitives.ReadUInt32BigEndian(data);
    string kind = tag == 0x4F54544F ? "OTTO (CFF outlines)" : tag == 0x00010000 ? "0x00010000 (TrueType outlines)" : $"0x{tag:X8}";
 
    FontFace face = FontFace.Load(data);
    Console.WriteLine($"{path}: {face.FamilyName} {face.SubfamilyName}, sfnt version {kind}");
    Console.WriteLine($"  IsCff {face.IsCff}, {face.GlyphCount} glyphs, {face.UnitsPerEm} units/em");
 
    string[] tables = ["glyf", "loca", "CFF ", "GSUB", "GPOS", "GDEF", "cmap", "hmtx", "name", "OS/2"];
    Console.WriteLine("  tables: " + string.Join(" ", tables.Select(t => $"{t.Trim()}={(face.HasTable(t) ? "yes" : "no")}")));
 
    // Outline of "S": quadratic curves in TrueType, cubic curves in CFF.
    var counter = new SegmentCounter();
    face.GetOutline(face.GetGlyphIndex('S')).Write(counter, System.Numerics.Matrix3x2.Identity);
    Console.WriteLine($"  'S' outline: {counter.Lines} lines, {counter.Quads} quadratic, {counter.Cubics} cubic");
 
    // Shaping uses the same GSUB/GPOS tables in both files.
    var clusters = TextShaping.ShapeRun("office", face);
    Console.WriteLine("  \"office\" shapes as " + string.Join("|", clusters.Select(c => "office".Substring(c.Start, c.Length))) +
                      " with glyphs " + string.Join(" ", clusters.SelectMany(c => c.Glyphs.ToArray()).Select(g => g.GlyphId)));
}
 
sealed class SegmentCounter : IOutlineSink
{
    public int Lines, Quads, Cubics;
    public void MoveTo(float x, float y) { }
    public void LineTo(float x, float y) => Lines++;
    public void QuadTo(float cx, float cy, float x, float y) => Quads++;
    public void CubicTo(float c1x, float c1y, float c2x, float c2y, float x, float y) => Cubics++;
    public void Close() { }
}
```

*Output · Console*

```
SourceSans3-Regular.otf: Source Sans 3 Regular, sfnt version OTTO (CFF outlines)
  IsCff True, 2478 glyphs, 1000 units/em
  tables: glyf=no loca=no CFF=yes GSUB=yes GPOS=yes GDEF=yes cmap=yes hmtx=yes name=yes OS/2=yes
  'S' outline: 4 lines, 0 quadratic, 12 cubic
  "office" shapes as o|ff|i|c|e with glyphs 42 687 36 30 32
SourceSans3-Regular.ttf: Source Sans 3 Regular, sfnt version 0x00010000 (TrueType outlines)
  IsCff False, 2478 glyphs, 1000 units/em
  tables: glyf=yes loca=yes CFF=no GSUB=yes GPOS=yes GDEF=yes cmap=yes hmtx=yes name=yes OS/2=yes
  'S' outline: 4 lines, 29 quadratic, 0 cubic
  "office" shapes as o|ff|i|c|e with glyphs 42 687 36 30 32
```

- The two files differ in their signature and their outline tables, and in nothing else that this program checks. Both have 2,478 glyphs and 1000 units per em, and both carry `GSUB`, `GPOS` and `GDEF` tables.
- Shaping “office” gives the same glyphs in both, including the “ff” ligature from `GSUB`: OpenType features don’t depend on the outline flavor.
- `FontFace.IsCff` tells the flavors apart without reading the bytes yourself, and `HasTable` and `GetTable` check for any other table, such as `COLR` for color glyphs.
- OneFont reads `.ttf`, `.otf` and `.ttc` files. It doesn’t read WOFF or WOFF2, or `CFF2` outlines, and it doesn’t convert between flavors.

The [read a font file](https://recursiveai.org/onefont/cookbook/read-font-file/) recipe shows names, metrics and the character map, and [text to SVG path](https://recursiveai.org/onefont/cookbook/text-to-svg-path/) turns these outlines into SVG, with `Q` commands for TrueType and `C` for CFF.

## Where next

- [Getting started with OneFont](https://recursiveai.org/onefont/docs/getting-started/): load a font, shape text, find line breaks and fallback fonts.
- [Text shaping in C#](https://recursiveai.org/onefont/articles/text-shaping-csharp/): what GSUB and GPOS do to your text, with OneFont and HarfBuzzSharp.
- [Turn on OpenType features](https://recursiveai.org/onefont/cookbook/opentype-features/) such as small caps and old-style figures.
- To draw text with these fonts on images, see [text in OneImage](https://recursiveai.org/oneimage/docs/text/).
