-
Notifications
You must be signed in to change notification settings - Fork 16
/
index.html
1762 lines (1605 loc) · 116 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<title>WOFF File Format 2.0</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="canonical" href="https://www.w3.org/TR/WOFF2/">
<style type="text/css">
table.spec {border: 2px solid #444;}
span.tt {font-family: monospaced;}
:link { text-decoration: none}
a:hover { text-decoration: underline}
.tt { font-family: monospace }
</style>
<!-- Embedded conformance stylesheet -->
<style type="text/css" title="Conformance">
.conform:hover {background: #DFD}
.conform:target {padding: 2px; border: 2px solid #ACA; background: #DFD }
.ua::before {
background: rgb(153, 255, 153); padding: 4px; border: thin solid green; border-image: none; content: "UA: ";
}
.ff::before {
background: rgb(255, 153, 153); padding: 4px; border: thin solid maroon; border-image: none; content: "FF: ";
}
.at::before {
background: rgb(153, 153, 255); padding: 4px; border: thin solid navy; border-image: none; content: "AT:";
}
.dc::before {
background: #f4b13d; padding:4px; border: thin solid #c17e0a; border-image: none; content: "DC: ";
}
</style>
<!-- -->
<!-- Conformance stylesheet - enable for online viewing -->
<link rel="alternate stylesheet" type="text/css" title="Conformance" href="conform.css">
<link rel="stylesheet" type="text/css" href="https://www.w3.org/StyleSheets/TR/2016/W3C-ED"/>
</head>
<body>
<div class="head">
<p>
<a class="logo" href="https://www.w3.org/"><img src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C" alt="W3C" width="72" height="48"></a>
</p>
<h1 style="clear:both" id="title">WOFF File Format 2.0 </h1>
<h2 id="W3C-doctype">W3C Editors Draft 11 January 2018</h2>
<dl>
<dt>This version:</dt>
<dd><a href="https://www.w3.org/TR/2018/PR-WOFF2-20180111/">https://www.w3.org/TR/2018/PR-WOFF2-20180111/</a>
<dt>Latest version:</dt>
<dd> <a href="https://www.w3.org/TR/WOFF2/">https://www.w3.org/TR/WOFF2/</a>
</dd>
<dt>Previous Version:</dt>
<dd> <a href="https://www.w3.org/TR/2016/CR-WOFF2-20160315/">https://www.w3.org/TR/2016/CR-WOFF2-20160315/</a></dd>
<dt>Latest editor's draft:</dt>
<dd><a href="https://w3c.github.io/woff/woff2/">https://w3c.github.io/woff/woff2/</a>
</dd>
</dl>
<dl>
<dt>Editors:</dt>
<dd>Vladimir Levantovsky (Monotype)</dd>
<dd>Raph Levien (Google)</dd>
</dl>
<p class="copyright">
<a href="https://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> ©
2018
<a href="https://www.w3.org/"><abbr title="World Wide Web Consortium">W3C</abbr></a><sup>®</sup>
(<a href="https://www.csail.mit.edu/"><abbr title="Massachusetts Institute of Technology">MIT</abbr></a>,
<a href="https://www.ercim.eu/"><abbr title="European Research Consortium for Informatics and Mathematics">ERCIM</abbr></a>,
<a href="https://www.keio.ac.jp/">Keio</a>, <a href="http://ev.buaa.edu.cn/">Beihang</a>).
<abbr title="World Wide Web Consortium">W3C</abbr> <a href="https://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>,
<a href="https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> and
<a rel="license" href="https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document">permissive document license</a>
rules apply.
</p>
<hr title="Separator for header">
</div>
<section id="abstract">
<h2 id='abstract-0'>Abstract</h2>
<p>Based on experience with WOFF 1.0, which is
widely deployed, this specification was developed to provide improved
compression and thus lower use of network bandwidth, while still
allowing fast decompression even on mobile devices. This is achieved
by combining a content-aware preprocessing step and
improved entropy coding, compared to the Flate compression used in
WOFF 1.0.</p>
</section>
<section id="sotd">
<h2 id="status-of-this-document">Status of This Document</h2>
<p><em>This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the <a href="https://www.w3.org/TR/">W3C technical reports index</a> at https://www.w3.org/TR/.</em></p>
<p>This document was developed by the <a href="https://www.w3.org/Fonts/WG/">WebFonts
Working Group</a> as a Candiate Recommendation.
This document will remain a Proposed Recommendation at least until <time class="status-deadline"
datetime="2018-02-11">11 February 2018</time> in order
to ensure the opportunity for wide review. The W3C Membership and other interested parties are invited to review the document and send comments.
Advisory Committee Representatives should consult their
<a href="https://www.w3.org/2002/09/wbs/myQuestionnaires">WBS questionnaires</a>.
<p>A complete <a href="#changes-since-CR">list of
changes</a> to this document since the last publication is available.
</p>
<p class=custom>Supporting material, including results of compression measurements, may be found in the
companion <a href="https://www.w3.org/TR/WOFF20ER/">WOFF 2.0 Evaluation Report</a>. The Working Group has
<a href="https://github.com/w3c/woff2-compiled-tests">created
tests</a> for
WOFF2 <a href="/Fonts/WG/wiki/TestPlan20-AuthoringTool" title="TestPlan20-AuthoringTool">encoders</a>,
<a href="/Fonts/WG/wiki/TestPlan20-Decoder" title="TestPlan20-Decoder">decoders</a>,
<a href="/Fonts/WG/wiki/TestPlan20-UserAgent" title="TestPlan20-UserAgent">browsers</a>, and for <a href="/Fonts/WG/wiki/TestPlan20-Format" title="TestPlan20-Format">the format itself</a> (a WOFF2 validator).
The source to build these tests is <a href="https://github.com/w3c/woff2-tests">available on GitHub</a>.</p>
<p>An <a href="https://www.w3.org/Fonts/WG/WOFF2/Implementation.html">Implementation Report</a> is available.
Note that, for OpenType Collections (previously, TrueType Collections) while there are two tested
implementations of encoding and of decoding, no user
agent is yet shown to <em>use</em> them after decoding. Browser support
for font collections is expected to improve, and once it does WOFF 2.0 already has
the needed support.</p>
<p>Please send comments about this document
<!--to <a href="mailto:www-font@w3.org">www-font@w3.org</a>
(with <a href="https://lists.w3.org/Archives/Public/www-font/">public
archive</a>)-->
as <a href="https://github.com/w3c/woff/issues">GitHub issues</a>.</p>
<p>Publication as a Proposed Recommendation does not imply endorsement
by the W3C Membership. This is a draft document and may be updated,
replaced or obsoleted by other documents at any time. It is
inappropriate to cite this document as other than work in progress.</p>
<p>This document was produced by a group operating under the <a href="https://www.w3.org/Consortium/Patent-Policy/">W3C Patent Policy</a>. W3C maintains a <a rel="disclosure"
href="https://www.w3.org/2004/01/pp-impl/44556/status">public list of any
patent disclosures</a> made in connection with the deliverables of the
group; that page also includes instructions for disclosing a patent. An
individual who has actual knowledge of a patent which the individual
believes contains <a href="https://www.w3.org/Consortium/Patent-Policy/#def-essential">Essential
Claim(s)</a> must disclose the information in accordance with <a href="https://www.w3.org/Consortium/Patent-Policy/#sec-Disclosure">section
6 of the W3C Patent Policy</a>. </p>
<p>For the Brotli compression scheme used in WOFF 2.0, Google has made an
<a href="https://www.w3.org/2004/01/pp-impl/44556/show-license#x35662">RF licensing commitment</a> for use in this specification.</p>
<p>This document is governed by the <a id="w3c_process_revision" href="https://www.w3.org/2017/Process-20170301/">1 March 2017 W3C Process Document</a>. </p>
</section>
<nav id="toc">
<h2 class="introductory" id="table-of-contents">Table of Contents</h2>
<ol class='toc'>
<li class='tocline'><a href="#Introduction"><span class="secno">1. </span>Introduction</a>
<ol class='toc'>
<li class='tocline'><a href="#Notation"><span class='secno'>1.1. </span>Notational Conventions</a></li>
</ol>
</li>
<li class='tocline'><a href="#General"><span class='secno'>2. </span>General Requirements</a></li>
<li class='tocline'><a href="#FileStructure"><span class='secno'>3. </span>Overall file structure and basic data types</a>
<ol class='toc'>
<li class='tocline'><a href="#DataTypes"><span class='secno'>3.1. </span>Data types</a></li>
<li class='tocline'><a href="#woff20Header"><span class='secno'>3.2. </span>WOFF2 Header</a></li>
</ol>
</li>
<li class='tocline'><a href="#font_directory"><span class='secno'>4. </span>Font directory</a>
<ol class='toc'>
<li class='tocline'><a href="#table_dir_format"><span class='secno'>4.1. </span>Table directory format</a></li>
<li class='tocline'><a href="#collection_dir_format"><span class='secno'>4.2. </span>Collection directory format</a></li>
</ol>
</li>
<li class='tocline'><a href="#table_format"><span class='secno'>5. </span>Compressed data format</a>
<ol class='toc'>
<li class='tocline'><a href="#glyf_table_format"><span class='secno'>5.1. </span>Transformed glyf table format</a></li>
<li class='tocline'><a href="#triplet_decoding"><span class='secno'>5.2. </span>Decoding of variable-length X and Y coordinates</a></li>
<li class='tocline'><a href="#loca_table_format"><span class='secno'>5.3. </span>Transformed loca table format</a></li>
<li class='tocline'><a href="#hmtx_table_format"><span class='secno'>5.4. </span>Transformed hmtx table format</a></li>
<li class='tocline'><a href="#table_order"><span class='secno'>5.5. </span>Table order constraints</a></li>
</ol>
</li>
<li class='tocline'><a href="#Metadata"><span class='secno'>6. </span>Extended Metadata Block</a></li>
<li class='tocline'><a href="#Private"><span class='secno'>7. </span>Private Data Block</a></li>
<li class='tocline'><a href="#IMT"><span class='secno'>A. </span>Internet Media Type Registration</a></li>
<li class='tocline'><a href="#changes"><span class='secno'>B. </span>Changes</a></li>
<li class='tocline'><a href="#security-privacy-considerations"><span class='secno'>C. </span>Security and Privacy Considerations</a></li>
<li class='tocline'><a href="#References"><span class='secno'>D. </span>References</a>
<ol class="toc">
<li class='tocline'><a href="#normative"><span class='secno'>D.1 </span>Normative References</a></li>
<li class='tocline'><a href="#informative"><span class='secno'>D.2 </span>Informative References</a></li>
</ol>
</li>
</ol>
</nav>
<section id="Introduction">
<h2 id="Introduction-0"><span class='secno'>1. </span>Introduction</h2>
<p>This document specifies the WOFF2 font packaging format. This format was
designed to provide a reasonably easy-to-implement compression of font data
with significantly better compression than previous techniques, suitable for
use with CSS <span class=tt>@font-face</span> rules. The improvement in compression rates,
compared to previously developed WOFF 1.0 format [<cite><a href="#ref-woff10">WOFF1</a></cite>]
are realized due to improved entropy coding and font data preprocessing and
optimization step that reduces built-in redundancy of various font data structures.
The details about WOFF 2.0 development history can be found in the WOFF 2.0
Evaluation Report [<cite><a href="#ref-woff20er">WOFF2ER</a></cite>].</p>
<section id="Notation"><h3 id="Notation_1"><span class='secno'>1.1 </span>Notational Conventions</h3>
<p>The all-uppercase key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"
in this document are to be interpreted as described in RFC 2119 [<cite><a
href="#ref-RFC-2119">RFC2119</a></cite>].
If these words occur in lower- or mixed case, they should be interpreted
in accordance with their normal English meaning. </p>
<p>This document includes sections of text that are called out as "Notes"
and set off from the main text of the specification. These notes are
intended as informative explanations or clarifications, to serve as hints
or guides to implementers and users, but are not part of the normative
text.</p>
<p>This document also uses hexadecimal numerical notation "0x..." to define the
constant binary values such as magic number or tag values, bitfields
/ flags format and mask values used in pseudo-code bitwise operators.</p>
</section>
</section>
<section id="General">
<h2 id="General-0"><span class='secno'>2. </span>General Requirements</h2>
<p>The primary purpose of the WOFF2 format is to efficiently package fonts linked
to Web documents by means of CSS <span class=tt>@font-face</span> rules. User agents supporting
the WOFF2 file format for linked fonts must respect the requirements of the
CSS3 Fonts specification
([<cite><a href="#ref-CSS3-Fonts">CSS3-Fonts</a></cite>]
<a href="https://www.w3.org/TR/css-fonts-3/#font-face-rule">
Section 4.1: The @font-face rule</A>). In particular,
<span class="conform ua" id="conform-css3font-available">such linked fonts are
only available to the documents that reference them; they MUST NOT be made
available to other applications or documents on the user's system</span>.</p>
<p>The input font file may contain a number of various font data tables described in the
clause 5 of the [<cite><a href="#ref-OFF">OFF</a></cite>] specification. The order of the
tables in a font file may differ and, while the entries in the table directory have
to be sorted in ascending order by tags, the actual tables can be presented in a font file
in arbitrary order.</p>
<div class="note">
<p>When WOFF2 file is decompressed, the decoder must sort the entries in the table directory
in ascending alphabetical order by table tags and should arrange the table order in a font file
according to the Recommendations (subclause 8.1 "Optimized table ordering") of the
[<cite><a href="#ref-OFF">OFF</a></cite>].</p>
</div>
</section>
<section id="FileStructure">
<h2 id="FileStructure-0"><span class='secno'>3. </span>Overall file structure and basic data types</h2>
<p>The structure of WOFF2 files is similar to that of SFNT and WOFF 1.0 font files,
in that there is a header followed by a table directory, followed by the data
for those tables. The SFNT structure is described fully in the TrueType
[<cite><a href="#ref-TTF">TrueType</a></cite>], OpenType
[<cite><a href="#ref-OTF">OpenType</a></cite>], and ISO "Open Font Format"
[<cite><a href="#ref-OFF">OFF</a></cite>] specifications. However,
WOFF2 differs in some important aspects from SFNT. Most notably, the data
for the font tables is compressed in a single data stream comprising all the font tables.
Similar to WOFF 1.0 format, the optional extended metadata and private data blocks are each
presented as separate blocks of data, and are concatenated together into the WOFF 2.0 file.
The compression algorithm used for both the compressed font data stream and extended
metadata block is Brotli [<cite><a href="#ref-Brotli">Brotli</a></cite>].</p>
<p>A complete WOFF2 file consists of several blocks of data: a 48-byte header, immediately
followed (in this order) by a variable-size Table Directory, an optional Collection
Directory (present only if the input font file is a font collection), a compressed font data block,
an optional block of Extended Metadata, and an optional block of Private Data. Except
for padding with a maximum of three null bytes in places where 4-byte alignment of a
table length or block offset is specified,
<span class="conform ff" id="conform-noextraneous">there MUST NOT be any extraneous
data between the data blocks or WOFF2 header and table directory, or beyond the last
such block or table</span>.
If such extraneous data is present <span class="conform ua" id="conform-extraneous-reject">
a conforming user agent MUST reject the file as invalid</span>. The file
<span class="conform ua" id="conform-overlap-reject">MUST also be rejected as invalid
if the offsets and lengths of any data blocks or font tables indicate overlapping
byte ranges of the file, or ranges that would extend beyond the end of the file</span>.</p>
<table>
<col class="type"/><col class="desc"/>
<tr class="header"><th colspan="2" style="background-color: #F8F8F8">WOFF2 File</th></tr>
<tr><td>WOFF2Header </td><td>File header with basic font type and version, along with offsets to metadata and private data blocks.</td></tr>
<tr><td>TableDirectory </td><td>Directory of font tables, containing size and other info. </td></tr>
<tr><td>CollectionDirectory </td><td>An optional table containing the font fragment descriptions of font collection entries. </td></tr>
<tr><td>CompressedFontData </td><td>Contents of font tables, compressed for storage in the WOFF2 file. </td></tr>
<tr><td>ExtendedMetadata </td><td>An optional block of extended metadata, represented in XML format and compressed for storage in the WOFF2 file. </td></tr>
<tr><td>PrivateData </td><td>An optional block of private data for the font designer, foundry, or vendor to use. </td></tr>
</table>
<section id="DataTypes">
<h3 id="DataTypes-0"><span class='secno'>3.1. </span>Data types</h3>
<table>
<col class="type"/><col class="desc"/>
<tr class="types"><th colspan="2" style="background-color: #F8F8F8">Data Types</th></tr>
<tr><td>UInt8 </td><td>8-bit unsigned integer. </td></tr>
<tr><td>Int16 </td><td>16-bit signed integer in 2's complement format, stored big-endian. </td></tr>
<tr><td>UInt16 </td><td>16-bit unsigned integer, stored big-endian. </td></tr>
<tr><td>255UInt16 </td><td>Variable-length encoding of a 16-bit unsigned integer for optimized intermediate font data storage. </td></tr>
<tr><td>UIntBase128 </td><td>Variable-length encoding of 32-bit unsigned integers. </td></tr>
</table>
<section id="255UInt16">
<h4 id="255UInt16-0">255UInt16 Data Type</h4>
<p>255UInt16 is a variable-length encoding of an unsigned integer in the range
0 to 65535 inclusive. This data type is intended to be used as intermediate
representation of various font values, which are typically expressed as UInt16 but
represent relatively small values. Depending on the encoded value, the length of
the data field may be one to three bytes, where the value of the first byte either
represents the small value itself or is treated as a code that defines the format of
the additional byte(s). The "C-like" pseudo-code describing how to read the 255UInt16
format is presented below:</p>
<!--
as described in the following table:</p>
<table>
<tr>
<th style="background-color: #F8F8F8; width: 10%;">Data Type</th>
<th style="background-color: #F8F8F8; width: 35%;">Syntax</th>
<th style="background-color: #F8F8F8; width: 55%;">Description and Comments</th>
</tr>
<tr><td>UInt8</td><td> Code</td><td>if (Code < 253) Value = Code; /* [0..252] */</td></tr>
<tr><td></td><td>if ((Code == 254) || (Code == 255))</td><td></td></tr>
<tr><td>UInt8</td><td> Value1</td>
<td>if (Code == 255) Value = 253 + Value1; /* [253..508] */<br/>if (Code == 254) Value = 506 + Value1; /* [506..761] */</td></tr>
<tr><td></td><td>else if (Code == 253)</td><td></td></tr>
<tr><td>UInt16</td><td> Value</td><td>Value; /* [0..65535] */</td></tr>
</table>
-->
<pre class='def'>
Read255UShort( data )
{
UInt8 code;
UInt16 value, value2;
const oneMoreByteCode1 = 255;
const oneMoreByteCode2 = 254;
const wordCode = 253;
const lowestUCode = 253;
code = data.getNextUInt8();
if ( code == wordCode ) {
/* Read two more bytes and concatenate them to form UInt16 value*/
value = data.getNextUInt8();
value <<= 8;
value &= 0xff00;
value2 = data.getNextUInt8();
value |= value2 & 0x00ff;
}
else if ( code == oneMoreByteCode1 ) {
value = data.getNextUInt8();
value = (value + lowestUCode);
}
else if ( code == oneMoreByteCode2 ) {
value = data.getNextUInt8();
value = (value + lowestUCode*2);
}
else {
value = code;
}
return value;
}
</pre>
<p>Note that the encoding is not unique. For example, the value 506 can be
encoded as [255, 253], [254, 0], and [253, 1, 250]. An encoder may produce
any of these, and <span class="conform ua" id="conform-mustAccept255UInt16">
a decoder MUST accept them all</span>. An encoder should choose shorter
encodings, and must be consistent in choice of encoding for the same value,
as this will tend to compress better.</p>
</section>
<section id="UIntBase128">
<h4 id="UIntBase128-0">UIntBase128 Data Type</h4>
<p>UIntBase128 is a different variable length encoding of unsigned integers,
suitable for values up to 2<sup>32</sup>-1. A UIntBase128 encoded number
is a sequence of bytes for which the most significant bit is set for all but
the last byte, and clear for the last byte. The number itself is base 128
encoded in the lower 7 bits of each byte. Thus, a decoding procedure for
a UIntBase128 is: start with value = 0. Consume a byte, setting value =
old value times 128 + (byte bitwise-and 127). Repeat last step until
the most significant bit of byte is false.</p>
<p>UIntBase128 encoding format allows a possibility of sub-optimal encoding, where e.g.
the same numerical value can be represented with variable number of bytes (utilizing
leading 'zeros'). For example, the value 63 could be encoded as either one byte 0x3F
or two (or more) bytes: [0x80, 0x3f]. An encoder must not allow this to happen and
must produce shortest possible encoding. A decoder
<span class="conform ua" id="conform-mustRejectInvalidBase128">
MUST reject the font file if it encounters a UintBase128-encoded value with
leading zeros (a value that starts with the byte 0x80), if UintBase128-encoded
sequence is longer than 5 bytes, or if a UintBase128-encoded value exceeds
2<sup>32</sup>-1</span>. The "C-like" pseudo-code describing how to read the
UIntBase128 format is presented below:</p>
<pre class='def'>
bool ReadUIntBase128( data, *result )
{
UInt32 accum = 0;
for (i = 0; i < 5; i++) {
UInt8 data_byte = data.getNextUInt8();
// No leading 0's
if (i == 0 && data_byte == 0x80) return false;
// If any of top 7 bits are set then << 7 would overflow
if (accum & 0xFE000000) return false;
*accum = (accum << 7) | (data_byte & 0x7F);
// Spin until most significant bit of data byte is false
if ((data_byte & 0x80) == 0) {
*result = accum;
return true;
}
}
// UIntBase128 sequence exceeds 5 bytes
return false;
}
</pre>
</section>
</section>
<section id="woff20Header">
<h3 id="woff20Header-0"><span class='secno'>3.2. </span>WOFF2 Header</h3>
<p>The WOFF 2.0 header includes an identifying signature and provides the
information about the compressed and uncompressed sizes of encapsulated font
data. It also indicates the specific kind of font data included in the WOFF 2.0
file, font version number and provides offsets to additional data blocks included
in the file.</p>
<table>
<col class="type"/><col class="name"/><col class="desc"/>
<tr class="header"><th colspan="3" style="background-color: #F8F8F8">WOFF2 Header</th></tr>
<tr><td>UInt32</td><td>signature</td><td>0x774F4632 <span class=tt>'wOF2'</span></td></tr>
<tr><td>UInt32</td><td>flavor</td><td>The "sfnt version" of the input font.</td></tr>
<tr><td>UInt32</td><td>length</td><td>Total size of the WOFF file.</td></tr>
<tr><td>UInt16</td><td>numTables</td><td>Number of entries in directory of font
tables.</td></tr>
<tr><td>UInt16</td><td>reserved</td><td>Reserved; set to 0.</td></tr>
<tr><td>UInt32</td><td>totalSfntSize</td><td>Total size needed for the
uncompressed font data, including the sfnt header, <br/>directory,
and font tables (including padding).</td></tr>
<tr><td>UInt32</td><td>totalCompressedSize</td><td>Total length of the compressed data block.</td></tr>
<tr><td>UInt16</td><td>majorVersion</td><td>Major version of the WOFF
file.</td></tr>
<tr><td>UInt16</td><td>minorVersion</td><td>Minor version of the WOFF
file.</td></tr>
<tr><td>UInt32</td><td>metaOffset</td><td>Offset to metadata block, from
beginning of WOFF file.</td></tr>
<tr><td>UInt32</td><td>metaLength</td><td>Length of compressed metadata block.</td></tr>
<tr><td>UInt32</td><td>metaOrigLength</td><td>Uncompressed size of metadata
block.</td></tr>
<tr><td>UInt32</td><td>privOffset</td><td>Offset to private data block, from
beginning of WOFF file.</td></tr>
<tr><td>UInt32</td><td>privLength</td><td>Length of private data block.</td></tr>
</table>
<p>The interpretation of the WOFF2 Header is the same as the WOFF Header in
[<cite><a href="#ref-woff10">WOFF1</a></cite>], with the addition of one new
<span class="tt">totalCompressedSize</span> field.
<span class="conform ff" id="conform-magicNumber">The <span class="tt">signature</span> field
in the WOFF2 header MUST contain the value of 0x774F4632 ('wOF2')</span>, which distinguishes
it from WOFF 1.0 files. <span class="conform ua" id="conform-noMagicNumber-reject">If the field
does not contain this value, user agents MUST reject the file as invalid</span>.
A valid WOFF 2.0 file <span class="conform ff" id="conform-mustSetReserved2Zero">
MUST have the reserved field set to 'zero'</span>, a decoder
<span class="conform ua" id="conform-mustNotUseReservedValue">MUST NOT reject a downloaded
font file if the reserved header value is not zero</span>. User agents
<span class="conform ua" id="conform-mustNotRejectIncorrectTotalSize">MUST NOT reject correctly
decoded font file if the resulting font file size doesn't match the <span class=tt>totalSfntSize
</span> value encoded as part of the WOFF2 header</span>.</p>
<div class="note">
<p>The "totalSfntSize" value in the WOFF2 Header is intended to be used for reference purposes
only. It may represent the size of the uncompressed input font file, but if the transformed
'glyf' and 'loca' tables are present, the uncompressed size of the reconstructed tables and
the total decompressed font size may differ substantially from the original total size
specified in the WOFF2 Header.
</p>
</div>
</section>
</section><section id="font_directory"><h2 id="font_directory-0"><span class='secno'>4. </span>Font directory</h2>
<p>The font directory section consists of the table directory, containing a single entry for
each unique font table in the input font file, and may also include an optional collection
directory table, when the input font file is a font collection.</p>
<section id="table_dir_format"><h3 id="table_dir_format-0"><span class='secno'>4.1. </span>Table directory format</h3>
<p>The table directory is an array of WOFF2 table directory entries, as defined
below. The directory follows immediately after the WOFF2 file header; therefore,
there is no explicit offset in the header pointing to this block.
Its size is dependent on the exact content; thus, the best strategy for
decoding is to process the file as a stream, rather than trying to access
it randomly. Each table directory entry specifies the original size of a single
font data table and, for those tables where an additional transform has been applied,
the size of the transformed table. Transformed tables are identified by their 'flags' field
that combines known table tags (bits 0-5, see "Known Table Tags") and transformation
version number (bits 6 and 7, see the description below) defining the applied transform.
The combination of the table tag and the transform version number defines the exact
transform that was applied to a table, currently defined transforms are specified
in details in <a href="#table_format">clause 5</a> of this specification.</p>
<p>Contrary to the way how table directory entries are specified in the original input
font file (where table directory entries are sorted in ascending alphabetical order),
the WOFF2 table directory entries define the physical order of tables in which they
have been processed and encoded as part of the compressed font data stream. It is
a decoder responsibility to sort and reorder the reconstructed table directory when
the font file is decompressed.</p>
<p>In order to simplify the font decoding process an encoder
<span class="conform at" id="conform-mustReorderGlyfLoca"> MUST reorder the transformed
tables so that the associated 'glyf' and 'loca' tables are always present as a pair,
with 'loca' table following the 'glyf' table</span>.
Please keep in mind that the entry for transformed 'loca' table is just a placeholder indicating
the size required to reconstruct the table while consuming no bytes of the data stream.
Therefore, the requirement for the 'loca' table entry to immediately follow the transformed
'glyf' table in the table directory makes it easier to implement the 'loca' table reconstruction
step when the reverse transform (see <a href="#glyf_table_format">subclause 5.1</a> for details)
is being applied to the 'glyf' table. For more details on table order constraints see
<a href="#table_order">subclause 5.5</a>.</p>
<p>The format of each individual table directory entry is as follows:</p>
<table>
<tr class="header"><th colspan="3" style="background-color: #F8F8F8">TableDirectoryEntry</th></tr>
<tr><td>UInt8</td><td>flags</td><td>table type and flags</td></tr>
<tr><td>UInt32</td><td>tag</td><td>4-byte tag (optional)</td></tr>
<tr><td>UIntBase128</td><td>origLength</td><td>length of original table</td></tr>
<tr><td>UIntBase128</td><td>transformLength</td><td>transformed length (if applicable)</td></tr>
</table>
<p>The interpretation of the flags field is as follows. Bits [0..5] contain an index to
the "known tag" table, which represents tags likely to appear in fonts. If the tag is
not present in this table, then the value of this bit field is 63. Bits 6 and 7 indicate
the preprocessing transformation version number (0-3) that was applied to each table.
For all tables in a font, except for 'glyf' and 'loca' tables, transformation version 0
indicates the <span class=tt>null</span> transform where the original table data is
passed directly to the Brotli compressor for inclusion in the compressed data stream.
For 'glyf' and 'loca' tables, transformation version 3 indicates the <span class=tt>null</span>
transform where the original table data was passed directly to the Brotli compressor without
applying any pre-processing defined in <a href="#glyf_table_format">subclause 5.1</a> and
<a href="#loca_table_format">subclause 5.3</a>.
The transformed table formats and their associated transformation version numbers are
described in details in <a href="#table_format">clause 5</a> of this specification.</p>
<div class="note">
<p>If multiple transformation versions are defined for a given table, an encoder should
normally choose the transformation version that results in the smallest transformed table
length, unless the reduction is so slight as to be insignificant.</p>
</div>
<p>Where more than one transformation version is defined for a given table tag, an encoder
may use any of the defined transformations that is applicable to the input data; a decoder
<span class="conform ua" id="conform-mustAcceptAllTransforms">MUST be prepared to accept
any of the defined transformations</span>.
<span class="conform ua" id="conform-mustBeRejected-FailTransform"> If a decoder
encounters a table entry that specifies an unknown transformation version number the
entire font MUST be rejected</span> as it cannot be correctly decoded.</p>
<p>Whether a font table is encoded with a known table tag or explicitly including
the four-byte tag has no semantical significance; it is simply a choice of encoding
intended to improve compression efficiency. Similarly, whether a particular four-byte
tag is present or not in the "Known Table Tags" table is not a normative statement about
whether such tags should be included in web fonts.The encoder <span class="conform at"
id="conform-mustUseKnownTags">MUST use known table flag when encoding an input
font table with a tag that is listed in the "Known Table Tags" table</span>.</p>
<p>There is a predefined extension mechanism for any custom table tag that is not
included in the known tag list (or for any new standard tags that may be defined
in the future). If bits [0..5] of the flags byte have the value 63 (0x3f), then
following the flag byte is a 4-byte arbitrary tag value. Otherwise, the tag field
is omitted in the TableDirectoryEntry structure, and is derived from bits [0..5]
of the flag byte from the fixed Known Table Tags table, given below. The decoder
<span class="conform ua" id="conform-mayAcceptKnownTagsAsCustom">MAY accept a table
entry defined using a custom table tag even if the tag that follows is identified
as one of the kown table tags</span>.</p>
<table>
<tr class="header"><th colspan="8" style="background-color: #F8F8F8">Known Table Tags</th></tr>
<tr>
<th style="background-color: #F8F8F8; width: 6%;">Flag</th>
<th style="background-color: #F8F8F8; width: 19%;">Tag</th>
<th style="background-color: #F8F8F8; width: 6%;">Flag</th>
<th style="background-color: #F8F8F8; width: 19%;">Tag</th>
<th style="background-color: #F8F8F8; width: 6%;">Flag</th>
<th style="background-color: #F8F8F8; width: 19%;">Tag</th>
<th style="background-color: #F8F8F8; width: 6%;">Flag</th>
<th style="background-color: #F8F8F8; width: 19%;">Tag</th>
</tr>
<tr><td> 0</td><td>cmap</td><td>16</td><td>EBLC</td><td>32</td><td>CBDT</td><td>48</td><td>gvar</td></tr>
<tr><td> 1</td><td>head</td><td>17</td><td>gasp</td><td>33</td><td>CBLC</td><td>49</td><td>hsty</td></tr>
<tr><td> 2</td><td>hhea</td><td>18</td><td>hdmx</td><td>34</td><td>COLR</td><td>50</td><td>just</td></tr>
<tr><td> 3</td><td>hmtx</td><td>19</td><td>kern</td><td>35</td><td>CPAL</td><td>51</td><td>lcar</td></tr>
<tr><td> 4</td><td>maxp</td><td>20</td><td>LTSH</td><td>36</td><td>SVG </td><td>52</td><td>mort</td></tr>
<tr><td> 5</td><td>name</td><td>21</td><td>PCLT</td><td>37</td><td>sbix</td><td>53</td><td>morx</td></tr>
<tr><td> 6</td><td>OS/2</td><td>22</td><td>VDMX</td><td>38</td><td>acnt</td><td>54</td><td>opbd</td></tr>
<tr><td> 7</td><td>post</td><td>23</td><td>vhea</td><td>39</td><td>avar</td><td>55</td><td>prop</td></tr>
<tr><td> 8</td><td>cvt </td><td>24</td><td>vmtx</td><td>40</td><td>bdat</td><td>56</td><td>trak</td></tr>
<tr><td> 9</td><td>fpgm</td><td>25</td><td>BASE</td><td>41</td><td>bloc</td><td>57</td><td>Zapf</td></tr>
<tr><td>10</td><td>glyf</td><td>26</td><td>GDEF</td><td>42</td><td>bsln</td><td>58</td><td>Silf</td></tr>
<tr><td>11</td><td>loca</td><td>27</td><td>GPOS</td><td>43</td><td>cvar</td><td>59</td><td>Glat</td></tr>
<tr><td>12</td><td>prep</td><td>28</td><td>GSUB</td><td>44</td><td>fdsc</td><td>60</td><td>Gloc</td></tr>
<tr><td>13</td><td>CFF </td><td>29</td><td>EBSC</td><td>45</td><td>feat</td><td>61</td><td>Feat</td></tr>
<tr><td>14</td><td>VORG</td><td>30</td><td>JSTF</td><td>46</td><td>fmtx</td><td>62</td><td>Sill</td></tr>
<tr><td>15</td><td>EBDT</td><td>31</td><td>MATH</td><td>47</td><td>fvar</td><td>63</td><td>arbitrary tag follows</td></tr>
</table>
<div class="note">
<p>Please note that according to the <a href="#References">SFNT-based font format specifications</a>
all table tags should consist of four characters. Table tags with less than four letters, such as
'<span class=tt>cvt </span>' (tag value 0x63767420) are padded with trailing spaces.</p>
</div>
<p>Following the flags (and the optional tag field) are one or two length values, each in
UIntBase128 unsigned integer encoding. The origLength field specifies the length of the
table in an uncompressed version of the font. For tables that are subjected to additional
<a href="#table_format">transformations</a>, <span class="conform ff" id="conform-mustIncludeTransformLength">
the transformLength field that specifies the length of the transformed version of the table
MUST be included</span>.</p>
<p>The transformLength field is present in the table directory entry if, and only if, the table
has been processed by a non-null transform prior to Brotli compression. For tables that are
not transformed, no transformLength field is present in the directory entry.</p>
<div class="note">
<p>The field containing the transformed length provides information about the transformed
table size prior to it being compressed by [<cite><a href="#ref-Brotli">Brotli</a></cite>].
This field is optional and is present only for certain tables (see below the description
of the "Compressed data format"). Please note that while the transformed length can be
relied upon to determined the decompressed table size, the original table length of the
transformed font table should be treated with caution.</p>
<p>The reconstruction process of transformed tables guarantees preserving the functionality
of the tables but may produce binary results that are different from the original
data. For example, 'glyf' table records may have outline point coordinates encoded
using one- or two-byte format, and the repetitive values can either be explicitly
duplicated in the coordinate stream or omitted (which would be indicated by the flags
byte of the control point). Therefore, various representations of glyph outline points
are possible that would produce identical rendering results; however, the binary data
of reconstructed glyph records may differ significantly from the original data. See
subclause 5.3.3 of the ISO "Open Font Format" [<cite><a href="#ref-OFF">OFF</a></cite>]
specification for details.</p>
<p>For this reason, the value of the origLength field of transformed table should be treated
only as a reference and should not be relied upon in making memory allocation decisions
when the WOFF2 data is decoded.</p>
</div>
</section><section id="collection_dir_format"><h3 id="collection_dir_format-0"><span class='secno'>4.2. </span>Collection directory format</h3>
<p>The collection directory is present only if the input font is a collection; i.e.
if the value of the <a href="#woff20Header">WOFF2 file header</a> "flavor" field is set
to 0x74746366 ('ttcf'). If present, the collection directory follows immediately after
the table directory. The collection directory consists of a CollectionHeader and one or
more CollectionFontEntry records.</p>
<p>If input font is a collection, the <a href="#table_dir_format">table directory</a> contains
a single entry for each unique table in the entire collection, regardless of whether a table
is shared among different fonts in a collection or not. Thus, the table directory for a
font collection compressed with WOFF2 comprises all tables from all fonts contained in the
font collection file.</p>
<p>The Collection directory starts with the Collection Header followed by an array of Collection
Font Entries.</p>
<table>
<col class="type"/><col class="name"/><col class="desc"/>
<tr class="header"><th colspan="3" style="background-color: #F8F8F8">CollectionHeader</th></tr>
<tr><td>UInt32</td><td>version</td><td>The Version of the TTC Header in the original font.</td></tr>
<tr><td>255UInt16</td><td>numFonts</td><td>The number of fonts in the collection.</td></tr>
</table>
<p>Collection font entries specify each font in the collection (defined by CollectionHeader "numFonts"
field). The format of each individual collection font entry is as follows:</p>
<table>
<col class="type"/><col class="name"/><col class="desc"/>
<tr class="header"><th colspan="3" style="background-color: #F8F8F8">CollectionFontEntry</th></tr>
<tr><td>255UInt16</td><td>numTables</td><td>The number of tables in this font</td></tr>
<tr><td>UInt32</td><td>flavor</td><td>The "sfnt version" of the font</td></tr>
<tr><td>255UInt16</td><td>index[numTables]</td><td>The index identifying an entry in the Table Directory for each table in this font (where the index of the first Table Directory entry is zero.)</td></tr>
</table>
<p>A table whose offset is referred to by multiple Offset Tables in the original collection is
considered "shared". An encoder <span class="conform at" id="conform-mustEmitSingleEntryDirectory">
MUST emit a single TableDirectoryEntry for each unique font table defined by its offset</span>,
regardless of whether that table is shared among multiple fonts in a collection or not.
I.e., if a collection contains multiple fonts with their corresponding Table Records referencing
shared font tables with the same offsets, <span class="conform at" id="conform-mustNotDuplicateTables">
the table data in the WOFF2 compressed data stream MUST NOT be duplicated</span>.</p>
<p>If an input font file is a font collection that contains multiple unique
<span class=tt>glyf</span> and <span class=tt>loca</span> tables, the <a href="#glyf_table_format">
transformations</a> described for the <span class=tt>glyf</span> and <span class=tt>loca</span> tables
<span class="conform at" id="conform-mustTransformMultipleGlyfLoca">MUST be applied to each
pair of the tables</span>.Sharing of <span class=tt>glyf</span> and <span class=tt>loca</span>
tables is allowed and encouraged (this is one of the major benefits of a font collection); however,
it is possible that font collections may have two or more pairs of the <span class=tt>glyf</span>
/ <span class=tt>loca</span> tables that may not be shared. When the tables are shared, an encoder
<span class="conform at" id="conform-mustVerifyGlyfLocaShared">MUST verify that both tables are
shared and that both form an associated pair (if more than one pair of <span class=tt>glyf</span>
/ <span class=tt>loca</span> tables are present)</span> and
<span class="conform at" id="conform-mustRejectSingleGlyfLocaShared">MUST reject a collection
containing fonts that share only one of either <span class=tt>glyf</span> or <span class=tt>loca</span></span> table.</p>
<p>An encoder, when processing a font collection, <span class="conform at" id="conform-mustPreserveFontOrder">
MUST preserve the same order of the nested fonts as they are in the input font collection</span> and
<span class="conform at" id="conform-mustRecordCollectionEntryIndex">MUST record the index of
the matching TableDirectoryEntry into the CollectionFontEntry for each font</span>.</p>
<p> A decoder <span class="conform dc" id="conform-mustRestoreCollectionOffsetTables">MUST restore
the collection with the same number of fonts and their corresponding Offset Tables</span>. The Offset
Tables for each font that comprises the output font collection file <span class="conform dc" id="conform-mustFixCollection">
MUST have either the same <span class=tt>numTables</span> as the input collection, or one less if DSIG
was present in the original input Offset Table. If the value of the version field for the TTC Header
in the CollectionHeader is set to "2.0", a decoder MUST either set the TTC Header fields {ulDsigTag,
ulDsigLength, ulDsigOffset} in the output collection
to <span class=tt>null</span> or convert the TTC header format to version 1 (0x00010000)</span>.</p>
<p>A decoder, when processing a font collection, <span class="conform dc" id="conform-mustRestoreFontOrder">
MUST recreate the same order of the nested fonts as they were in the input collection</span>. The tables
within each nested font can be reordered. When processing a font collection with multiple pairs of
'glyf'/'loca' tables present, a decoder <span class="conform ua" id="conform-mustCheckRejectMismatchedTables">
MUST check CollectionFontEntry indices to make sure that referenced 'glyf' and 'loca' tables are paired
with each other, and MUST reject a font collection if a mismatch in table pairing is found</span>. For more
details about table pairs see the <a href="#table_dir_format">table directory</a> format description.
A conforming user agent <span class="conform ua" id="conform-mustLoadFontCollection">MUST be able to load
and use properly formatted font collection file generated by a WOFF2 decoder.</span></p>
</section>
</section><section id="table_format"><h2 id="table_format-0"><span class='secno'>5. </span>Compressed data format</h2>
<p>The CompressedFontData field in a WOFF2 file contains the concatenation of
data for each table in the font, in the order that entries appear in the WOFF2
<a href="#table_dir_format">table directory</a>.
<span class="conform ff" id="conform-noExtraData">There MUST NOT be any extraneous
data between the table entries in the decompressed data stream as defined by the table directory</span>.
If such extraneous data is present <span class="conform ua" id="conform-mustRejectExtraData">
a conforming user agent MUST reject the file as invalid</span>.
<span class="conform ff" id="conform-mustUseBrotli-FontData">The CompressedFontData
stream MUST be compressed using the Brotli compression algorithm
[<cite><a href="#ref-Brotli">Brotli</a></cite>]</span>. If the decompression of the
data block fails for any reason, the WOFF2 file is invalid and
<span class="conform ua" id="conform-mustBeInvalidated-FailDecompress">
MUST NOT be loaded</span>.</p>
<p>The process of decoding the table data in a WOFF2 font file can be specified
by decompressing the byte-level compression of the CompressedFontData field,
yielding a "table data block", then applying additional decoding steps as
described below. An actual implementation is free to combine these steps or
perform some of the steps in an incremental or streaming fashion, but the
results must be consistent with the sequential process as specified here.</p>
<p>Certain tables (such as <span class=tt>glyf</span>, <span class=tt>loca</span> and
<span class=tt>hmtx</span> tables, identified by their corresponding tags), are subject
to additional transforms. If a font table is not transformed, then the table data appears
in the compressed stream in literal form, and occupies origLength bytes of the table data
block. Whether or not the table is transformed, and the version number of the applied transform is
defined by the two most significant flag bits (see <a href="#table_dir_format">subclause 4.1</a>
for details), and the table data must be additionally processed by a transformation specified below.
In this case, the transformed table occupies transformLength bytes of the table data block.</p>
<!-- See www-font comments on the EOFF2 spec specific to changing recommended checkSum behavior
http://lists.w3.org/Archives/Public/www-font/2015OctDec/0000.html -->
<p><span class="conform dc" id="conform-mustProduceOFF">The decompressed and reconstructed
table data MUST be stored in the format specified by the [<cite><a href="#ref-OFF">OFF</a></cite>]
specification.</span> <span class="conform dc" id="conform-mustCalculateCheckSum">Each
reconstructed table directory entry MUST contain a valid 'checkSum' value,
the decoder MUST recalculate the checkSum value for each decoded table.</span>
Also, due to modifying transforms applied to <span class=tt>glyf</span> and <span class=tt>loca</span>
tables, <span class="conform dc" id="conform-mustRecalculateHeadCheckSum">the decoder
MUST recalculate the <span class=tt>checkSumAdjustment</span> value of the entire
font and MUST store the updated value in the <span class=tt>head</span> table.</span></p>
<div class="note">
<p>The known table flag values should not be relied upon in determining the presence of
transformed tables, it is feasible that e.g. the <span class=tt>glyf</span> table can be
represented in the table directory with either flag = 10 and no tag, or with flag = 63
and 'glyf' tag that follows. The combination of flags value that defines a transform
version number and the table tag should be used to determine the applied transform.</p>
</div>
<p><span class="conform ff" id="conform-mustMatchUncompressedSize">The sum of the origLength
(for non-transformed tables) and transformLength (for transformed tables) fields in the
table directory MUST equal the size of the font data block after it has been decompressed
using [<cite><a href="#ref-Brotli">Brotli</a></cite>]</span>.If the size
of the decompressed font data block doesn't match the sum of lengths defined in the table
directory as described above, <span class="conform ua" id="conform-mustBeInvalidated-FailSize">
the WOFF2 file MUST NOT be loaded</span>.</p>
<p>According to the curent version of the WOFF2, a transform can be applied to three types
of tables: <span class=tt>glyf</span>, representing outline data, <span class=tt>loca</span>,
representing the offsets of the individual glyphs within a <span class=tt>glyf</span> table, and
<span class=tt>hmtx</span>, representing glyph horizontal metrics, if these tables are present
in a font. An authoring tool can use any applicable transforms taking into consideration
additional constraints specified in <a href="#loca_table_format">subclause 5.3</a> and
<a href="#table_order">subclause 5.5</a>. The <span class=tt>glyf</span> table transformation
is specified in <a href="#glyf_table_format">subclause 5.1</a>, the <span class=tt>loca</span>
table transformation is specified in <a href="#loca_table_format">subclause 5.3</a>, and the
<span class=tt>hmtx</span> table transformation is specified in
<a href="#hmtx_table_format">subclause 5.4</a>.</p>
<div class="note" id="CFF-de-subroutinization">
<p>CFF table processing and de-subroutinization.</p>
<p>The majority of OpenType fonts with CFF outlines have CFF data subroutinized for more
compact data storage. The experiments conducted as part of WOFF2 development and
evaluation have shown that Brotli compression technology works more efficiently
and produces better compression gains for WOFF2 fonts if the CFF outline data is
de-subroutinized prior to WOFF2 encoding - this will on average reduce the compressed
data size by 5-10%. However, the CFF de-subroutinization will, at the same time, increase
the output file size by ~10%.</p>
<p>Since the CFF pre-processing / de-subroutinization is considered an external step that
can be implemented prior to WOFF2 encoding, it is not covered by this specification.
Font producers have an opportunity to optimize their production process to either
reduce the compressed font size for fastest webfont data transfer at the expense of
increasing the output CFF font size (which will also improve rendering performance)
or to keep subroutinized CFF data to minimize input/output font size.</p>
</div>
<p>The WOFF 2.0 transformations applied to certain tables are designed to reduce and/or
eliminate the built-in redundancies of the SFNT format and restructure the font data
stream for more efficient entropy encoding. As a result, the reconstructed font data
will retain the exact functionality of the input font file, but due to certain possible
encoding variations (such as various levels of optimization of outline point
coordinates in the 'glyf' table, and/or difference in offset calculations of the 'loca'
table) different WOFF2 decoders may produce an output file that will not be a bitwise
match to the input font file. The font tables of the input font file may also be subjected
to reordering operations, which may take place either as a part of the encoding process
or the tables can be reordered by a decoder to comply with the recommended table order
defined by the [<cite><a href="#ref-OFF">OFF</a></cite>] specification – as a result,
even if the content of the font data tables is not affected, the table offsets may change.
The differences in binary font data (however minor, due to significant extent to decoder
optimizations and table reordering) between encoded and decoded font data structures will
invalidate the 'DSIG' table, if one is present. Therefore, the compliant WOFF2 encoder
<span class="conform at" id="conform-mustRemoveDSIG">MUST remove the DSIG table from an input
font data</span>, prior to applying transformations and entropy coding steps.</p>
<p>The WOFF 2.0 encoders <span class="conform at" id="conform-mustSetBit11">MUST also set
bit 11 of the 'flags' field of the <span class=tt>head</span> table</span>
(see [<cite><a href="#ref-OFF">OFF</a></cite>] specification) to indicate that
a recreated font file was subjected to lossless modifying transform.</p>
<section id="glyf_table_format"><h3 id="glyf_table_format-0"><span class='secno'>5.1. </span>Transformed <span class=tt>glyf</span> table format</h3>
<p>The <span class=tt>glyf</span> table data can be presented in the WOFF2 file in one of two
formats defined by the transformation version number (encoded in the table directory flag bits,
see <a href="#table_dir_format">subclause 4.1</a> for details). The transformation version "3"
defines a null transform where the content of the <span class=tt>glyf</span> table is
presented in its original, unmodified format. The transformation version "0", specified below,
is optional and can be applied to eliminate certain redundancies in the <span class=tt>glyf</span>
table data.</p>
<p>The version "0" of the <span class=tt>glyf</span> table transformation (as defined
by the table directory flag bits, see <a href="#table_dir_format">subclause 4.1</a>
for details) specified in this subclause is intended to reduce redundant information
and provide a more efficient encoding of the actual TrueType outlines of glyphs.
The modified transformation is based on a similar transformation described in MicroType
Express [<cite><a href="#ref-mtx">MTX</a></cite>] specification.
The reference to MTX is informative; the details of the modified transformation are
stated below and this section is normative.</p>
<div class="note">
<p>While <span class=tt>glyf</span> table transformation preserves the functionality and fidelity
of rendering for every glyph in a font, it will most likely result in producing a new set of
glyph records that will not be a binary match to the original font. According to the encoding
rules specified in subclause 5.3.3 of [<cite><a href="#ref-OFF">OFF</a></cite>], there may be
multiple valid reconstructions of a glyph record. It is possible that depending on the context
and on the level of optimizations being applied to reconstructed <span class=tt>glyf</span>
table data, the size of the reconstructed table may be greater than, less than, or equal to the
original size of the <span class=tt>glyf</span> table of the input font compressed by WOFF2.
Neither this specification nor the [<cite><a href="#ref-OFF">OFF</a></cite>] standard mandate
specific optimizations being applied on the font data; therefore, it is the responsibility of
WOFF2 decoder implementations to make sure that an adequate amount of memory is allocated when
glyph records are being reconstructed from the WOFF2 file – the original <span class=tt>glyf</span>
table size supplied as an origLength value for the transformed <span class=tt>glyf</span> table can
only be used as a reference point.</p>
</div>
<p>Regardless of the implementation details of the glyph record reconstruction process
and the level of optimizations applied to reconstructed 'glyf' table data
<span class="conform ua" id="conform-mustNotRejectGlyfSizeMismatch">User Agents MUST NOT
reject correctly decoded font file if the size of the reconstructed 'glyf' table doesn't
match the <span class=tt>origLength</span> value encoded as part of the 'glyf' table entry
in WOFF2 Table Directory</span>.</p>
<p>For greater compression effectiveness, the <span class=tt>glyf</span> table is split
into several substreams, to group like data together. The transformed table consists of
a number of fields specifying the size of each of the substreams, followed by the
substreams in sequence. During the decoding process the reverse transformation takes place,
where data from various separate substreams are recombined to create a complete glyph
record for each entry of the original <span class=tt>glyf</span> table.</p>
<table>
<tr class="header"><th colspan="3" style="background-color: #F8F8F8">Transformed <span class=tt>glyf</span> Table</th></tr>
<tr>
<th style="background-color: #F8F8F8; width: 10%;">Data Type</th>
<th style="background-color: #F8F8F8; width: 30%;">Semantic</th>
<th style="background-color: #F8F8F8; width: 60%;">Description and value type (if applicable)</th>
</tr>
<tr><td>Fixed</td><td>version</td><td>= 0x00000000</td></tr>
<tr><td>UInt16</td><td>numGlyphs</td><td>Number of glyphs</td></tr>
<tr><td>UInt16</td><td>indexFormat</td><td>Offset format for <span class=tt>loca</span> table, should be consistent with
<span class=tt>indexToLocFormat</span> of the original <span class=tt>head</span> table (see
[<cite><a href="#ref-OFF">OFF</a></cite>] specification)</td></tr>
<tr><td>UInt32</td><td>nContourStreamSize</td><td>Size of nContour stream in bytes</td></tr>
<tr><td>UInt32</td><td>nPointsStreamSize</td><td>Size of nPoints stream in bytes</td></tr>
<tr><td>UInt32</td><td>flagStreamSize</td><td>Size of flag stream in bytes</td></tr>
<tr><td>UInt32</td><td>glyphStreamSize</td><td>Size of glyph stream in bytes (a stream of variable-length encoded values, see description below)</td></tr>
<tr><td>UInt32</td><td>compositeStreamSize</td><td>Size of composite stream in bytes (a stream of variable-length encoded values, see description below)</td></tr>
<tr><td>UInt32</td><td>bboxStreamSize</td><td>Size of bbox data in bytes representing combined length of bboxBitmap (a packed bit array) and bboxStream (a stream of Int16 values)</td></tr>
<tr><td>UInt32</td><td>instructionStreamSize</td><td>Size of instruction stream (a stream of UInt8 values)</td></tr>
<tr><td>Int16</td><td>nContourStream[]</td><td>Stream of Int16 values representing number of contours for each glyph record</td></tr>
<tr><td>255UInt16</td><td>nPointsStream[]</td><td>Stream of values representing number of outline points for each contour in glyph records</td></tr>
<tr><td>UInt8</td><td>flagStream[]</td><td>Stream of UInt8 values representing flag values for each outline point.</td></tr>
<tr><td>Vary</td><td>glyphStream[]</td><td>Stream of bytes representing point coordinate values using variable length encoding format (defined in <a href="#triplet_decoding">subclause 5.2</a>)</td></tr>
<tr><td>Vary</td><td>compositeStream[]</td><td>Stream of bytes representing component flag values and associated composite glyph data</td></tr>
<tr><td>UInt8</td><td>bboxBitmap[]</td><td>Bitmap (a numGlyphs-long bit array) indicating explicit bounding boxes</td></tr>
<tr><td>Int16</td><td>bboxStream[]</td><td>Stream of Int16 values representing glyph bounding box data</td></tr>
<tr><td>UInt8</td><td>instructionStream[]</td><td>Stream of UInt8 values representing a set of instructions for each corresponding glyph</td></tr>
</table>
<p>The format is best characterized by describing the decoding process, especially
indications of what are valid and invalid data. Note also that this format specifies
the decoded result at the semantic level, not specific byte streams.</p>
<p>Included in the Transformed <span class=tt>glyf</span> Table is a
<span class=tt>bboxBitmap</span> indicating for each glyph
whether it contains an explicitly encoded bounding box, or whether the bounding
box is to be inferred from the coordinate values. The relevant computations to determine
the bounding box status must be performed by both an encoder and a decoder. For each
simple glyph, <span class="conform at" id="conform-mustCalculateOmitBBoxValues">
an encoder MUST calculate the the xMin, yMin, xMax and yMax coordinate values using
all outline points (both on- and off-curve points) and compare the calculated values
with the encoded bounding box info for the glyph. If the glyph bounding box info matches
the calculated values, an encoder MUST omit the bounding box info</span>. Otherwise,
<span class="conform at" id="conform-mustCalculateSetBBoxValues">if the
calculated bounding box values do not equal the glyph values encoded in a font,
an encoder MUST set the corresponding <span class=tt>bboxBitmap</span> flag and record
the original bounding box values in the <span class=tt>bboxStream</span>.</span>
For glyphs records that contain zero contours, <span class="conform at" id="conform-mustRejectNonEmptyBBox">
an encoder MUST check that the glyph bounding box values are all zeros and, if this condition
is not met, MUST reject an input font as invalid.</span> For either an empty glyph or
a glyph with zero contours, <span class="conform at" id="conform-mustClearEmptyBBox">
an encoder MUST always clear the corresponding <span class=tt>bboxBitmap</span> flag.</span>
For a composite glyph, <span class="conform at" id="conform-mustSetCompositeBBoxValues">
an encoder MUST always set the corresponding <span class=tt>bboxBitmap</span> flag and
record the original bounding box values in the <span class=tt>bboxStream</span>.</span></p>
<p><span class="conform ua" id="conform-mustCalculateBBox">A decoder MUST perform similar
calculations if the bounding box is to be inferred. For a given glyph, when a corresponding
bit in <span class=tt>bboxBitmap</span> is not set, the xMin, yMin,
xMax and yMax values MUST be calculated at the time of decoding using all outline
point coordinates</span>. The total number of bytes in <span class=tt>bboxBitmap</span>
is equal to 4 * floor((numGlyphs + 31) / 32). The bits are packed
so that glyph number 0 corresponds to the most significant bit of the first
byte, glyph number 7 corresponds to the least significant bit of the first
byte, glyph number 8 corresponds to the most significant bit of the second
byte, and so on. A bit=1 value indicates an explicitly set bounding box.</p>
<p>Upon reading the Transformed <span class=tt>glyf</span> Table, the decoding process
iterates one glyph at a time. For each glyph, it reads zero or more bytes from each
of the streams referenced in the Transformed <span class=tt>glyf</span> Table.
Also, at the point of reconstructing a glyph, a decoder needs to store for each glyph
the corresponding offset in the new reconstructed glyph table, and this data will
collectively become the contents of the reconstructed <span class=tt>loca</span> table
(see <a href="#loca_table_format">subclause 5.3</a> below for more information about
the reconstruction of the <span class=tt>loca</span> table).</p>
<section id="ReconstructingGlyhs">
<h4 id="ReconstructingGlyhs-0">Reconstruction of Glyph Records</h4>
<p>The reconstruction process begins by performing the following step to determine
the encoded glyph type (simple, composite or empty glyph):</p>
<p>Read a Int16 from the nContour stream. Store this in the numberOfContours
field in the reconstructed TrueType glyph. The interpretation of the field is
the same as the TrueType spec; if it is zero, the glyph is empty. If it is
positive, the glyph is simple and the value represents the number of contours in the
outline. If the nContour value is equal to -1 (0xffff), then the glyph is composite.
</section>
<section id="EmptyGlyph">
<h4 id="EmptyGlyph-0">Decoding of Empty Glyphs</h4>
<p>Reconstruction of an empty glyph (when nContour = 0) is a simple step that involves
incrementing the glyph record count and creating a new entry in the <span class=tt>loca</span>
table where <span class=tt>loca[n] = loca[n-1]</span>. If the <span class=tt>bboxBitmap</span>
flag indicates that the bounding box values are explicitly encoded in the
<span class=tt>bboxStream</span> the decoder
<span class="conform ua" id="conform-mustRejectNonEmptyBBox2"> MUST reject WOFF2 file
as invalid</span>.</p>
</section>
<section id="SimpleGlyph-0">
<h4 id="SimpleGlyph">Decoding of Simple Glyphs</h4>
<p>For a simple glyph (when nContour > 0), the process continues as follows:</p>
<ol>
<li>Read numberOfContours 255UInt16 values from the nPoints stream. Each of
these is the number of points of that contour. Convert this into the
endPtsOfContours[] array by computing the cumulative sum, then subtracting
one. For example, if the values in the stream are [2, 4], then the
endPtsOfContours array is [1, 5]. Also, the sum of all the values in the
array is the total number of points in the glyph, nPoints. In the example