git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

font/sfnt/proprietary_test.go (48.2K)

   1 // Copyright 2017 The Go Authors. All rights reserved.
   2 // Use of this source code is governed by a BSD-style
   3 // license that can be found in the LICENSE file.
   4 
   5 package sfnt
   6 
   7 /*
   8 This file contains opt-in tests for popular, high quality, proprietary fonts,
   9 made by companies such as Adobe and Microsoft. These fonts are generally
  10 available, but copies are not explicitly included in this repository due to
  11 licensing differences or file size concerns. To opt-in, run:
  12 
  13 go test golang.org/x/image/font/sfnt -args -proprietary
  14 
  15 Not all tests pass out-of-the-box on all systems. For example, the Microsoft
  16 Times New Roman font is downloadable gratis even on non-Windows systems, but as
  17 per the ttf-mscorefonts-installer Debian package, this requires accepting an
  18 End User License Agreement (EULA) and a CAB format decoder. These tests assume
  19 that such fonts have already been installed. You may need to specify the
  20 directories for these fonts:
  21 
  22 go test golang.org/x/image/font/sfnt -args -proprietary \
  23 	-adobeDir=$HOME/fonts/adobe \
  24 	-appleDir=$HOME/fonts/apple \
  25 	-dejavuDir=$HOME/fonts/dejavu \
  26 	-microsoftDir=$HOME/fonts/microsoft \
  27 	-notoDir=$HOME/fonts/noto
  28 
  29 To only run those tests for the Microsoft fonts:
  30 
  31 go test golang.org/x/image/font/sfnt -test.run=ProprietaryMicrosoft -args -proprietary etc
  32 */
  33 
  34 // TODO: enable Apple/Microsoft tests by default on Darwin/Windows?
  35 
  36 import (
  37 	"errors"
  38 	"flag"
  39 	"io/ioutil"
  40 	"path/filepath"
  41 	"strconv"
  42 	"strings"
  43 	"testing"
  44 
  45 	"golang.org/x/image/font"
  46 	"golang.org/x/image/math/fixed"
  47 )
  48 
  49 var (
  50 	proprietary = flag.Bool("proprietary", false, "test proprietary fonts not included in this repository")
  51 
  52 	adobeDir = flag.String(
  53 		"adobeDir",
  54 		// This needs to be set explicitly. There is no default dir on Debian:
  55 		// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736680
  56 		//
  57 		// Get the fonts from https://github.com/adobe-fonts, e.g.:
  58 		//	- https://github.com/adobe-fonts/source-code-pro/releases/latest
  59 		//	- https://github.com/adobe-fonts/source-han-sans/releases/latest
  60 		//	- https://github.com/adobe-fonts/source-sans-pro/releases/latest
  61 		//
  62 		// Copy all of the TTF and OTF files to the one directory, such as
  63 		// $HOME/adobe-fonts, and pass that as the -adobeDir flag here.
  64 		"",
  65 		"directory name for the Adobe proprietary fonts",
  66 	)
  67 
  68 	appleDir = flag.String(
  69 		"appleDir",
  70 		// This needs to be set explicitly. These fonts come with macOS, which
  71 		// is widely available but not freely available.
  72 		//
  73 		// On a Mac, set this to "/System/Library/Fonts/".
  74 		"",
  75 		"directory name for the Apple proprietary fonts",
  76 	)
  77 
  78 	dejavuDir = flag.String(
  79 		"dejavuDir",
  80 		// Get the fonts from https://dejavu-fonts.github.io/
  81 		"",
  82 		"directory name for the DejaVu proprietary fonts",
  83 	)
  84 
  85 	microsoftDir = flag.String(
  86 		"microsoftDir",
  87 		"/usr/share/fonts/truetype/msttcorefonts",
  88 		"directory name for the Microsoft proprietary fonts",
  89 	)
  90 
  91 	notoDir = flag.String(
  92 		"notoDir",
  93 		// Get the fonts from https://www.google.com/get/noto/
  94 		"",
  95 		"directory name for the Noto proprietary fonts",
  96 	)
  97 )
  98 
  99 func TestProprietaryAdobeSourceCodeProRegularOTF(t *testing.T) {
 100 	testProprietary(t, "adobe", "SourceCodePro-Regular.otf", 1500, -1)
 101 }
 102 
 103 func TestProprietaryAdobeSourceCodeProRegularTTF(t *testing.T) {
 104 	testProprietary(t, "adobe", "SourceCodePro-Regular.ttf", 1500, -1)
 105 }
 106 
 107 func TestProprietaryAdobeSourceHanSansSCRegularOTF(t *testing.T) {
 108 	testProprietary(t, "adobe", "SourceHanSansSC-Regular.otf", 65535, -1)
 109 }
 110 
 111 func TestProprietaryAdobeSourceSansProBlackOTF(t *testing.T) {
 112 	testProprietary(t, "adobe", "SourceSansPro-Black.otf", 1900, -1)
 113 }
 114 
 115 func TestProprietaryAdobeSourceSansProBlackTTF(t *testing.T) {
 116 	testProprietary(t, "adobe", "SourceSansPro-Black.ttf", 1900, -1)
 117 }
 118 
 119 func TestProprietaryAdobeSourceSansProRegularOTF(t *testing.T) {
 120 	testProprietary(t, "adobe", "SourceSansPro-Regular.otf", 1900, -1)
 121 }
 122 
 123 func TestProprietaryAdobeSourceSansProRegularTTF(t *testing.T) {
 124 	testProprietary(t, "adobe", "SourceSansPro-Regular.ttf", 1900, -1)
 125 }
 126 
 127 func TestProprietaryAppleAppleSymbols(t *testing.T) {
 128 	testProprietary(t, "apple", "Apple Symbols.ttf", 4600, -1)
 129 }
 130 
 131 func TestProprietaryAppleGeezaPro0(t *testing.T) {
 132 	testProprietary(t, "apple", "GeezaPro.ttc?0", 1700, -1)
 133 }
 134 
 135 func TestProprietaryAppleGeezaPro1(t *testing.T) {
 136 	testProprietary(t, "apple", "GeezaPro.ttc?1", 1700, -1)
 137 }
 138 
 139 func TestProprietaryAppleHelvetica0(t *testing.T) {
 140 	testProprietary(t, "apple", "Helvetica.dfont?0", 2100, -1)
 141 }
 142 
 143 func TestProprietaryAppleHelvetica1(t *testing.T) {
 144 	testProprietary(t, "apple", "Helvetica.dfont?1", 2100, -1)
 145 }
 146 
 147 func TestProprietaryAppleHelvetica2(t *testing.T) {
 148 	testProprietary(t, "apple", "Helvetica.dfont?2", 2100, -1)
 149 }
 150 
 151 func TestProprietaryAppleHelvetica3(t *testing.T) {
 152 	testProprietary(t, "apple", "Helvetica.dfont?3", 2100, -1)
 153 }
 154 
 155 func TestProprietaryAppleHelvetica4(t *testing.T) {
 156 	testProprietary(t, "apple", "Helvetica.dfont?4", 1300, -1)
 157 }
 158 
 159 func TestProprietaryAppleHelvetica5(t *testing.T) {
 160 	testProprietary(t, "apple", "Helvetica.dfont?5", 1300, -1)
 161 }
 162 
 163 func TestProprietaryAppleHiragino0(t *testing.T) {
 164 	testProprietary(t, "apple", "ヒラギノ角ゴシック W0.ttc?0", 9000, -1)
 165 }
 166 
 167 func TestProprietaryAppleHiragino1(t *testing.T) {
 168 	testProprietary(t, "apple", "ヒラギノ角ゴシック W0.ttc?1", 9000, -1)
 169 }
 170 
 171 func TestProprietaryDejaVuSans(t *testing.T) {
 172 	testProprietary(t, "dejavu", "DejaVuSans.ttf", 3300, -1)
 173 }
 174 
 175 func TestProprietaryDejaVuSansExtraLight(t *testing.T) {
 176 	testProprietary(t, "dejavu", "DejaVuSans-ExtraLight.ttf", 2000, -1)
 177 }
 178 
 179 func TestProprietaryDejaVuSansMono(t *testing.T) {
 180 	testProprietary(t, "dejavu", "DejaVuSansMono.ttf", 3300, -1)
 181 }
 182 
 183 func TestProprietaryDejaVuSerif(t *testing.T) {
 184 	testProprietary(t, "dejavu", "DejaVuSerif.ttf", 3500, -1)
 185 }
 186 
 187 func TestProprietaryMicrosoftArial(t *testing.T) {
 188 	testProprietary(t, "microsoft", "Arial.ttf", 1200, -1)
 189 }
 190 
 191 func TestProprietaryMicrosoftArialAsACollection(t *testing.T) {
 192 	testProprietary(t, "microsoft", "Arial.ttf?0", 1200, -1)
 193 }
 194 
 195 func TestProprietaryMicrosoftComicSansMS(t *testing.T) {
 196 	testProprietary(t, "microsoft", "Comic_Sans_MS.ttf", 550, -1)
 197 }
 198 
 199 func TestProprietaryMicrosoftTimesNewRoman(t *testing.T) {
 200 	testProprietary(t, "microsoft", "Times_New_Roman.ttf", 1200, -1)
 201 }
 202 
 203 func TestProprietaryMicrosoftWebdings(t *testing.T) {
 204 	testProprietary(t, "microsoft", "Webdings.ttf", 200, -1)
 205 }
 206 
 207 func TestProprietaryNotoColorEmoji(t *testing.T) {
 208 	testProprietary(t, "noto", "NotoColorEmoji.ttf", 2300, -1)
 209 }
 210 
 211 func TestProprietaryNotoSansRegular(t *testing.T) {
 212 	testProprietary(t, "noto", "NotoSans-Regular.ttf", 2400, -1)
 213 }
 214 
 215 // testProprietary tests that we can load every glyph in the named font.
 216 //
 217 // The exact number of glyphs in the font can differ across its various
 218 // versions, but as a sanity check, there should be at least minNumGlyphs.
 219 //
 220 // While this package is a work-in-progress, not every glyph can be loaded. The
 221 // firstUnsupportedGlyph argument, if non-negative, is the index of the first
 222 // unsupported glyph in the font. This number should increase over time (or set
 223 // negative), as the TODO's in this package are done.
 224 func testProprietary(t *testing.T, proprietor, filename string, minNumGlyphs, firstUnsupportedGlyph int) {
 225 	if !*proprietary {
 226 		t.Skip("skipping proprietary font test")
 227 	}
 228 
 229 	basename, fontIndex, err := filename, -1, error(nil)
 230 	if i := strings.IndexByte(filename, '?'); i >= 0 {
 231 		fontIndex, err = strconv.Atoi(filename[i+1:])
 232 		if err != nil {
 233 			t.Fatalf("could not parse collection font index from filename %q", filename)
 234 		}
 235 		basename = filename[:i]
 236 	}
 237 
 238 	dir := ""
 239 	switch proprietor {
 240 	case "adobe":
 241 		dir = *adobeDir
 242 	case "apple":
 243 		dir = *appleDir
 244 	case "dejavu":
 245 		dir = *dejavuDir
 246 	case "microsoft":
 247 		dir = *microsoftDir
 248 	case "noto":
 249 		dir = *notoDir
 250 	default:
 251 		panic("unreachable")
 252 	}
 253 	file, err := ioutil.ReadFile(filepath.Join(dir, basename))
 254 	if err != nil {
 255 		t.Fatalf("%v\nPerhaps you need to set the -%sDir flag?", err, proprietor)
 256 	}
 257 	qualifiedFilename := proprietor + "/" + filename
 258 
 259 	f := (*Font)(nil)
 260 	if fontIndex >= 0 {
 261 		c, err := ParseCollection(file)
 262 		if err != nil {
 263 			t.Fatalf("ParseCollection: %v", err)
 264 		}
 265 		if want, ok := proprietaryNumFonts[qualifiedFilename]; ok {
 266 			if got := c.NumFonts(); got != want {
 267 				t.Fatalf("NumFonts: got %d, want %d", got, want)
 268 			}
 269 		}
 270 		f, err = c.Font(fontIndex)
 271 		if err != nil {
 272 			t.Fatalf("Font: %v", err)
 273 		}
 274 	} else {
 275 		f, err = Parse(file)
 276 		if err != nil {
 277 			t.Fatalf("Parse: %v", err)
 278 		}
 279 	}
 280 
 281 	ppem := fixed.Int26_6(f.UnitsPerEm())
 282 	var buf Buffer
 283 
 284 	// Some of the tests below, such as which glyph index a particular rune
 285 	// maps to, can depend on the specific version of the proprietary font. If
 286 	// tested against a different version of that font, the test might (but not
 287 	// necessarily will) fail, even though the Go code is good. If so, log a
 288 	// message, but don't automatically fail (i.e. dont' call t.Fatalf).
 289 	gotVersion, err := f.Name(&buf, NameIDVersion)
 290 	if err != nil {
 291 		t.Fatalf("Name(Version): %v", err)
 292 	}
 293 	wantVersion := proprietaryVersions[qualifiedFilename]
 294 	if gotVersion != wantVersion {
 295 		t.Logf("font version provided differs from the one the tests were written against:"+
 296 			"\ngot  %q\nwant %q", gotVersion, wantVersion)
 297 	}
 298 
 299 	gotFull, err := f.Name(&buf, NameIDFull)
 300 	if err != nil {
 301 		t.Fatalf("Name(Full): %v", err)
 302 	}
 303 	wantFull := proprietaryFullNames[qualifiedFilename]
 304 	if gotFull != wantFull {
 305 		t.Fatalf("Name(Full):\ngot  %q\nwant %q", gotFull, wantFull)
 306 	}
 307 
 308 	numGlyphs := f.NumGlyphs()
 309 	if numGlyphs < minNumGlyphs {
 310 		t.Fatalf("NumGlyphs: got %d, want at least %d", numGlyphs, minNumGlyphs)
 311 	}
 312 
 313 	iMax := numGlyphs
 314 	if firstUnsupportedGlyph >= 0 {
 315 		iMax = firstUnsupportedGlyph
 316 	}
 317 	for i, numErrors := 0, 0; i < iMax; i++ {
 318 		if _, err := f.LoadGlyph(&buf, GlyphIndex(i), ppem, nil); err != nil && err != ErrColoredGlyph {
 319 			t.Errorf("LoadGlyph(%d): %v", i, err)
 320 			numErrors++
 321 		}
 322 		if numErrors == 10 {
 323 			t.Fatal("LoadGlyph: too many errors")
 324 		}
 325 	}
 326 
 327 	for r, want := range proprietaryGlyphIndexTestCases[qualifiedFilename] {
 328 		got, err := f.GlyphIndex(&buf, r)
 329 		if err != nil {
 330 			t.Errorf("GlyphIndex(%q): %v", r, err)
 331 			continue
 332 		}
 333 		if got != want {
 334 			t.Errorf("GlyphIndex(%q): got %d, want %d", r, got, want)
 335 			continue
 336 		}
 337 	}
 338 
 339 	for r, want := range proprietaryGlyphTestCases[qualifiedFilename] {
 340 		x, err := f.GlyphIndex(&buf, r)
 341 		if err != nil {
 342 			t.Errorf("GlyphIndex(%q): %v", r, err)
 343 			continue
 344 		}
 345 		got, err := f.LoadGlyph(&buf, x, ppem, nil)
 346 		if err != nil {
 347 			t.Errorf("LoadGlyph(%q): %v", r, err)
 348 			continue
 349 		}
 350 		if err := checkSegmentsEqual(got, want); err != nil {
 351 			t.Errorf("LoadGlyph(%q): %v", r, err)
 352 			continue
 353 		}
 354 	}
 355 
 356 	for r, tc := range proprietaryGlyphBoundsTestCases[qualifiedFilename] {
 357 		ppem := fixed.Int26_6(f.UnitsPerEm())
 358 		x, err := f.GlyphIndex(&buf, r)
 359 		if err != nil {
 360 			t.Errorf("GlyphIndex(%q): %v", r, err)
 361 			continue
 362 		}
 363 		gotBounds, gotAdv, err := f.GlyphBounds(&buf, x, ppem, font.HintingNone)
 364 		if err != nil {
 365 			t.Errorf("GlyphBounds(%q): %v", r, err)
 366 			continue
 367 		}
 368 		if gotBounds != tc.wantBounds {
 369 			t.Errorf("GlyphBounds(%q): got %#v, want %#v", r, gotBounds, tc.wantBounds)
 370 		}
 371 		if gotAdv != tc.wantAdv {
 372 			t.Errorf("GlyphBounds(%q): got %#v, want %#v", r, gotAdv, tc.wantAdv)
 373 		}
 374 	}
 375 
 376 kernLoop:
 377 	for _, tc := range proprietaryKernTestCases[qualifiedFilename] {
 378 		var indexes [2]GlyphIndex
 379 		for i := range indexes {
 380 			x, err := f.GlyphIndex(&buf, tc.runes[i])
 381 			if x == 0 && err == nil {
 382 				err = errors.New("no glyph index found")
 383 			}
 384 			if err != nil {
 385 				t.Errorf("GlyphIndex(%q): %v", tc.runes[0], err)
 386 				continue kernLoop
 387 			}
 388 			indexes[i] = x
 389 		}
 390 		kern, err := f.Kern(&buf, indexes[0], indexes[1], tc.ppem, tc.hinting)
 391 		if err != nil {
 392 			t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): %v",
 393 				tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, err)
 394 			continue
 395 		}
 396 		if got := Units(kern); got != tc.want {
 397 			t.Errorf("Kern(%q, %q, ppem=%d, hinting=%v): got %d, want %d",
 398 				tc.runes[0], tc.runes[1], tc.ppem, tc.hinting, got, tc.want)
 399 			continue
 400 		}
 401 	}
 402 
 403 	for x, want := range proprietaryFDSelectTestCases[qualifiedFilename] {
 404 		got, err := f.cached.glyphData.fdSelect.lookup(f, &buf, x)
 405 		if err != nil {
 406 			t.Errorf("fdSelect.lookup(%d): %v", x, err)
 407 			continue
 408 		}
 409 		if got != want {
 410 			t.Errorf("fdSelect.lookup(%d): got %d, want %d", x, got, want)
 411 			continue
 412 		}
 413 	}
 414 }
 415 
 416 // proprietaryNumFonts holds the expected number of fonts in each collection,
 417 // or 1 for a single font. It is not necessarily an exhaustive list of all
 418 // proprietary fonts tested.
 419 var proprietaryNumFonts = map[string]int{
 420 	"apple/Helvetica.dfont?0":    6,
 421 	"apple/ヒラギノ角ゴシック W0.ttc?0": 2,
 422 	"microsoft/Arial.ttf?0":      1,
 423 }
 424 
 425 // proprietaryVersions holds the expected version string of each proprietary
 426 // font tested. If third parties such as Adobe or Microsoft update their fonts,
 427 // and the tests subsequently fail, these versions should be updated too.
 428 //
 429 // Updates are expected to be infrequent. For example, as of 2017, the fonts
 430 // installed by the Debian ttf-mscorefonts-installer package have last modified
 431 // times no later than 2001.
 432 var proprietaryVersions = map[string]string{
 433 	"adobe/SourceCodePro-Regular.otf":   "Version 2.030;PS 1.0;hotconv 16.6.51;makeotf.lib2.5.65220",
 434 	"adobe/SourceCodePro-Regular.ttf":   "Version 2.030;PS 1.000;hotconv 16.6.51;makeotf.lib2.5.65220",
 435 	"adobe/SourceHanSansSC-Regular.otf": "Version 1.004;PS 1.004;hotconv 1.0.82;makeotf.lib2.5.63406",
 436 	"adobe/SourceSansPro-Black.otf":     "Version 2.020;PS 2.0;hotconv 1.0.86;makeotf.lib2.5.63406",
 437 	"adobe/SourceSansPro-Black.ttf":     "Version 2.020;PS 2.000;hotconv 1.0.86;makeotf.lib2.5.63406",
 438 	"adobe/SourceSansPro-Regular.otf":   "Version 2.020;PS 2.0;hotconv 1.0.86;makeotf.lib2.5.63406",
 439 	"adobe/SourceSansPro-Regular.ttf":   "Version 2.020;PS 2.000;hotconv 1.0.86;makeotf.lib2.5.63406",
 440 
 441 	"apple/Apple Symbols.ttf":    "12.0d3e10",
 442 	"apple/GeezaPro.ttc?0":       "12.0d1e3",
 443 	"apple/GeezaPro.ttc?1":       "12.0d1e3",
 444 	"apple/Helvetica.dfont?0":    "12.0d1e3",
 445 	"apple/Helvetica.dfont?1":    "12.0d1e3",
 446 	"apple/Helvetica.dfont?2":    "12.0d1e3",
 447 	"apple/Helvetica.dfont?3":    "12.0d1e3",
 448 	"apple/Helvetica.dfont?4":    "12.0d1e3",
 449 	"apple/Helvetica.dfont?5":    "12.0d1e3",
 450 	"apple/ヒラギノ角ゴシック W0.ttc?0": "11.0d7e1",
 451 	"apple/ヒラギノ角ゴシック W0.ttc?1": "11.0d7e1",
 452 
 453 	"dejavu/DejaVuSans-ExtraLight.ttf": "Version 2.37",
 454 	"dejavu/DejaVuSans.ttf":            "Version 2.37",
 455 	"dejavu/DejaVuSansMono.ttf":        "Version 2.37",
 456 	"dejavu/DejaVuSerif.ttf":           "Version 2.37",
 457 
 458 	"microsoft/Arial.ttf":           "Version 2.82",
 459 	"microsoft/Arial.ttf?0":         "Version 2.82",
 460 	"microsoft/Comic_Sans_MS.ttf":   "Version 2.10",
 461 	"microsoft/Times_New_Roman.ttf": "Version 2.82",
 462 	"microsoft/Webdings.ttf":        "Version 1.03",
 463 
 464 	"noto/NotoColorEmoji.ttf":   "Version 1.33",
 465 	"noto/NotoSans-Regular.ttf": "Version 1.06",
 466 }
 467 
 468 // proprietaryFullNames holds the expected full name of each proprietary font
 469 // tested.
 470 var proprietaryFullNames = map[string]string{
 471 	"adobe/SourceCodePro-Regular.otf":   "Source Code Pro",
 472 	"adobe/SourceCodePro-Regular.ttf":   "Source Code Pro",
 473 	"adobe/SourceHanSansSC-Regular.otf": "Source Han Sans SC Regular",
 474 	"adobe/SourceSansPro-Black.otf":     "Source Sans Pro Black",
 475 	"adobe/SourceSansPro-Black.ttf":     "Source Sans Pro Black",
 476 	"adobe/SourceSansPro-Regular.otf":   "Source Sans Pro",
 477 	"adobe/SourceSansPro-Regular.ttf":   "Source Sans Pro",
 478 
 479 	"apple/Apple Symbols.ttf":    "Apple Symbols",
 480 	"apple/GeezaPro.ttc?0":       "Geeza Pro Regular",
 481 	"apple/GeezaPro.ttc?1":       "Geeza Pro Bold",
 482 	"apple/Helvetica.dfont?0":    "Helvetica",
 483 	"apple/Helvetica.dfont?1":    "Helvetica Bold",
 484 	"apple/Helvetica.dfont?2":    "Helvetica Oblique",
 485 	"apple/Helvetica.dfont?3":    "Helvetica Bold Oblique",
 486 	"apple/Helvetica.dfont?4":    "Helvetica Light",
 487 	"apple/Helvetica.dfont?5":    "Helvetica Light Oblique",
 488 	"apple/ヒラギノ角ゴシック W0.ttc?0": "Hiragino Sans W0",
 489 	"apple/ヒラギノ角ゴシック W0.ttc?1": ".Hiragino Kaku Gothic Interface W0",
 490 
 491 	"dejavu/DejaVuSans-ExtraLight.ttf": "DejaVu Sans ExtraLight",
 492 	"dejavu/DejaVuSans.ttf":            "DejaVu Sans",
 493 	"dejavu/DejaVuSansMono.ttf":        "DejaVu Sans Mono",
 494 	"dejavu/DejaVuSerif.ttf":           "DejaVu Serif",
 495 
 496 	"microsoft/Arial.ttf":           "Arial",
 497 	"microsoft/Arial.ttf?0":         "Arial",
 498 	"microsoft/Comic_Sans_MS.ttf":   "Comic Sans MS",
 499 	"microsoft/Times_New_Roman.ttf": "Times New Roman",
 500 	"microsoft/Webdings.ttf":        "Webdings",
 501 
 502 	"noto/NotoColorEmoji.ttf":   "Noto Color Emoji",
 503 	"noto/NotoSans-Regular.ttf": "Noto Sans",
 504 }
 505 
 506 // proprietaryGlyphIndexTestCases hold a sample of each font's rune to glyph
 507 // index cmap. The numerical values can be verified by running the ttx tool.
 508 var proprietaryGlyphIndexTestCases = map[string]map[rune]GlyphIndex{
 509 	"adobe/SourceCodePro-Regular.otf": {
 510 		'\u0030':     877,  // U+0030 DIGIT ZERO
 511 		'\u0041':     2,    // U+0041 LATIN CAPITAL LETTER A
 512 		'\u0061':     28,   // U+0061 LATIN SMALL LETTER A
 513 		'\u0104':     64,   // U+0104 LATIN CAPITAL LETTER A WITH OGONEK
 514 		'\u0125':     323,  // U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX
 515 		'\u01f4':     111,  // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
 516 		'\u03a3':     623,  // U+03A3 GREEK CAPITAL LETTER SIGMA
 517 		'\u2569':     1500, // U+2569 BOX DRAWINGS DOUBLE UP AND HORIZONTAL
 518 		'\U0001f100': 0,    // U+0001F100 DIGIT ZERO FULL STOP
 519 	},
 520 	"adobe/SourceCodePro-Regular.ttf": {
 521 		'\u0030': 877, // U+0030 DIGIT ZERO
 522 		'\u0041': 2,   // U+0041 LATIN CAPITAL LETTER A
 523 		'\u01f4': 111, // U+01F4 LATIN CAPITAL LETTER G WITH ACUTE
 524 	},
 525 	"adobe/SourceHanSansSC-Regular.otf": {
 526 		'\u0030':     17,    // U+0030 DIGIT ZERO
 527 		'\u0041':     34,    // U+0041 LATIN CAPITAL LETTER A
 528 		'\u00d7':     150,   // U+00D7 MULTIPLICATION SIGN
 529 		'\u1100':     365,   // U+1100 HANGUL CHOSEONG KIYEOK
 530 		'\u25ca':     1254,  // U+25CA LOZENGE
 531 		'\u2e9c':     1359,  // U+2E9C CJK RADICAL SUN
 532 		'\u304b':     1463,  // U+304B HIRAGANA LETTER KA
 533 		'\u4e2d':     9893,  // U+4E2D <CJK Ideograph>, 中
 534 		'\ua960':     47537, // U+A960 HANGUL CHOSEONG TIKEUT-MIEUM
 535 		'\ufb00':     58919, // U+FB00 LATIN SMALL LIGATURE FF
 536 		'\uffee':     59213, // U+FFEE HALFWIDTH WHITE CIRCLE
 537 		'\U0001f100': 59214, // U+0001F100 DIGIT ZERO FULL STOP
 538 		'\U0001f248': 59449, // U+0001F248 TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
 539 		'\U0002f9f4': 61768, // U+0002F9F4 CJK COMPATIBILITY IDEOGRAPH-2F9F4
 540 	},
 541 	"adobe/SourceSansPro-Regular.otf": {
 542 		'\u0041': 2,    // U+0041 LATIN CAPITAL LETTER A
 543 		'\u03a3': 592,  // U+03A3 GREEK CAPITAL LETTER SIGMA
 544 		'\u0435': 999,  // U+0435 CYRILLIC SMALL LETTER IE
 545 		'\u2030': 1728, // U+2030 PER MILLE SIGN
 546 	},
 547 	"adobe/SourceSansPro-Regular.ttf": {
 548 		'\u0041': 2,    // U+0041 LATIN CAPITAL LETTER A
 549 		'\u03a3': 592,  // U+03A3 GREEK CAPITAL LETTER SIGMA
 550 		'\u0435': 999,  // U+0435 CYRILLIC SMALL LETTER IE
 551 		'\u2030': 1728, // U+2030 PER MILLE SIGN
 552 	},
 553 
 554 	"apple/Helvetica.dfont?0": {
 555 		'\u0041':     36,   // U+0041 LATIN CAPITAL LETTER A
 556 		'\u00f1':     120,  // U+00F1 LATIN SMALL LETTER N WITH TILDE
 557 		'\u0401':     473,  // U+0401 CYRILLIC CAPITAL LETTER IO
 558 		'\u200d':     611,  // U+200D ZERO WIDTH JOINER
 559 		'\u20ab':     1743, // U+20AB DONG SIGN
 560 		'\u2229':     0,    // U+2229 INTERSECTION
 561 		'\u04e9':     1208, // U+04E9 CYRILLIC SMALL LETTER BARRED O
 562 		'\U0001f100': 0,    // U+0001F100 DIGIT ZERO FULL STOP
 563 	},
 564 
 565 	"dejavu/DejaVuSerif.ttf": {
 566 		'\u0041': 36,   // U+0041 LATIN CAPITAL LETTER A
 567 		'\u1e00': 1418, // U+1E00 LATIN CAPITAL LETTER A WITH RING BELOW
 568 	},
 569 
 570 	"microsoft/Arial.ttf": {
 571 		'\u0041':     36,   // U+0041 LATIN CAPITAL LETTER A
 572 		'\u00f1':     120,  // U+00F1 LATIN SMALL LETTER N WITH TILDE
 573 		'\u0401':     556,  // U+0401 CYRILLIC CAPITAL LETTER IO
 574 		'\u200d':     745,  // U+200D ZERO WIDTH JOINER
 575 		'\u20ab':     1150, // U+20AB DONG SIGN
 576 		'\u2229':     320,  // U+2229 INTERSECTION
 577 		'\u04e9':     1319, // U+04E9 CYRILLIC SMALL LETTER BARRED O
 578 		'\U0001f100': 0,    // U+0001F100 DIGIT ZERO FULL STOP
 579 	},
 580 	"microsoft/Comic_Sans_MS.ttf": {
 581 		'\u0041': 36,  // U+0041 LATIN CAPITAL LETTER A
 582 		'\u03af': 573, // U+03AF GREEK SMALL LETTER IOTA WITH TONOS
 583 	},
 584 	"microsoft/Times_New_Roman.ttf": {
 585 		'\u0041': 36,  // U+0041 LATIN CAPITAL LETTER A
 586 		'\u0042': 37,  // U+0041 LATIN CAPITAL LETTER B
 587 		'\u266a': 392, // U+266A EIGHTH NOTE
 588 		'\uf041': 0,   // PRIVATE USE AREA
 589 		'\uf042': 0,   // PRIVATE USE AREA
 590 	},
 591 	"microsoft/Webdings.ttf": {
 592 		'\u0041': 0,  // U+0041 LATIN CAPITAL LETTER A
 593 		'\u0042': 0,  // U+0041 LATIN CAPITAL LETTER B
 594 		'\u266a': 0,  // U+266A EIGHTH NOTE
 595 		'\uf041': 36, // PRIVATE USE AREA
 596 		'\uf042': 37, // PRIVATE USE AREA
 597 	},
 598 }
 599 
 600 // proprietaryGlyphTestCases hold a sample of each font's glyph vectors. The
 601 // numerical values can be verified by running the ttx tool, remembering that:
 602 //   - for PostScript glyphs, ttx coordinates are relative.
 603 //   - for TrueType glyphs, ttx coordinates are absolute, and consecutive
 604 //     off-curve points implies an on-curve point at the midpoint.
 605 var proprietaryGlyphTestCases = map[string]map[rune][]Segment{
 606 	"adobe/SourceHanSansSC-Regular.otf": {
 607 		'!': {
 608 			// -312 123 callsubr # 123 + bias = 230
 609 			// :	# Arg stack is [-312].
 610 			// :	-13 140 -119 -21 return
 611 			// :	# Arg stack is [-312 -13 140 -119 -21].
 612 			// 120 callsubr # 120 + bias = 227
 613 			// :	# Arg stack is [-312 -13 140 -119 -21].
 614 			// :	hstemhm
 615 			// :	95 132 -103 75 return
 616 			// :	# Arg stack is [95 132 -103 75].
 617 			// hintmask 01010000
 618 			// 8 callsubr # 8 + bias = 115
 619 			// :	# Arg stack is [].
 620 			// :	130 221 rmoveto
 621 			moveTo(130, 221),
 622 			// :	63 hlineto
 623 			lineTo(193, 221),
 624 			// :	12 424 3 -735 callgsubr # -735 + bias = 396
 625 			// :	:	# Arg stack is [12 424 3].
 626 			// :	:	104 rlineto
 627 			lineTo(205, 645),
 628 			lineTo(208, 749),
 629 			// :	:	-93 hlineto
 630 			lineTo(115, 749),
 631 			// :	:	3 -104 rlineto
 632 			lineTo(118, 645),
 633 			// :	:	return
 634 			// :	:	# Arg stack is [].
 635 			// :	return
 636 			// :	# Arg stack is [].
 637 			// hintmask 01100000
 638 			// 106 callsubr # 106 + bias = 213
 639 			// :	# Arg stack is [].
 640 			// :	43 -658 rmoveto
 641 			lineTo(130, 221),
 642 			moveTo(161, -13),
 643 			// :	37 29 28 41 return
 644 			// :	# Arg stack is [37 29 28 41].
 645 			// hvcurveto
 646 			cubeTo(198, -13, 227, 15, 227, 56),
 647 			// hintmask 10100000
 648 			// 41 -29 30 -37 -36 -30 -30 -41 vhcurveto
 649 			cubeTo(227, 97, 198, 127, 161, 127),
 650 			cubeTo(125, 127, 95, 97, 95, 56),
 651 			// hintmask 01100000
 652 			// 111 callsubr # 111 + bias = 218
 653 			// :	# Arg stack is [].
 654 			// :	-41 30 -28 36 vhcurveto
 655 			cubeTo(95, 15, 125, -13, 161, -13),
 656 			// :	endchar
 657 		},
 658 
 659 		'二': { // U+4E8C <CJK Ideograph> "two; twice"
 660 			// 23 81 510 79 hstem
 661 			// 60 881 cntrmask 11000000
 662 			// 144 693 rmoveto
 663 			moveTo(144, 693),
 664 			// -79 713 79 vlineto
 665 			lineTo(144, 614),
 666 			lineTo(857, 614),
 667 			lineTo(857, 693),
 668 			// -797 -589 rmoveto
 669 			lineTo(144, 693),
 670 			moveTo(60, 104),
 671 			// -81 881 81 vlineto
 672 			lineTo(60, 23),
 673 			lineTo(941, 23),
 674 			lineTo(941, 104),
 675 			// endchar
 676 			lineTo(60, 104),
 677 		},
 678 	},
 679 
 680 	"adobe/SourceSansPro-Black.otf": {
 681 		'¤': { // U+00A4 CURRENCY SIGN
 682 			// -45 147 99 168 98 hstem
 683 			// 44 152 148 152 vstem
 684 			// 102 76 rmoveto
 685 			moveTo(102, 76),
 686 			// 71 71 rlineto
 687 			lineTo(173, 147),
 688 			// 31 -13 33 -6 33 32 34 6 31 hflex1
 689 			cubeTo(204, 134, 237, 128, 270, 128),
 690 			cubeTo(302, 128, 336, 134, 367, 147),
 691 			// 71 -71 85 85 -61 60 rlineto
 692 			lineTo(438, 76),
 693 			lineTo(523, 161),
 694 			lineTo(462, 221),
 695 			// 21 30 13 36 43 vvcurveto
 696 			cubeTo(483, 251, 496, 287, 496, 330),
 697 			// 42 -12 36 -21 29 vhcurveto
 698 			cubeTo(496, 372, 484, 408, 463, 437),
 699 			// 60 60 -85 85 -70 -70 rlineto
 700 			lineTo(523, 497),
 701 			lineTo(438, 582),
 702 			lineTo(368, 512),
 703 			// -31 13 -34 7 -33 -33 -34 -7 -31 hflex1
 704 			cubeTo(337, 525, 303, 532, 270, 532),
 705 			cubeTo(237, 532, 203, 525, 172, 512),
 706 			// -70 70 -85 -85 59 -60 rlineto
 707 			lineTo(102, 582),
 708 			lineTo(17, 497),
 709 			lineTo(76, 437),
 710 			// -20 -29 -12 -36 -42 vvcurveto
 711 			cubeTo(56, 408, 44, 372, 44, 330),
 712 			// -43 12 -36 21 -30 vhcurveto
 713 			cubeTo(44, 287, 56, 251, 77, 221),
 714 			// -60 -60 rlineto
 715 			lineTo(17, 161),
 716 			// 253 85 rmoveto
 717 			lineTo(102, 76),
 718 			moveTo(270, 246),
 719 			// -42 -32 32 52 52 32 32 42 42 32 -32 -52 -52 -32 -32 -42 hvcurveto
 720 			cubeTo(228, 246, 196, 278, 196, 330),
 721 			cubeTo(196, 382, 228, 414, 270, 414),
 722 			cubeTo(312, 414, 344, 382, 344, 330),
 723 			cubeTo(344, 278, 312, 246, 270, 246),
 724 			// endchar
 725 		},
 726 	},
 727 
 728 	"adobe/SourceSansPro-Regular.otf": {
 729 		',': {
 730 			// -309 -1 115 hstem
 731 			// 137 61 vstem
 732 			// 67 -170 rmoveto
 733 			moveTo(67, -170),
 734 			// 81 34 50 67 86 vvcurveto
 735 			cubeTo(148, -136, 198, -69, 198, 17),
 736 			// 60 -26 37 -43 -33 -28 -22 -36 -37 27 -20 32 3 4 0 1 3 vhcurveto
 737 			cubeTo(198, 77, 172, 114, 129, 114),
 738 			cubeTo(96, 114, 68, 92, 68, 56),
 739 			cubeTo(68, 19, 95, -1, 127, -1),
 740 			cubeTo(130, -1, 134, -1, 137, 0),
 741 			// 1 -53 -34 -44 -57 -25 rrcurveto
 742 			cubeTo(138, -53, 104, -97, 47, -122),
 743 			// endchar
 744 			lineTo(67, -170),
 745 		},
 746 
 747 		'Q': {
 748 			// 106 -165 70 87 65 538 73 hstem
 749 			// 52 86 388 87 vstem
 750 			// 332 57 rmoveto
 751 			moveTo(332, 57),
 752 			// -117 -77 106 168 163 77 101 117 117 77 -101 -163 -168 -77 -106 -117 hvcurveto
 753 			cubeTo(215, 57, 138, 163, 138, 331),
 754 			cubeTo(138, 494, 215, 595, 332, 595),
 755 			cubeTo(449, 595, 526, 494, 526, 331),
 756 			cubeTo(526, 163, 449, 57, 332, 57),
 757 			// 201 -222 rmoveto
 758 			moveTo(533, -165),
 759 			// 39 35 7 8 20 hvcurveto
 760 			cubeTo(572, -165, 607, -158, 627, -150),
 761 			// -16 64 rlineto
 762 			lineTo(611, -86),
 763 			// -5 -18 -22 -4 -29 hhcurveto
 764 			cubeTo(593, -91, 571, -95, 542, -95),
 765 			// -71 -60 29 58 -30 hvcurveto
 766 			cubeTo(471, -95, 411, -66, 381, -8),
 767 			// 139 24 93 126 189 vvcurveto
 768 			cubeTo(520, 16, 613, 142, 613, 331),
 769 			// 209 -116 128 -165 -165 -115 -127 -210 -193 96 -127 143 -20 vhcurveto
 770 			cubeTo(613, 540, 497, 668, 332, 668),
 771 			cubeTo(167, 668, 52, 541, 52, 331),
 772 			cubeTo(52, 138, 148, 11, 291, -9),
 773 			// -90 38 83 -66 121 hhcurveto
 774 			cubeTo(329, -99, 412, -165, 533, -165),
 775 			// endchar
 776 		},
 777 
 778 		'ĩ': { // U+0129 LATIN SMALL LETTER I WITH TILDE
 779 			// 92 callgsubr # 92 + bias = 199.
 780 			// :	# Arg stack is [].
 781 			// :	-312 21 85 callgsubr # 85 + bias = 192.
 782 			// :	:	# Arg stack is [-312 21].
 783 			// :	:	-21 486 -20 return
 784 			// :	:	# Arg stack is [-312 21 -21 486 -20].
 785 			// :	return
 786 			// :	# Arg stack is [-312 21 -21 486 -20].
 787 			// 111 45 callsubr # 45 + bias = 152
 788 			// :	# Arg stack is [-312 21 -21 486 -20 111].
 789 			// :	60 24 60 -9 216 callgsubr # 216 + bias = 323
 790 			// :	:	# Arg stack is [-312 21 -21 486 -20 111 60 24 60 -9].
 791 			// :	:	-20 24 -20 hstemhm
 792 			// :	:	return
 793 			// :	:	# Arg stack is [].
 794 			// :	return
 795 			// :	# Arg stack is [].
 796 			// -50 55 77 82 77 55 hintmask 1101000100000000
 797 			// 134 callsubr # 134 + bias = 241
 798 			// :	# Arg stack is [].
 799 			// :	82 hmoveto
 800 			moveTo(82, 0),
 801 			// :	82 127 callsubr # 127 + bias = 234
 802 			// :	:	# Arg stack is [82].
 803 			// :	:	486 -82 hlineto
 804 			lineTo(164, 0),
 805 			lineTo(164, 486),
 806 			lineTo(82, 486),
 807 			// :	:	return
 808 			// :	:	# Arg stack is [].
 809 			// :	return
 810 			// :	# Arg stack is [].
 811 			// hintmask 1110100110000000
 812 			// 113 91 15 callgsubr # 15 + bias = 122
 813 			// :	# Arg stack is [113 91].
 814 			// :	rmoveto
 815 			lineTo(82, 0),
 816 			moveTo(195, 577),
 817 			// :	69 29 58 77 3 hvcurveto
 818 			cubeTo(264, 577, 293, 635, 296, 712),
 819 			// :	return
 820 			// :	# Arg stack is [].
 821 			// hintmask 1110010110000000
 822 			// -58 callsubr # -58 + bias = 49
 823 			// :	# Arg stack is [].
 824 			// :	-55 4 rlineto
 825 			lineTo(241, 716),
 826 			// :	-46 -3 -14 -33 -29 -47 -26 84 -71 hhcurveto
 827 			cubeTo(238, 670, 224, 637, 195, 637),
 828 			cubeTo(148, 637, 122, 721, 51, 721),
 829 			// :	return
 830 			// :	# Arg stack is [].
 831 			// hintmask 1101001100000000
 832 			// -70 callgsubr # -70 + bias = 37
 833 			// :	# Arg stack is [].
 834 			// :	-69 -29 -58 -78 -3 hvcurveto
 835 			cubeTo(-18, 721, -47, 663, -50, 585),
 836 			// :	55 -3 rlineto
 837 			lineTo(5, 582),
 838 			// :	47 3 14 32 30 hhcurveto
 839 			cubeTo(8, 629, 22, 661, 52, 661),
 840 			// :	return
 841 			// :	# Arg stack is [].
 842 			// hintmask 1110100110000000
 843 			// 51 callsubr # 51 + bias = 158
 844 			// :	# Arg stack is [].
 845 			// :	46 26 -84 71 hhcurveto
 846 			cubeTo(98, 661, 124, 577, 195, 577),
 847 			// :	endchar
 848 		},
 849 
 850 		'ī': { // U+012B LATIN SMALL LETTER I WITH MACRON
 851 			// 92 callgsubr # 92 + bias = 199.
 852 			// :	# Arg stack is [].
 853 			// :	-312 21 85 callgsubr # 85 + bias = 192.
 854 			// :	:	# Arg stack is [-312 21].
 855 			// :	:	-21 486 -20 return
 856 			// :	:	# Arg stack is [-312 21 -21 486 -20].
 857 			// :	return
 858 			// :	# Arg stack is [-312 21 -21 486 -20].
 859 			// 135 57 112 callgsubr # 112 + bias = 219
 860 			// :	# Arg stack is [-312 21 -21 486 -20 135 57].
 861 			// :	hstem
 862 			// :	82 82 vstem
 863 			// :	134 callsubr # 134 + bias = 241
 864 			// :	:	# Arg stack is [].
 865 			// :	:	82 hmoveto
 866 			moveTo(82, 0),
 867 			// :	:	82 127 callsubr # 127 + bias = 234
 868 			// :	:	:	# Arg stack is [82].
 869 			// :	:	:	486 -82 hlineto
 870 			lineTo(164, 0),
 871 			lineTo(164, 486),
 872 			lineTo(82, 486),
 873 			// :	:	:	return
 874 			// :	:	:	# Arg stack is [].
 875 			// :	:	return
 876 			// :	:	# Arg stack is [].
 877 			// :	return
 878 			// :	# Arg stack is [].
 879 			// -92 115 -60 callgsubr # -60 + bias = 47
 880 			// :	# Arg stack is [-92 115].
 881 			// :	rmoveto
 882 			lineTo(82, 0),
 883 			moveTo(-10, 601),
 884 			// :	266 57 -266 hlineto
 885 			lineTo(256, 601),
 886 			lineTo(256, 658),
 887 			lineTo(-10, 658),
 888 			// :	endchar
 889 			lineTo(-10, 601),
 890 		},
 891 
 892 		'ĭ': { // U+012D LATIN SMALL LETTER I WITH BREVE
 893 			// 92 callgsubr # 92 + bias = 199.
 894 			// :	# Arg stack is [].
 895 			// :	-312 21 85 callgsubr # 85 + bias = 192.
 896 			// :	:	# Arg stack is [-312 21].
 897 			// :	:	-21 486 -20 return
 898 			// :	:	# Arg stack is [-312 21 -21 486 -20].
 899 			// :	return
 900 			// :	# Arg stack is [-312 21 -21 486 -20].
 901 			// 105 55 96 -20 hstem
 902 			// -32 51 63 82 65 51 vstem
 903 			// 134 callsubr # 134 + bias = 241
 904 			// :	# Arg stack is [].
 905 			// :	82 hmoveto
 906 			moveTo(82, 0),
 907 			// :	82 127 callsubr # 127 + bias = 234
 908 			// :	:	# Arg stack is [82].
 909 			// :	:	486 -82 hlineto
 910 			lineTo(164, 0),
 911 			lineTo(164, 486),
 912 			lineTo(82, 486),
 913 			// :	:	return
 914 			// :	:	# Arg stack is [].
 915 			// :	return
 916 			// :	# Arg stack is [].
 917 			// 42 85 143 callsubr # 143 + bias = 250
 918 			// :	# Arg stack is [42 85].
 919 			// :	rmoveto
 920 			lineTo(82, 0),
 921 			moveTo(124, 571),
 922 			// :	-84 callsubr # -84 + bias = 23
 923 			// :	:	# Arg stack is [].
 924 			// :	:	107 44 77 74 5 hvcurveto
 925 			cubeTo(231, 571, 275, 648, 280, 722),
 926 			// :	:	-51 8 rlineto
 927 			lineTo(229, 730),
 928 			// :	:	-51 -8 -32 -53 -65 hhcurveto
 929 			cubeTo(221, 679, 189, 626, 124, 626),
 930 			// :	:	-65 -32 53 51 -8 hvcurveto
 931 			cubeTo(59, 626, 27, 679, 19, 730),
 932 			// :	:	-51 -22 callsubr # -22 + bias = 85
 933 			// :	:	:	# Arg stack is [-51].
 934 			// :	:	:	-8 rlineto
 935 			lineTo(-32, 722),
 936 			// :	:	:	-74 5 44 -77 107 hhcurveto
 937 			cubeTo(-27, 648, 17, 571, 124, 571),
 938 			// :	:	:	return
 939 			// :	:	:	# Arg stack is [].
 940 			// :	:	return
 941 			// :	:	# Arg stack is [].
 942 			// :	return
 943 			// :	# Arg stack is [].
 944 			// endchar
 945 		},
 946 
 947 		'Λ': { // U+039B GREEK CAPITAL LETTER LAMDA
 948 			// -43 21 -21 572 84 hstem
 949 			// 0 515 vstem
 950 			// 0 vmoveto
 951 			moveTo(0, 0),
 952 			// 85 hlineto
 953 			lineTo(85, 0),
 954 			// 105 355 23 77 16 63 24 77 rlinecurve
 955 			lineTo(190, 355),
 956 			cubeTo(213, 432, 229, 495, 253, 572),
 957 			// 4 hlineto
 958 			lineTo(257, 572),
 959 			// 25 -77 16 -63 23 -77 106 -355 rcurveline
 960 			cubeTo(282, 495, 298, 432, 321, 355),
 961 			lineTo(427, 0),
 962 			// 88 hlineto
 963 			lineTo(515, 0),
 964 			// -210 656 rlineto
 965 			lineTo(305, 656),
 966 			// -96 hlineto
 967 			lineTo(209, 656),
 968 			// endchar
 969 			lineTo(0, 0),
 970 		},
 971 
 972 		'Ḫ': { // U+1E2A LATIN CAPITAL LETTER H WITH BREVE BELOW
 973 			// 94 -231 55 197 157 callgsubr # 157 + bias = 264
 974 			// :	# Arg stack is [94 -231 55 197].
 975 			// :	-21 309 72 return
 976 			// :	# Arg stack is [94 -231 55 197 -21 309 72].
 977 			// 275 254 callgsubr # 254 + bias = 361
 978 			// :	# Arg stack is [94 -231 55 197 -21 309 72 275].
 979 			// :	-20 hstemhm
 980 			// :	90 83 return
 981 			// :	# Arg stack is [90 83].
 982 			// -4 352 callsubr # 352 + bias = 459
 983 			// :	# Arg stack is [90 83 -4].
 984 			// :	51 210 51 return
 985 			// :	# Arg stack is [90 83 -4 51 210 51].
 986 			// -3 84 hintmask 11111001
 987 			// 90 -40 callsubr # -40 + bias = 67
 988 			// :	# Arg stack is [90].
 989 			// :	-27 callgsubr # -27 + bias = 80
 990 			// :	:	# Arg stack is [90].
 991 			// :	:	hmoveto
 992 			moveTo(90, 0),
 993 			// :	:	83 309 305 -309 84 return
 994 			// :	:	# Arg stack is [83 309 305 -309 84].
 995 			// :	-41 callgsubr # -41 + bias = 66
 996 			// :	:	# Arg stack is [83 309 305 -309 84].
 997 			// :	:	656 -84 -275 -305 275 -83 return
 998 			// :	:	# Arg stack is [83 309 305 -309 84 656 -84 -275 -305 275 -83].
 999 			// :	hlineto
1000 			lineTo(173, 0),
1001 			lineTo(173, 309),
1002 			lineTo(478, 309),
1003 			lineTo(478, 0),
1004 			lineTo(562, 0),
1005 			lineTo(562, 656),
1006 			lineTo(478, 656),
1007 			lineTo(478, 381),
1008 			lineTo(173, 381),
1009 			lineTo(173, 656),
1010 			lineTo(90, 656),
1011 			// :	return
1012 			// :	# Arg stack is [].
1013 			// hintmask 11110110
1014 			// 235 -887 143 callsubr # 143 + bias = 250
1015 			// :	# Arg stack is [235 -887].
1016 			// :	rmoveto
1017 			lineTo(90, 0),
1018 			moveTo(325, -231),
1019 			// :	-84 callsubr # -84 + bias = 23
1020 			// :	:	# Arg stack is [].
1021 			// :	:	107 44 77 74 5 hvcurveto
1022 			cubeTo(432, -231, 476, -154, 481, -80),
1023 			// :	:	-51 8 rlineto
1024 			lineTo(430, -72),
1025 			// :	:	-51 -8 -32 -53 -65 hhcurveto
1026 			cubeTo(422, -123, 390, -176, 325, -176),
1027 			// :	:	-65 -32 53 51 -8 hvcurveto
1028 			cubeTo(260, -176, 228, -123, 220, -72),
1029 			// :	:	-51 -22 callsubr # -22 + bias = 85
1030 			// :	:	:	# Arg stack is [-51].
1031 			// :	:	:	-8 rlineto
1032 			lineTo(169, -80),
1033 			// :	:	:	-74 5 44 -77 107 hhcurveto
1034 			cubeTo(174, -154, 218, -231, 325, -231),
1035 			// :	:	:	return
1036 			// :	:	:	# Arg stack is [].
1037 			// :	:	return
1038 			// :	:	# Arg stack is [].
1039 			// :	return
1040 			// :	# Arg stack is [].
1041 			// endchar
1042 		},
1043 	},
1044 
1045 	"apple/Helvetica.dfont?0": {
1046 		'i': {
1047 			// - contour #0
1048 			moveTo(132, 1066),
1049 			lineTo(315, 1066),
1050 			lineTo(315, 0),
1051 			lineTo(132, 0),
1052 			lineTo(132, 1066),
1053 			// - contour #1
1054 			moveTo(132, 1469),
1055 			lineTo(315, 1469),
1056 			lineTo(315, 1265),
1057 			lineTo(132, 1265),
1058 			lineTo(132, 1469),
1059 		},
1060 	},
1061 
1062 	"apple/Helvetica.dfont?1": {
1063 		'i': {
1064 			// - contour #0
1065 			moveTo(426, 1220),
1066 			lineTo(137, 1220),
1067 			lineTo(137, 1483),
1068 			lineTo(426, 1483),
1069 			lineTo(426, 1220),
1070 			// - contour #1
1071 			moveTo(137, 1090),
1072 			lineTo(426, 1090),
1073 			lineTo(426, 0),
1074 			lineTo(137, 0),
1075 			lineTo(137, 1090),
1076 		},
1077 	},
1078 
1079 	"dejavu/DejaVuSans-ExtraLight.ttf": {
1080 		'i': {
1081 			// - contour #0
1082 			moveTo(230, 1120),
1083 			lineTo(322, 1120),
1084 			lineTo(322, 0),
1085 			lineTo(230, 0),
1086 			lineTo(230, 1120),
1087 			// - contour #1
1088 			moveTo(230, 1556),
1089 			lineTo(322, 1556),
1090 			lineTo(322, 1430),
1091 			lineTo(230, 1430),
1092 			lineTo(230, 1556),
1093 		},
1094 	},
1095 
1096 	"microsoft/Arial.ttf": {
1097 		',': {
1098 			// - contour #0
1099 			moveTo(182, 0),
1100 			lineTo(182, 205),
1101 			lineTo(387, 205),
1102 			lineTo(387, 0),
1103 			quadTo(387, -113, 347, -182),
1104 			quadTo(307, -252, 220, -290),
1105 			lineTo(170, -213),
1106 			quadTo(227, -188, 254, -139),
1107 			quadTo(281, -91, 284, 0),
1108 			lineTo(182, 0),
1109 		},
1110 
1111 		'i': {
1112 			// - contour #0
1113 			moveTo(136, 1259),
1114 			lineTo(136, 1466),
1115 			lineTo(316, 1466),
1116 			lineTo(316, 1259),
1117 			lineTo(136, 1259),
1118 			// - contour #1
1119 			moveTo(136, 0),
1120 			lineTo(136, 1062),
1121 			lineTo(316, 1062),
1122 			lineTo(316, 0),
1123 			lineTo(136, 0),
1124 		},
1125 
1126 		'o': {
1127 			// - contour #0
1128 			moveTo(68, 531),
1129 			quadTo(68, 826, 232, 968),
1130 			quadTo(369, 1086, 566, 1086),
1131 			quadTo(785, 1086, 924, 942),
1132 			quadTo(1063, 799, 1063, 546),
1133 			quadTo(1063, 341, 1001, 223),
1134 			quadTo(940, 106, 822, 41),
1135 			quadTo(705, -24, 566, -24),
1136 			quadTo(343, -24, 205, 119),
1137 			quadTo(68, 262, 68, 531),
1138 			// - contour #1
1139 			moveTo(253, 531),
1140 			quadTo(253, 327, 342, 225),
1141 			quadTo(431, 124, 566, 124),
1142 			quadTo(700, 124, 789, 226),
1143 			quadTo(878, 328, 878, 537),
1144 			quadTo(878, 734, 788, 835),
1145 			quadTo(699, 937, 566, 937),
1146 			quadTo(431, 937, 342, 836),
1147 			quadTo(253, 735, 253, 531),
1148 		},
1149 
1150 		'í': { // U+00ED LATIN SMALL LETTER I WITH ACUTE
1151 			// - contour #0
1152 			translate(0, 0, moveTo(198, 0)),
1153 			translate(0, 0, lineTo(198, 1062)),
1154 			translate(0, 0, lineTo(378, 1062)),
1155 			translate(0, 0, lineTo(378, 0)),
1156 			translate(0, 0, lineTo(198, 0)),
1157 			// - contour #1
1158 			translate(-33, 0, moveTo(222, 1194)),
1159 			translate(-33, 0, lineTo(355, 1474)),
1160 			translate(-33, 0, lineTo(591, 1474)),
1161 			translate(-33, 0, lineTo(371, 1194)),
1162 			translate(-33, 0, lineTo(222, 1194)),
1163 		},
1164 
1165 		'Ī': { // U+012A LATIN CAPITAL LETTER I WITH MACRON
1166 			// - contour #0
1167 			translate(0, 0, moveTo(191, 0)),
1168 			translate(0, 0, lineTo(191, 1466)),
1169 			translate(0, 0, lineTo(385, 1466)),
1170 			translate(0, 0, lineTo(385, 0)),
1171 			translate(0, 0, lineTo(191, 0)),
1172 			// - contour #1
1173 			translate(-57, 336, moveTo(29, 1227)),
1174 			translate(-57, 336, lineTo(29, 1375)),
1175 			translate(-57, 336, lineTo(653, 1375)),
1176 			translate(-57, 336, lineTo(653, 1227)),
1177 			translate(-57, 336, lineTo(29, 1227)),
1178 		},
1179 
1180 		// Ǻ is a compound glyph whose elements are also compound glyphs.
1181 		'Ǻ': { // U+01FA LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
1182 			// - contour #0
1183 			translate(0, 0, moveTo(-3, 0)),
1184 			translate(0, 0, lineTo(560, 1466)),
1185 			translate(0, 0, lineTo(769, 1466)),
1186 			translate(0, 0, lineTo(1369, 0)),
1187 			translate(0, 0, lineTo(1148, 0)),
1188 			translate(0, 0, lineTo(977, 444)),
1189 			translate(0, 0, lineTo(364, 444)),
1190 			translate(0, 0, lineTo(203, 0)),
1191 			translate(0, 0, lineTo(-3, 0)),
1192 			// - contour #1
1193 			translate(0, 0, moveTo(420, 602)),
1194 			translate(0, 0, lineTo(917, 602)),
1195 			translate(0, 0, lineTo(764, 1008)),
1196 			translate(0, 0, quadTo(694, 1193, 660, 1312)),
1197 			translate(0, 0, quadTo(632, 1171, 581, 1032)),
1198 			translate(0, 0, lineTo(420, 602)),
1199 			// - contour #2
1200 			translate(319, 263, moveTo(162, 1338)),
1201 			translate(319, 263, quadTo(162, 1411, 215, 1464)),
1202 			translate(319, 263, quadTo(269, 1517, 342, 1517)),
1203 			translate(319, 263, quadTo(416, 1517, 469, 1463)),
1204 			translate(319, 263, quadTo(522, 1410, 522, 1334)),
1205 			translate(319, 263, quadTo(522, 1257, 469, 1204)),
1206 			translate(319, 263, quadTo(416, 1151, 343, 1151)),
1207 			translate(319, 263, quadTo(268, 1151, 215, 1204)),
1208 			translate(319, 263, quadTo(162, 1258, 162, 1338)),
1209 			// - contour #3
1210 			translate(319, 263, moveTo(238, 1337)),
1211 			translate(319, 263, quadTo(238, 1290, 269, 1258)),
1212 			translate(319, 263, quadTo(301, 1226, 344, 1226)),
1213 			translate(319, 263, quadTo(387, 1226, 418, 1258)),
1214 			translate(319, 263, quadTo(450, 1290, 450, 1335)),
1215 			translate(319, 263, quadTo(450, 1380, 419, 1412)),
1216 			translate(319, 263, quadTo(388, 1444, 344, 1444)),
1217 			translate(319, 263, quadTo(301, 1444, 269, 1412)),
1218 			translate(319, 263, quadTo(238, 1381, 238, 1337)),
1219 			// - contour #4
1220 			translate(339, 650, moveTo(222, 1194)),
1221 			translate(339, 650, lineTo(355, 1474)),
1222 			translate(339, 650, lineTo(591, 1474)),
1223 			translate(339, 650, lineTo(371, 1194)),
1224 			translate(339, 650, lineTo(222, 1194)),
1225 		},
1226 
1227 		'﴾': { // U+FD3E ORNATE LEFT PARENTHESIS.
1228 			// - contour #0
1229 			moveTo(560, -384),
1230 			lineTo(516, -429),
1231 			quadTo(412, -304, 361, -226),
1232 			quadTo(258, -68, 201, 106),
1233 			quadTo(127, 334, 127, 595),
1234 			quadTo(127, 845, 201, 1069),
1235 			quadTo(259, 1246, 361, 1404),
1236 			quadTo(414, 1487, 514, 1608),
1237 			lineTo(560, 1566),
1238 			quadTo(452, 1328, 396, 1094),
1239 			quadTo(336, 845, 336, 603),
1240 			quadTo(336, 359, 370, 165),
1241 			quadTo(398, 8, 454, -142),
1242 			quadTo(482, -217, 560, -384),
1243 		},
1244 
1245 		'﴿': { // U+FD3F ORNATE RIGHT PARENTHESIS
1246 			// - contour #0
1247 			transform(-1<<14, 0, 0, +1<<14, 653, 0, moveTo(560, -384)),
1248 			transform(-1<<14, 0, 0, +1<<14, 653, 0, lineTo(516, -429)),
1249 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(412, -304, 361, -226)),
1250 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(258, -68, 201, 106)),
1251 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(127, 334, 127, 595)),
1252 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(127, 845, 201, 1069)),
1253 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(259, 1246, 361, 1404)),
1254 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(414, 1487, 514, 1608)),
1255 			transform(-1<<14, 0, 0, +1<<14, 653, 0, lineTo(560, 1566)),
1256 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(452, 1328, 396, 1094)),
1257 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(336, 845, 336, 603)),
1258 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(336, 359, 370, 165)),
1259 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(398, 8, 454, -142)),
1260 			transform(-1<<14, 0, 0, +1<<14, 653, 0, quadTo(482, -217, 560, -384)),
1261 		},
1262 	},
1263 
1264 	"noto/NotoSans-Regular.ttf": {
1265 		'i': {
1266 			// - contour #0
1267 			moveTo(354, 0),
1268 			lineTo(174, 0),
1269 			lineTo(174, 1098),
1270 			lineTo(354, 1098),
1271 			lineTo(354, 0),
1272 			// - contour #1
1273 			moveTo(160, 1395),
1274 			quadTo(160, 1455, 190, 1482),
1275 			quadTo(221, 1509, 266, 1509),
1276 			quadTo(308, 1509, 339, 1482),
1277 			quadTo(371, 1455, 371, 1395),
1278 			quadTo(371, 1336, 339, 1308),
1279 			quadTo(308, 1280, 266, 1280),
1280 			quadTo(221, 1280, 190, 1308),
1281 			quadTo(160, 1336, 160, 1395),
1282 		},
1283 	},
1284 }
1285 
1286 type boundsTestCase struct {
1287 	wantBounds fixed.Rectangle26_6
1288 	wantAdv    fixed.Int26_6
1289 }
1290 
1291 // proprietaryGlyphBoundsTestCases hold expected GlyphBounds. The
1292 // numerical values can be verified by running the ttx tool.
1293 // - Advance from hmtx width
1294 // - Bounds from TTGlyph (with flipped Y axis)
1295 var proprietaryGlyphBoundsTestCases = map[string]map[rune]boundsTestCase{
1296 	"adobe/SourceHanSansSC-Regular.otf": {
1297 		'!': {
1298 			wantBounds: fixed.Rectangle26_6{
1299 				Min: fixed.Point26_6{X: 95, Y: -749},
1300 				Max: fixed.Point26_6{X: 227, Y: 13},
1301 			},
1302 			wantAdv: 323,
1303 		},
1304 	},
1305 	"apple/Helvetica.dfont?0": {
1306 		'i': {
1307 			wantBounds: fixed.Rectangle26_6{
1308 				Min: fixed.Point26_6{X: 132, Y: -1469},
1309 				Max: fixed.Point26_6{X: 315, Y: 0},
1310 			},
1311 			wantAdv: 455,
1312 		},
1313 	},
1314 	"microsoft/Arial.ttf": {
1315 		'A': {
1316 			wantBounds: fixed.Rectangle26_6{
1317 				Min: fixed.Point26_6{X: -3, Y: -1466},
1318 				Max: fixed.Point26_6{X: 1369, Y: 0},
1319 			},
1320 			wantAdv: 1366,
1321 		},
1322 		// U+01FA LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE is a
1323 		// compound glyph whose elements are also compound glyphs.
1324 		'Ǻ': {
1325 			wantBounds: fixed.Rectangle26_6{
1326 				Min: fixed.Point26_6{X: -3, Y: -2124},
1327 				Max: fixed.Point26_6{X: 1369, Y: 0},
1328 			},
1329 			wantAdv: 1366,
1330 		},
1331 		// U+FD3E ORNATE LEFT PARENTHESIS.
1332 		'﴾': {
1333 			wantBounds: fixed.Rectangle26_6{
1334 				Min: fixed.Point26_6{X: 127, Y: -1608},
1335 				Max: fixed.Point26_6{X: 560, Y: 429},
1336 			},
1337 			wantAdv: 653,
1338 		},
1339 		// U+FD3F ORNATE RIGHT PARENTHESIS is a transformed version of left parenthesis
1340 		'﴿': {
1341 			wantBounds: fixed.Rectangle26_6{
1342 				Min: fixed.Point26_6{X: 93, Y: -1608},
1343 				Max: fixed.Point26_6{X: 526, Y: 429},
1344 			},
1345 			wantAdv: 653,
1346 		},
1347 	},
1348 	"noto/NotoSans-Regular.ttf": {
1349 		'i': {
1350 			wantBounds: fixed.Rectangle26_6{
1351 				Min: fixed.Point26_6{X: 160, Y: -1509},
1352 				Max: fixed.Point26_6{X: 371, Y: 0},
1353 			},
1354 			wantAdv: 528,
1355 		},
1356 	},
1357 }
1358 
1359 type kernTestCase struct {
1360 	ppem    fixed.Int26_6
1361 	hinting font.Hinting
1362 	runes   [2]rune
1363 	want    Units
1364 }
1365 
1366 // proprietaryKernTestCases hold a sample of each font's kerning pairs. The
1367 // numerical values can be verified by running the ttx tool.
1368 var proprietaryKernTestCases = map[string][]kernTestCase{
1369 	"adobe/SourceSansPro-Regular.otf": {
1370 		{1000, font.HintingNone, [2]rune{'A', 'V'}, -14},
1371 		{1000, font.HintingNone, [2]rune{'F', '\u0129'}, 36},
1372 	},
1373 	"adobe/SourceHanSansSC-Regular.otf": {
1374 		// U+3043 HIRAGANA LETTER SMALL I
1375 		// U+3067 HIRAGANA LETTER DE
1376 		{1000, font.HintingNone, [2]rune{'\u3043', '\u3067'}, -20},
1377 	},
1378 	"dejavu/DejaVuSans-ExtraLight.ttf": {
1379 		{2048, font.HintingNone, [2]rune{'A', 'A'}, 57},
1380 		{2048, font.HintingNone, [2]rune{'W', 'A'}, -112},
1381 		// U+00C1 LATIN CAPITAL LETTER A WITH ACUTE
1382 		// U+01FA LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
1383 		// U+1E82 LATIN CAPITAL LETTER W WITH ACUTE
1384 		{2048, font.HintingNone, [2]rune{'\u00c1', 'A'}, 57},
1385 		{2048, font.HintingNone, [2]rune{'\u01fa', 'A'}, 57},
1386 		{2048, font.HintingNone, [2]rune{'\u1e82', 'A'}, -112},
1387 	},
1388 	"dejavu/DejaVuSans.ttf": {
1389 		// U+EF13 + U+EF19 are private use codes, but DejaVuSans has these
1390 		// codes in a rarely used ClassDef format 1
1391 		{2048, font.HintingNone, [2]rune{'\uef13', '\uef19'}, -40},
1392 		{2048, font.HintingNone, [2]rune{'\uef13', '\uef13'}, 0},
1393 		// Use U+EF13 to trigger default class in ClassDef format 2
1394 		{2048, font.HintingNone, [2]rune{'A', '\uef13'}, 0},
1395 	},
1396 	"microsoft/Arial.ttf": {
1397 		{2048, font.HintingNone, [2]rune{'A', 'V'}, -152},
1398 		// U+03B8 GREEK SMALL LETTER THETA
1399 		// U+03BB GREEK SMALL LETTER LAMDA
1400 		{2048, font.HintingNone, [2]rune{'\u03b8', '\u03bb'}, -39},
1401 		{2048, font.HintingNone, [2]rune{'\u03bb', '\u03b8'}, -0},
1402 	},
1403 	"microsoft/Comic_Sans_MS.ttf": {
1404 		{2048, font.HintingNone, [2]rune{'A', 'V'}, 0},
1405 	},
1406 	"microsoft/Times_New_Roman.ttf": {
1407 		{768, font.HintingNone, [2]rune{'A', 'V'}, -99},
1408 		{768, font.HintingFull, [2]rune{'A', 'V'}, -128},
1409 		{2048, font.HintingNone, [2]rune{'A', 'A'}, 0},
1410 		{2048, font.HintingNone, [2]rune{'A', 'T'}, -227},
1411 		{2048, font.HintingNone, [2]rune{'A', 'V'}, -264},
1412 		{2048, font.HintingNone, [2]rune{'T', 'A'}, -164},
1413 		{2048, font.HintingNone, [2]rune{'T', 'T'}, 0},
1414 		{2048, font.HintingNone, [2]rune{'T', 'V'}, 0},
1415 		{2048, font.HintingNone, [2]rune{'V', 'A'}, -264},
1416 		{2048, font.HintingNone, [2]rune{'V', 'T'}, 0},
1417 		{2048, font.HintingNone, [2]rune{'V', 'V'}, 0},
1418 		// U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
1419 		// U+0393 GREEK CAPITAL LETTER GAMMA
1420 		{2048, font.HintingNone, [2]rune{'\u0390', '\u0393'}, 0},
1421 		{2048, font.HintingNone, [2]rune{'\u0393', '\u0390'}, 76},
1422 	},
1423 	"microsoft/Webdings.ttf": {
1424 		{2048, font.HintingNone, [2]rune{'\uf041', '\uf042'}, 0},
1425 	},
1426 	"noto/NotoSans-Regular.ttf": {
1427 		{2048, font.HintingNone, [2]rune{'A', 'V'}, -40},
1428 		{2048, font.HintingNone, [2]rune{'A', 'W'}, -40},
1429 		{2048, font.HintingNone, [2]rune{'A', 'T'}, -70},
1430 		{2048, font.HintingNone, [2]rune{'V', 'A'}, -40},
1431 		{2048, font.HintingNone, [2]rune{'W', 'A'}, -40},
1432 		{2048, font.HintingNone, [2]rune{'T', 'A'}, -70},
1433 		// U+00C1 LATIN CAPITAL LETTER A WITH ACUTE
1434 		// U+01FA LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
1435 		// U+1E82 LATIN CAPITAL LETTER W WITH ACUTE
1436 		{2048, font.HintingNone, [2]rune{'\u00c1', 'T'}, -70},
1437 		{2048, font.HintingNone, [2]rune{'\u01fa', 'T'}, -70},
1438 		{2048, font.HintingNone, [2]rune{'\u1e82', 'A'}, -40},
1439 
1440 		// NotoSans-Regular.ttf uses two PairPos format=1 tables (with ExtensionPos).
1441 		// Test first and last pairs in both tables.
1442 		// First pair in first table
1443 		{2048, font.HintingNone, [2]rune{'F', '?'}, 20},
1444 		// U+04c3 CYRILLIC CAPITAL LETTER KA WITH HOOK
1445 		// U+0424 CYRILLIC CAPITAL LETTER EF
1446 		// Last pair in first table
1447 		{2048, font.HintingNone, [2]rune{'\u04c3', '\u0424'}, -20},
1448 		// First pair in second table
1449 		{2048, font.HintingNone, [2]rune{'"', 'A'}, -70},
1450 		// <!-- GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA -->
1451 		// <!-- GREEK UPSILON WITH HOOK SYMBOL -->
1452 		// Last pair in second table
1453 		{2048, font.HintingNone, [2]rune{'\u1f4d', '\u03d2'}, -10},
1454 	},
1455 }
1456 
1457 // proprietaryFDSelectTestCases hold a sample of each font's Font Dict Select
1458 // (FDSelect) map. The numerical values can be verified by grepping the output
1459 // of the ttx tool:
1460 //
1461 //	grep CharString.*fdSelectIndex SourceHanSansSC-Regular.ttx
1462 //
1463 // will print lines like this:
1464 //
1465 //	<CharString name="cid00100" fdSelectIndex="15">
1466 //	<CharString name="cid00101" fdSelectIndex="15">
1467 //	<CharString name="cid00102" fdSelectIndex="3">
1468 //	<CharString name="cid00103" fdSelectIndex="15">
1469 //
1470 // As for what the values like 3 or 15 actually mean, grepping that ttx file
1471 // for "FontName" gives this list:
1472 //
1473 //	0:	<FontName value="SourceHanSansSC-Regular-Alphabetic"/>
1474 //	1:	<FontName value="SourceHanSansSC-Regular-AlphabeticDigits"/>
1475 //	2:	<FontName value="SourceHanSansSC-Regular-Bopomofo"/>
1476 //	3:	<FontName value="SourceHanSansSC-Regular-Dingbats"/>
1477 //	4:	<FontName value="SourceHanSansSC-Regular-DingbatsDigits"/>
1478 //	5:	<FontName value="SourceHanSansSC-Regular-Generic"/>
1479 //	6:	<FontName value="SourceHanSansSC-Regular-HDingbats"/>
1480 //	7:	<FontName value="SourceHanSansSC-Regular-HHangul"/>
1481 //	8:	<FontName value="SourceHanSansSC-Regular-HKana"/>
1482 //	9:	<FontName value="SourceHanSansSC-Regular-HWidth"/>
1483 //	10:	<FontName value="SourceHanSansSC-Regular-HWidthCJK"/>
1484 //	11:	<FontName value="SourceHanSansSC-Regular-HWidthDigits"/>
1485 //	12:	<FontName value="SourceHanSansSC-Regular-Hangul"/>
1486 //	13:	<FontName value="SourceHanSansSC-Regular-Ideographs"/>
1487 //	14:	<FontName value="SourceHanSansSC-Regular-Kana"/>
1488 //	15:	<FontName value="SourceHanSansSC-Regular-Proportional"/>
1489 //	16:	<FontName value="SourceHanSansSC-Regular-ProportionalCJK"/>
1490 //	17:	<FontName value="SourceHanSansSC-Regular-ProportionalDigits"/>
1491 //	18:	<FontName value="SourceHanSansSC-Regular-VKana"/>
1492 //
1493 // As a sanity check, the cmap table maps U+3127 BOPOMOFO LETTER I to the glyph
1494 // named "cid65353", proprietaryFDSelectTestCases here maps 65353 to Font Dict
1495 // 2, and the list immediately above maps 2 to "Bopomofo".
1496 var proprietaryFDSelectTestCases = map[string]map[GlyphIndex]int{
1497 	"adobe/SourceHanSansSC-Regular.otf": {
1498 		0:     5,
1499 		1:     15,
1500 		2:     15,
1501 		16:    15,
1502 		17:    17,
1503 		26:    17,
1504 		27:    15,
1505 		100:   15,
1506 		101:   15,
1507 		102:   3,
1508 		103:   15,
1509 		777:   4,
1510 		1000:  3,
1511 		2000:  3,
1512 		3000:  13,
1513 		4000:  13,
1514 		20000: 13,
1515 		48000: 12,
1516 		59007: 1,
1517 		59024: 0,
1518 		59087: 8,
1519 		59200: 7,
1520 		59211: 6,
1521 		60000: 13,
1522 		63000: 16,
1523 		63039: 9,
1524 		63060: 11,
1525 		63137: 10,
1526 		65353: 2,
1527 		65486: 14,
1528 		65505: 18,
1529 		65506: 5,
1530 		65533: 5,
1531 		65534: 5,
1532 	},
1533 }