The CFF2 CharString Format (OpenType 1.8.1)
1 Introduction
The CFF2 CharString format provides a method for compact encoding of glyph procedures in an outline font program. CFF2 CharStrings are intended for use only with a CFF2 font table in an OpenType font file.
The CFF2 CharString format is closely descended from the Type 2 CharString format. Type 2 CharStrings are documented in Adobe Technical Note #5177, The Type 2 CharString Format, which is available at Adobe Font Technical Notes.
The motivation for developing the CFF2 CharString format was twofold:
- Reduce the size of CFF2 fonts by removing all the data which is duplicated elsewhere in the OpenType font, or is not used in the context of OpenType font files.
- Add support for OpenType Font Variations. (See the chapter OpenType Font Variations Overview for a general overview and a complete list of the tables required to support a variable font.)
Accordingly, the CFF2 CharString format has added some new operators, and has removed many more operators. However, the encoding of operators and operands is the same between Type 2 and CFF2 CharStrings; interpreters will need relatively little change to process both formats. See Appendix C Changes From Type 2 CharStrings for a complete list of the differences between Type 2 and CFF2 CharString formats. CFF2 CharStrings can be converted to Type 2 CharStrings with loss of only the variation data.
This document only describes how CFF2 CharStrings are encoded, and does not attempt to explain the reasons for choosing various options. CFF2 CharStrings are based on Type 1 font concepts, and this document assumes familiarity with the Type 1 font format specification. For more information, please see Adobe Type 1 Font Format at Adobe Font Technical Notes. Also, familiarity with the CFF2 table format is assumed; please see the chapter Compact Font Format Version 2 ('CFF2') for details.
2 CFF2 CharStrings
The following sections describe the general concepts of encoding a CFF2 CharString.
2.1 Hints
The CFF2 CharString format supports six hint operators: hstem, vstem, hstemhm, vstemhm, hintmask, and cntrmask. The hint information must be declared at the beginning of a CharString (see section 3.1) using the hstem, vstem, hstemhm, and vstemhm operators, each of which may each take arguments for multiple stem hints.
CFF2 hint operators aid the rasterizer in recognizing and controlling stems and counter areas within a glyph. A stem generally consists of two positions (edges) and the associated width. Edge stem hints help to control character features where there is only a single edge (see section 4.3). The CFF2 CharString format includes edge hints, which are equivalent to the Type 1 concept of ghost hints (see the section on ghost hints in the Adobe Type 1 Font Format). They are used to locate an edge rather than a stem that has two edges. A stem width value of -20 is reserved for a top or right edge, and a value of -21 for a bottom or left edge. The operation of hints with other negative width values is undefined.
hintmask
The hintmask operator has the same function as that described in “Changing Hints within a Character,” section 8.1 of the Adobe Type 1 Font Format. It provides a means for activating or deactivating stem hints so that only a set of non-overlapping hints are active at one time. The hintmask operator is followed by one or more data bytes that specify the stem hints which are to be active for the subsequent path construction. The number of data bytes must be exactly the number needed to represent the number of stems in the original stem list (those stems specified by the hstem, vstem, hstemhm, and vstemhm commands), using one bit in the data bytes for each stem in the original stem list. Bits with a value of one indicate stems that are active, and a value of zero indicates stems that are inactive.
cntrmask
The cntrmask (countermask) hint causes arbitrary but nonoverlapping collections of counter spaces in a character to be controlled in a manner similar to how stem widths are controlled by the stem hint commands. (For more information, see Adobe Technical Note #5015, The Type 1 Font Format Supplement, at Adobe Font Technical Notes.) The cntrmask operator is followed by one or more data bytes that specify the index number of the stem hints on both sides of a counter space. The number of data bytes must be exactly the number needed to represent the number of stems in the original stem list (those stems specified by the hstem, vstem, hstemhm, or vstemhm commands), using one bit in the data bytes for each stem in the original stem list.
For the example shown in Figure 1, the stem list for the glyph would be:
- H1 H2 H3 H4 H5 H6 H7 H8 V1 V2 V3 V4 V5
and the following cntrmask commands would be used to control the counter spaces between those stems:
-
cntrmask 0xB5 0xE8 (H1 H3 H4 H6 H8 V1 V2 V3 V5) cntrmask 0x4A 0x00(H2 H5 H7)
The bits set in the data bytes indicate that the corresponding stem hints delimit the desired set of counters. Hints specified in the first command have a higher priority than those in the second command. Notice that the V4 stem does not delimit an appropriate counter space, and hence is not referenced in this example.
Note that hints are just that, hints, or recommendations. They are additional guidelines to an intelligent rasterizer.
If the font’s LanguageGroup is not equal to 1 (a LanguageGroup value of 1 indicates complex Asian language glyphs), the cntrmask operator, with three stems, can be used in place of the hstem3 and vstem3 hints in the Type 1 format, as long as the related conditions specified in the Type 1 specification are met. For more information on Counter Control hints, see Adobe Technical Note #5015, Type 1 Font Format Supplement.
2.2 The Flex Mechanism
The flex mechanism is provided to improve the rendering of shallow curves, representing them as line segments at small sizes rather than as small humps or dents in the character shape. It is essentially a path construction mechanism: the arguments describe the construction of two curves, with an additional argument that is used as a hint for when the curves should be rendered as a straight line at smaller sizes and resolutions.
The CFF2 flex mechanism is general; there are no restrictions on what type or orientation of curve may be expressed with a flex operator. The flex operator is used for the general case; special cases can use the flex1, hflex, or hflex1 operators for a more efficient encoding. Figure 2 shows an example of the flex mechanism used for a horizontal curve, and Figure 3 shows an example of flex curves at non-standard angles.
The flex operators can be used for any curved character feature, in any orientation or depth, that meets the following requirements:
- The character feature must be capable of being represented as exactly two curves, drawn by two rrcurveto operators.
- The curves must meet at a common point called the joining point.
- The length of the combined curve must exceed its depth.
2.3 Subroutines
A CFF2 font program can use subroutines to reduce the storage requirements by combining the program statements that describe common elements of the characters in the font.
A subroutine is typically a sequence of CharString bytes representing a sub-program that occurs in more than one place in a font’s CharString data. Local subroutines may be called from within the same Font DICT and global subroutines may be shared across Font DICTs.
Subroutines may contain sections of CharStrings, and are encoded the same as CFF2 CharStrings. They are called with the callsubr (for a local subroutine) or callgsubr (for a global subroutine) operator, using a biased index into the local or global Subrs array as the argument.
CharString subroutines may call other subroutines, to the depth allowed by the implementation limits (see Appendix B). A subroutine returns when the interpreter reaches the end of its byte-string.
3 CharString Encoding
A CFF2 CharString program is a sequence of unsigned 8-bit bytes that encode numbers and operators. The byte value specifies a operator, a number, or subsequent bytes that are to be interpreted in a specific manner.
The bytes are decoded into numbers and operators. The CFF2 CharString interpreter is required to count the number of arguments on the argument stack. It can thus detect additional sets of arguments for a single operator. The stack depth implementation limit is specified in Appendix B.
A number, decoded from a CharString, is pushed onto the CFF2 argument stack. An operator expects its arguments in order from this argument stack with all arguments generally taken from the bottom of the stack (first argument bottom-most); however, some operators, particularly the subroutine operators, normally work from the top of the stack. If an operator returns results, they are pushed onto the CFF2 argument stack (last result topmost).
In the following discussion, all numeric constants are decimal numbers, except where indicated.
3.1 CFF2 CharString Organization
The sequence and form of a CFF2 CharString program may be represented as:
- {hs* vs* cm* hm* mt subpath}? {mt subpath}*
Where:
-
hs = hstem or hstemhm command
vs = vstem or vstemhm command
cm = cntrmask operator
hm = hintmask operator
mt = moveto (i.e. any of the moveto) operators
subpath = refers to the construction of a subpath (one complete closed contour), which may include hintmask operators where appropriate.
and the following symbols indicate specific usage:
-
* zero or more occurrences are allowed
? zero or one occurrences are allowed
+ one or more occurrences are allowed
{ } indicates grouping
Stated in words, the constraints on the sequence of operators in a CharString are as follows:
CFF2 CharStrings must be structured with operators, or classes of operators, sequenced in the following specific order:
- Hints: zero or more of each of the following hint operators, in exactly the following order: hstem, hstemhm, vstem, vstemhm, cntrmask, hintmask. Each entry is optional, and each may be expressed by one or more occurrences of the operator. The hint operators cntrmask and/or hintmask must not occur if the CharString has no stem hints.
- Path Construction: Zero or more path construction operators are used to draw the path of the character; the second and all subsequent subpaths must also begin with one of the moveto operators. The hintmask operator may be used as needed.
Any operand for the hint and path construction operators may be replaced by the blend operator and its operands. If a vsindex operator is used, it must be used only once, and prior to any blend operator. Blend operators may not be nested. Hint mask bytes and subroutine indices may not be blended.
Note: CharStrings may contain subr and gsubr calls as desired at any point between complete tokens. This means that a subr (gsubr) call must not occur between the bytes of a multibyte number or operator, nor between the bytes of a multibyte command (for example, hintmask and cntrmask).
3.2 CharString Number Encoding
A CharString byte containing the values from 32 through 254 inclusive indicates an integer. These values are decoded in three ranges (also see Table 1):
- A CharString byte containing a value,
v
, between 32 and 246 inclusive, specifies the integerv - 139
. Thus, the integer values from −107 through 107 inclusive may be encoded in a single byte. -
A CharString byte containing a value,
v
, between 247 and 250 inclusive, indicates an integer involving the next byte,w
, according to the formula,(v − 247) * 256 + w + 108
. The integer values between 108 and 1131 inclusive can be encoded in 2 bytes in this manner. -
A CharString byte containing a value,
v
, between 251 and 254 inclusive, indicates an integer involving the next byte,w
, according to the formula,−[(v − 251) * 256] − w − 108
. The integer values between −1131 and −108 inclusive can be encoded in 2 bytes in this manner.
If the CharString byte contains the value 255, the next four bytes contain a Fixed value (a signed fixed-point number with 16 fractional bits).
Note: The CFF2 interpretation of a number encoded in five-bytes (those with an initial byte value of 255) differs from how it is interpreted in the Type 1 format.
In addition to the numeric representations listed above, numbers between -32768 and +32767 can be represented using the operator (28) followed by an int16. This allows a more compact representation of large numbers which occur occasionally in fonts, but perhaps more importantly, this will allow more compact encoding of numbers which may be used as arguments to callsubr and callgsubr.
CharString Byte Value | Interpretation | Number Range Represented | Bytes Required |
---|---|---|---|
0 to 11 | operators | operators 0 to 11 | 1 |
12 | escape: next byte interpreted as additional operators | additional 0 to 255 range for operator codes | 2 |
13 to 18 | operators | operators 13 to 18 | 1 |
19, 20 | operators (hintmask and cntrmask) | operators 19, 20 | 2 or more |
21 to 27 | operators | operators 21 to 27 | 1 |
28 | next 2 bytes are an int16 | -32768 to +32767 | 3 |
29 to 31 | operators | operators 29 to 31 | 1 |
32 to 246 | result = v – 139 | -107 to +107 | 1 |
247 to 250 | with next byte, w, result = (v – 247) * 256 + w + 108 | +108 to +1131 | 2 |
251 to 254 | with next byte, w, result = -[(v – 251) * 256] – w – 108 | -108 to -113 | 2 |
255 | next 4 bytes are a Fixed value | 16-bit signed integer with 16 bits of fraction | 5 |
3.3 CharString Operator Encoding
CharString operators are encoded in one or two bytes. Not all possible operator encoding values are defined. See Appendix A for a list of operator encoding values. When an unrecognized operator is encountered, it is ignored and the stack is cleared.
If an operator byte contains the value 12, then the value in the next byte specifies an operator. This escape mechanism allows many extra operators to be encoded.
4 CharString Operators
CFF2 CharString operators are divided into four groups, classified by function:
- path construction
- hints
- subroutine
- variation data support
The following definitions use a format similar to that used in the PostScript Language Reference Manual. Parentheses following the operator name either include the operator value that represents this operator in a CharString byte, or the two values (beginning with 12) that represent a two-byte operator.
Many operators take their arguments from the bottom-most entries in the CFF2 argument stack; this behavior is indicated by the stack bottom symbol ‘|-’ appearing to the left of the first argument. Operators that clear the argument stack are indicated by the stack bottom symbol ‘|-’ in the result position of the operator definition.
Because of this stack-clearing behavior, in general, arguments are not accumulated on the CFF2 argument stack for later removal by a sequence of operators, arguments generally may be supplied only for the next operator. Notable exceptions occur with subroutine calls and with the blend operator. All stack operations must observe the stack limit (see Appendix B).
4.1 Path Construction Operators
In a CFF2 CharString, a path is constructed by sequential application of one or more path construction operators. The current point is initially the (0, 0) point of the character coordinate system. The operators listed in this section cause the current point to change, either by a moveto operation, or by appending one or more curve or line segments to the current point. Upon completion of the operation, the current point is updated to the position to which the move was made, or to the last point on the segment or segments.
Many of the operators can take multiple sets of arguments, which indicate a series of path construction operations. The number of operations is limited only by the limit on the stack size (see Appendix B).
All Bézier curve path segments are drawn using six arguments, dxa, dya, dxb, dyb, dxc, dyc; where dxa and dya are relative to the current point, and all subsequent arguments are relative to the previous point. A number of the curve operators take advantage of the situation where some tangent points are horizontal or vertical (and hence the value is zero), thus reducing the number of arguments needed.
The flex operators are considered path construction commands because they specify the drawing of two curves. There is also an additional argument that serves as a hint as to when to render the curves as a straight line at small sizes and low resolutions.
The following are three types of moveto operators. For the initial moveto operator in a CharString, the arguments are relative to the (0, 0) point in the character’s coordinate system; subsequent moveto operators’ arguments are relative to the current point.
Every character path and subpath must begin with one of the moveto operators. If the current path is open when a moveto operator is encountered, the path is closed by performing a lineto operation to the previous moveto coordinates before performing the moveto operation. The inserted lineto operation does not change the current point.
- rmoveto
-
|- dx1 dy1 rmoveto (21) |-
Moves the current point to a position at the relative coordinates (dx1, dy1).
- hmoveto
-
|- dx1 hmoveto (22) |-
Moves the current point dx1 units in the horizontal direction.
- vmoveto
-
|- dy1 vmoveto (4) |-
Moves the current point dy1 units in the vertical direction.
- rlineto
-
|- {dxa dya}+ rlineto (5) |-
Appends a line from the current point to a position at the relative coordinates dxa, dya. Additional rlineto operations are performed for all subsequent argument pairs. The number of lines is determined from the number of arguments on the stack.
- hlineto
-
|- dx1 {dya dxb}* hlineto (6) |-
|- {dxa dyb}+ hlineto (6) |-
Appends a horizontal line of length dx1 to the current point. With an odd number of arguments, subsequent argument pairs are interpreted as alternating values of dy and dx, for which additional lineto operators draw alternating vertical and horizontal lines. With an even number of arguments, the arguments are interpreted as alternating horizontal and vertical lines. The number of lines is determined from the number of arguments on the stack.
- vlineto
-
|- dy1 {dxa dyb}* vlineto (7) |-
|- {dya dxb}+ vlineto (7) |-
Appends a vertical line of length dy1 to the current point. With an odd number of arguments, subsequent argument pairs are interpreted as alternating values of dx and dy, for which additional lineto operators draw alternating horizontal and vertical lines. With an even number of arguments, the arguments are interpreted as alternating vertical and horizontal lines. The number of lines is determined from the number of arguments on the stack.
- rrcurveto
-
|- {dxa dya dxb dyb dxc dyc}+ rrcurveto (8) |-
Appends a Bézier curve, defined by dxa...dyc, to the current point. For each subsequent set of six arguments, an additional curve is appended to the current point. The number of curve segments is determined from the number of arguments on the number stack and is limited only by the size of the number stack.
- hhcurveto
-
|- dy1? {dxa dxb dyb dxc}+ hhcurveto (27) |-
Appends one or more Bézier curves, as described by the dxa...dxc set of arguments, to the current point. For each curve, if there are 4 arguments, the curve starts and ends horizontal. The first curve need not start horizontal (the odd argument case). Note the argument order for the odd argument case.
- hvcurveto
-
|- dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? hvcurveto (31) |-
|- {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? hvcurveto (31) |-
Appends one or more Bézier curves to the current point. The tangent for the first Bézier must be horizontal, and the second must be vertical (except as noted below).
If there is a multiple of four arguments, the curve starts horizontal and ends vertical. Note that the curves alternate between start horizontal, end vertical, and start vertical, and end horizontal. The last curve (the odd argument case) need not end horizontal/vertical.
- rcurveline
-
|- {dxa dya dxb dyb dxc dyc}+ dxd dyd rcurveline (24) |-
Is equivalent to one rrcurveto for each set of six arguments dxa...dyc, followed by exactly one rlineto using the dxd, dyd arguments. The number of curves is determined from the count on the argument stack.
- rlinecurve
-
|- {dxa dya}+ dxb dyb dxc dyc dxd dyd rlinecurve (25) |-
Is equivalent to one rlineto for each pair of arguments beyond the six arguments dxb...dyd needed for the one rrcurveto command. The number of lines is determined from the count of items on the argument stack.
- vhcurveto
-
|- dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? vhcurveto (30) |-
|- {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? vhcurveto (30) |-
Appends one or more Bézier curves to the current point, where the first tangent is vertical and the second tangent is horizontal. This command is the complement of hvcurveto; see the description of hvcurveto for more information.
- vvcurveto
-
|- dx1? {dya dxb dyb dyc}+ vvcurveto (26) |-
Appends one or more curves to the current point. If the argument count is a multiple of four, the curve starts and ends vertical. If the argument count is odd, the first curve does not begin with a vertical tangent.
- flex
-
|- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
Causes two Bézier curves, as described by the arguments (as shown in Figure 2 below), to be rendered as a straight line when the flex depth is less than fd /100 device pixels, and as curved lines when the flex depth is greater than or equal to fd/100 device pixels. The flex depth for a horizontal curve, as shown in Figure 2, is the distance from the join point to the line connecting the start and end points on the curve. If the curve is not exactly horizontal or vertical, it must be determined whether the curve is more horizontal or vertical by the method described in the flex1 description, below, and as illustrated in Figure 3.
Note: In cases where some of the points have the same x or y coordinate as other points in the curves, arguments may be omitted by using one of the following forms of the flex operator: hflex, hflex1, or flex1.
- hflex
-
|- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
Causes the two curves described by the arguments dx1...dx6 to be rendered as a straight line when the flex depth is less than 0.5 (that is, fd is 50) device pixels, and as curved lines when the flex depth is greater than or equal to 0.5 device pixels.
hflex is used when the following are all true:
a) The starting and ending points, first and last control points have the same y value.
b) The joining point and the neighbor control points have the same y value.
c) The flex depth is 50. - hflex1
-
|- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
Causes the two curves described by the arguments to be rendered as a straight line when the flex depth is less than 0.5 device pixels, and as curved lines when the flex depth is greater than or equal to 0.5 device pixels.
hflex1 is used if the conditions for hflex are not met but all of the following are true:
a) The starting and ending points have the same y value.
b) The joining point and the neighbor control points have the same y value.
c) The flex depth is 50. - flex1
-
|- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
Causes the two curves described by the arguments to be rendered as a straight line when the flex depth is less than 0.5 device pixels, and as curved lines when the flex depth is greater than or equal to 0.5 device pixels.
The d6 argument will be either a dx or dy value, depending on the curve (see Figure 3). To determine the correct value, compute the distance from the starting point (x, y), the first point of the first curve, to the last flex control point (dx5, dy5) by summing all the arguments except d6; call this (dx, dy). If abs(dx) > abs(dy), then the last point’s x-value is given by d6, and its y-value is equal to y. Otherwise, the last point’s x-value is equal to x and its y-value is given by d6.
flex1 is used if the conditions for hflex and hflex1 are not met but all of the following are true:
a) The starting and ending points have the same x or y value.
b) The flex depth is 50.
4.2 Finishing a CharString Outline Definition
CFF2 CharStrings differ from Type 2 CharStrings in that there is no operator for finishing a CharString outline definition.The end of the CharString byte string implies the end of the last subpath, and serves the same purpose as the Type 2 endchar operator. If the last operator in a CharString is a call(g)subr, then the CharString ends when that subroutine ends.
The smallest legal CharString is simply an empty byte string.
4.3 Hint Operators
All hints must be declared at the beginning of the CharString program program (see section 3.1 for details).
- hstem
-
|- y dy {dya dyb}* hstem (1) |-
Specifies one or more horizontal stem hints (see the following section for more information about horizontal stem hints). This allows multiple pairs of numbers, limited by the stack depth, to be used as arguments to a single hstem operator.
It is required that the stems are encoded in ascending order (defined by increasing bottom edge). The encoded values are all relative; in the first pair, y is relative to 0, and dy specifies the distance from y. The first value of each subsequent pair is relative to the last edge defined by the previous pair.
A width of -20 specifies the top edge of an edge hint, and -21 specifies the bottom edge of an edge hint. All other negative widths have undefined meaning.
Figure 4 shows an example of the encoding of a character stem that uses top and bottom edge hints. The edge stem hint serves to control the position of the edge of the stem in situations where controlling the stem width is not the primary purpose.
The encoding for the edge stem hints shown in Figure 4 would be:
121 -21 400 -20 hstem
- vstem
-
|- x dx {dxa dxb}* vstem (3) |-
Specifies one or more vertical stem hints between the x coordinates x and x+dx, where x is relative to the origin of the coordinate axes.
It is required that the stems are encoded in ascending order (defined by increasing left edge). The encoded values are all relative; in the first pair, x is relative to 0, and dx specifies the distance from x. The first value of each subsequent pair is relative to the last edge defined by the previous pair.
A width of -20 specifies the right edge of an edge hint, and -21 specifies the left edge of an edge hint. All other negative widths have undefined meaning.
It is important to note that hstem hints must not overlap other hstem hints, and similarly, vstem hints must not overlap other vstem hints. If overlapping hints are needed, then the overlapping hints must be defined by using the hstemhm or vstemhm operator rather than the hstem or vstem operator. In addition, the hints must be selectively applied by using the hintmask operator to select the active hint so that no overlapping horizontal or vertical hints are active at the same time. See below for details on the hintmask operator and the example in figure 6.
Figure 5 shows an example of overlapping horizontal hints on a sample feature of a character outline.
The encoding for the two hints shown in Figure 5 would be:
280 100 -70 40 hstemhm
Again, note that the hintmask operator, not shown here, must also be used in conjunction with these hints.
- hstemhm
-
|- y dy {dya dyb}* hstemhm (18) |-
Has the same meaning as hstem (1), except that it must be used in place of hstem if the CharString contains one or more hintmask operators.
- vstemhm
-
|- x dx {dxa dxb}* vstemhm (23) |-
Has the same meaning as vstem (3), except that it must be used in place of vstem if the CharString contains one or more hintmask operators.
- hintmask
-
|- hintmask (19) mask |-
Specifies which hints are active and which are not active. If any hints overlap, hintmask must be used to establish a non-overlapping subset of hints. hintmask may occur any number of times in a CharString. Path operators occurring after a hintmask are influenced by the new hint set, but the current point is not moved. If stem hint zones overlap and are not properly managed by use of the hintmask operator, the results are undefined.
The mask data bytes are defined as follows:
- The number of data bytes is exactly the number needed, one bit per hint, to reference the number of stem hints declared at the beginning of the CharString program.
- Each bit of the mask, starting with the most-significant bit of the first byte, represents the corresponding hint zone in the order in which the hints were declared at the beginning of the CharString.
- For each bit in the mask, a value of ‘1’ specifies that the corresponding hint shall be active. A bit value of ‘0’ specifies that the hint shall be inactive.
- Unused bits in the mask, if any, must be zero.
If hstem and vstem hints are both declared at the beginning of a CharString, and this sequence is followed directly by the hintmask or cntrmask operators, then the vstem hint operator or, if applicable, the vstemhm operator) need not be included. For example, Figure 6 shows part of a character with hstem and vstem hints.
Figure 6 shows two overlapping hstem hints plus one vstem hint. If only these three hints are defined, and the first active hint group is to be the hstem from 310 to 385 and the vstem from 400 to 450, then the hints would be specified as:
280 100 -70 40 hstemhm 400 50 hintmask 0x60
where the hex data 0x60 (01100000) indicates which hints are active at the beginning of the path construction.
Note that the hstemhm is used to indicate that hint substitution is used.
- cntrmask
-
|- cntrmask (20) mask |-
Specifies the counter spaces to be controlled, and their relative priority. The mask bits in the bytes, following the operator, reference the stem hint declarations; the most significant bit of the first byte refers to the first stem hint declared, through to the last hint declaration. The counters to be controlled are those that are delimited by the referenced stem hints. Bits set to 1 in the first cntrmask command have top priority; subsequent cntrmask commands specify lower priority counters (see Figure 1 and the accompanying example).
4.4 Subroutine Operators
The numbering of subroutines is encoded more compactly by using the negative half of the number space, which effectively doubles the number of compactly encodable subroutine numbers. The bias applied depends on the number of subrs (gsubrs). If the number of subrs (gsubrs) is less than 1240, the bias is 107. Otherwise if it is less than 33900, it is 1131; otherwise it is 32768. This bias is added to the encoded subr (gsubr) number to find the appropriate entry in the subr (gsubr) array.
- callsubr
-
subr# callsubr (10)
Calls a CharString subroutine with index subr# (actually the subr number plus the subroutine bias number, as described in section 2.3) in the Subrs array. Each element of the Subrs array is a CharString encoded like any other CharString. The subroutine call removes only the subr# and operator from the stack, so arguments pushed on the stack are available to any operators in the subroutine. Similarly, values pushed from inside the subroutine are available after the subroutine returns to the caller. Calling an undefined subr (gsubr) has undefined results.
These subroutines are generally used to encode sequences of path operators that are repeated throughout the font program, for example, serif outline sequences. Subroutine calls may be nested to the depth specified in the implementation limits in Appendix B.
- callgsubr
-
globalsubr# callgsubr (29)
Operates in the same manner as callsubr except that it calls a global subroutine.
4.5 Variation Data Operators
In order to support variation data in CFF2 CharStrings, two new operators are added in CFF2 CharStrings: vsindex and blend.
A variable font holds data representing the equivalent of several distinct design variations, and uses algorithms for interpolation — or blending — between these designs to derive a continuous range of design instances. This allows an entire family of fonts to be represented by a single variable font. For example, a variable font may contain data equivalent to Light and Heavy designs from a family, which can then be interpolated to derive instances for any weight in a continuous range between Light and Heavy.
See the chapter OpenType Font Variations Overview for general background on OpenType Font Variations, details on the tables used to support a variable font, terminology, and a specification of the interpolation algorithm used to blend values to derive specific design instances.
Outline data for a variable font in the CFF2 format are built much like a non-variable CFF2 table would be built, with exactly the same structure and operators as would be used for the default design representation. However, wherever a value occurs in the default design, the single value for the one design is supplemented with a set of delta values, followed by the blend operator. (For efficiency, a single blend operator may follow a series of such delta sets, rather than after each individual set.) Unlike other CharString operators, blend does not clear the stack when it is processed. The result of the blend operator remains on the stack to be processed by the following operator.
Within a variable font, different glyphs can use different sets of regions and associated delta values for the blending operation. When processing a given glyph, the interpreter must determine which set to use. These sets are stored in the CFF2 table in an ItemVariationStore structure. The ItemVariationStore contains one or more ItemVariationData subtables, each of which contains a list of Variation Regions. The first ItemVariationData subtable (index 0) is used by default when no other subtable has been specified. When an ItemVariationData subtable other than the default is needed for a set of delta values, the vsindex operator is used. When this operator is used in a Private DICT to set a non-default itemVariationData index, this then becomes the default Item Variation Data index for not only the Private DICT, but also for all CharStrings that reference that Private DICT. When the vsindex operator is used in a CharString, it supersedes any vsindex from the private DICT. All private DICTs and CharStrings in a CFF2 table share the same ItemVariationStore.
Syntax for Font Variations support operators.
- vsindex
-
|- ivs vsindex (15) |-
Selects the ItemVariationData subtable to be used for blending in this CharString; the ivs argument is the ItemVariationData index. When used, vsindex must precede the first blend operator, and may occur only once in the CharString. If the vsindex operator is not present in the CharString, then the ItemVariationData index is inherited from the Private DICT vsindex value. If the vsindex operator is not present in a Private DICT, then the default value is 0.
- blend
-
num(0)…num(n-1), delta(0,0)…delta(k-1,0), delta(0,1)…delta(k-1,1) … delta(0,n-1)…delta(k-1,n-1) n blend (16) val(0)…val(n-1)
For k regions, produces n interpolated result value(s) from n*(k + 1) operands.
The blend operator is used in conjunction with other operators to produce interpolated input values for the other operator that are applicable for the currently-selected variation instance. The variation-instance design vector is specified in the interpreter, external to the font program, and the interpreter applies the design vector when processing the blend operator to calculate the appropriate interpolated values.
Blending is supported only for design space coordinate values, such as the operands for the hint and path construction operators. The last operand on the stack, n, specifies the number of operands that will be left on the stack for the next operator. (For example, if the blend operator is used in conjunction with the hflex operator, which requires 6 operands, then n would be set to 6.) This operand also informs the handler for the blend operator that the operator is preceded by n+1 sets of operands.
The first set of operands, num(0)…num(n-1), contains the n operands for the following CharsString operator that are applicable to the default variation instance.
There are n additional sets of operands, delta(0,i)…delta(k-1,i), one corresponding to each of the values in the first set of operands. Each set contains the variation adjustment deltas for the given operand, with each delta being associated with a different region of the design-variation space. (See the “Variation Space, Default Instances and Adjustment Deltas” and “Variation Data” sections in the OpenType Font Variations Overview chapter for more information regarding regions and associated adjustment deltas.) Each of these additional operand sets has k operands, where k represents the number of regions for which variation adjustment deltas are defined. This value is determined by the ItemVariationData subtable that is currently active for the CharString (see vsindex).
Thus, the first set contains n operands, and the following sets contain n*k operands, giving a total of n*(k+1) operands that precede the final n operand.
The blend handler will compare the currently-selected variation-instance design vector with the coordinates for each region to compute an interpolation scalar factor for each given region. This is then applied to the adjustment deltas for the region to compute a net adjustment delta to be applied to the default value. For more details on the interpolation algorithm, see Algorithm for Interpolation of Instance Values in the OpenType Font Variations Overview chapter.
As an example of the blend operator, consider use of blend to interpolate inputs to an rmoveto operator. The rmoveto operator takes two operands, x and y, and so the n argument for the blend operator will be set to 2.
Suppose, also, that the font has weight and width variation axes, and that the default variation instance of the font is Regular. In addition, suppose that this CharString uses deltas for three regions, the extreme points of which correspond to Light and Bold (extremes for the weight axis), and also Condensed (extreme for the width axis, opposite of Regular which has normal width). Thus, the value of k is 3.
Now suppose that the x and y arguments for the removeto operator that would be needed for the Regular, Light, Bold and Condensed variation instances are as follows:
-
Regular: 100 200 rmoveto
Light: 100 150 rmoveto
Bold: 100 300 rmoveto
Condensed: 50 100 rmoveto
For the blend operator, the first set of arguments will be the rmoveto arguments required for the default instance:
100 200
The following sets of blend arguments are the set of deltas for the three regions, with one set of deltas for each of the rmoveto arguments. As an example of a delta, the x argument for Regular — the default instance — is 100, and the x argument required for Condensed is 50, and so the x-argument delta for the 3rd region (index 2) is -50. Thus, the set of deltas for the first rmoveto operand for all three regions are:
0 0 -50
And the set of deltas for the second rmoveto operand for all three regions are:
-50 100 -100
Combining this together, the CharString sequence for the blend and rmoveto operator combination will be as follows; parentheses are added to demarcate each of the blend operand sets:
(100 200) (0 0 -50) (-50 100 -100) 2 blend rmoveto
When the blend operator is processed for a particular variation instance, the handler will calculate scalar coefficients for each region and then apply each scalar to the deltas for the corresponding region. For instance, if the selected instance is midway between Regular and Light on the weight axis and normal width on the width axis, then the scalar for region 0 will be 0.5, while the scalars for regions 1 and 2 will each be 0.0. The blend operator will interpolate the rmoveto arguments as follows:
-
x = 100 + (0 * 0.5) + (0 * 0.0) + (-50 * 0.0) = 100
y = 200 + (-50 * 0.5) + (100 * 0.0) + (-100 * 0.0) = 175
These blend results are pushed onto the stack. Thus, the rmoveto operation that will be performed is:
100 175 rmoveto
Appendix A. CFF2 CharString Command Codes
One-byte CFF2 Operators
Dec | Hex | Operator | Note |
---|---|---|---|
0 | 00 | <reserved> | |
1 | 01 | hstem | |
2 | 02 | <reserved> | |
3 | 03 | vstem | |
4 | 04 | vmoveto | |
5 | 05 | rlineto | |
6 | 06 | hlineto | |
7 | 07 | vlineto | |
8 | 08 | rrcurveto | |
9 | 09 | <reserved> | |
10 | 0a | callsubr | |
11 | 0b | <reserved> | |
12 | 0c | escape | First byte of a 2-byte operator. |
13 | 0d | <reserved> | |
14 | 0e | <reserved> | |
15 | 0f | vsindex | |
16 | 10 | blend | |
17 | 11 | <reserved> | |
18 | 12 | hstemhm | |
19 | 13 | hintmask | |
20 | 14 | cntrmask | |
21 | 15 | rmoveto | |
22 | 16 | hmoveto | |
23 | 17 | vstemhm | |
24 | 18 | rcurveline | |
25 | 19 | rlinecurve | |
26 | 1a | vvcurveto | |
27 | 1b | hhcurveto | |
28 | 1c | <numbers> | First byte of a 3-byte sequence specifying an unsigned integer value (next two bytes are a uint16). |
29 | 1d | callgsubr | |
30 | 1e | vhcurveto | |
31 | 1f | hvcurveto | |
32 to 246 | 20 to f6 | <numbers> | |
247 to 254 | f7 to fe | <numbers> | First byte of a 2-byte sequence specifying a number. |
255 | ff | <number> | First byte of a 5-byte sequence specifying a Fixed value. |
Two-byte CFF2 Operators
Dec | Hex | Operator |
---|---|---|
12 0 to 12 33 | 0c 00 to 0c 21 | <reserved> |
12 34 | 0c 22 | hflex |
12 35 | 0c 23 | flex |
12 36 | 0c 24 | hflex1 |
12 37 | 0c 25 | flex1 |
12 38 to 12 255 | 0c 26 to 0c ff | <reserved> |
Appendix B. CFF2 CharString Implementation Limits
The following are the implementation limits of the CFF2 CharString interpreter:
Description | Limit |
---|---|
Argument stack | 1931 |
Number of stem hints (H/V total) | 96 |
Subr nesting, stack limit | 10 |
CharString length | 65535 |
maximum (g)subrs count | 65536 |
- 1. The argument stack limit is a default value. This may be increased by the maxstack operator in the CFF2 Top DICT to an upper limit of 513. This operator may be used only once, and will set the max stack value for all CharStrings in the font.
Appendix C Changes From Type 2 CharStrings
- CFF2 CharStrings do not contain a value for width.
- The CharString operator set is extended in CFF2 to include the blend and vsindex operators. These work as described above in section 4.5 Variation Data Operators. The CFF2 CharString operator code for blend is 16, and for vsindex is 15.
- The Type 2 operators endchar and return are removed.
- The Type 2 logic, storage, and math operators are removed.
- For CFF2 fonts, the fill rule for CharStrings must always be the nonzero winding number rule, rather than the even-odd rule. Overlap subpaths are permitted.
- The default maximum stack depth allowed is increased from 48 to 193.
Appendix D Changes Since Earlier Versions
The following changes and revisions have been made since the initial publication in OpenType 1.8.
- Initial publication: OpenType 1.8 (September 2016). See Appendix C, Changes from Type 2 CharStrings.
-
OpenType 1.8.1 (January 2017):
- All references to FontSets were removed or reworded.
- In section 1.0, Introduction, a note was added that CFF2 CharStrings can be converted to Type2 CharStrings with loss of only the variation data.
- In sections 2.3 and 4.2, the statements about ending CharString and subroutines were corrected: these end when the end of the byte string is reached.
- In section 3, CharString Encoding, all references to width were removed.
- In section 3.2, CharString Number Encoding, Table 1, the number ‘255’ was deleted from start of text in last row, second column.
- In section 3.3, CharString Operator Encoding, an explicit statement was added that when an unrecognized operator is encountered, it should be ignored and the stack cleared.
- In section 4, references to arithmetic and conditional operators were deleted.
- In section 4.3, Figure 6, the hex and bitmask values in following hint mask example were corrected, from 0xA0 to 0x60.
- In section 4.4, Subroutines, the description of subroutines was expanded.
- In section 4.5, “vsindex (22)” was corrected to “vsindex (15)”. “blend (23)” was corrected to “blend (16)”. The blend example was updated to use 3 regions.
- In section 4.5, a statement was added that if present, vsindex must precede the first occurrence of the blend operator, and may occur only once in the CharString. The description of the blend operator was expanded.
- In Appendix A, Table 2, ‘return’ was corrected to ‘<reserved>‘.
- In Appendix B, CFF2 CharString Implementation Limits, the table row “TransientArray elements 32” was deleted. This is not needed, as the Type 2 storage operators are removed.
- Moved the content of Appendix C, Compatibility, into next appendix.
- Many small formatting and wording changes were made for legibility and consistency. All occurrences of “CFF 2” were changed to “CFF2”, and capitalization of “CharString” was made consistent.