Note 1: D-Type Text Layout Extension provides a quick, easy and straightforward way to access and utilize advanced OpenType typography features and shaping rules needed to render complex scripts such as Arabic, Indic or Thai. Thus, D-Type Text Layout Extension makes the advanced typography structures described below obsolete.
Note 2: D-Type Power Engine makes it easy to render complex rich text in both device dependent and device independent manner. In addition, D-Type Power Engine supports all of the advanced OpenType features described below and all of the complex scripts defined in D-Type Text Layout Extension.
Note 3: Even better, use D-Type Unicode Text Module to render Unicode text and complex scripts such as Arabic, Indic or Thai without the need to know anything about the advanced typography structures described below.
In addition to the common D-Type structure types, D-Type Engine also defines and utilizes the following advanced typography structure types:
This structure type provides information for substituting glyphs to properly render the advanced typography scripts and features supported in a font. For example, in the Arabic script, the glyph shape that depicts a particular character varies according to its position in a word or text string. The same character will have a different glyph shape depending on whether it is located at the beginning, in the middle or at the end of the word. In this case, glyph substitutes are essential to properly render the string. In other scripts, glyph substitutes are aesthetic options for the user, such as ligatures or alternative forms.
Not all fonts support glyph substitutions. In order for glyph substitutions to function as described below, an OpenType font with the GSUB table is needed. For more details on how to access glyph substitutions in a font, see the dtFontGetGlyphSubsts function.
The DT_AT_GLYPH_SUBSTS_SET structure type is defined as follows:
/* A set of glyph substitutions for the specified script and feature in a font */ typedef struct { DT_AT_GLYPH_SUBSTS* subst_arr; /* array of substitution instructions */ DT_AT_GLYPH_INDEX* glyph_arr; /* array of glyphs */ DT_SLONG nr_of_substs; /* number of substitution instructions in the array */ DT_SLONG nr_of_glyphs; /* number of glyphs in the array */ DT_ID_UBYTE script_id; /* specified script */ DT_ID_UBYTE feature_id; /* specified feature */ } DT_AT_GLYPH_SUBSTS_SET;
The structure members have the following purpose:
subst_arr — a pointer to an array of glyph substitution instructions. Each individual glyph substitution instruction is described using the DT_AT_GLYPH_SUBSTS structure type, which is more thoroughly described below.
glyph_arr — a pointer to an array of glyphs. This array contains the glyphs that are to be substituted and the glyphs that substitute them. Each single glyph is represented using the DT_AT_GLYPH_INDEX type, which is merely an alias for the basic DT_ID_ULONG data type.
nr_of_substs — specifies the total number of substitution instructions that is necessary to perform in order to complete all glyph substitutions for the specified script and feature.
nr_of_glyphs — specifies the total number of glyphs in the glyph array. The glyphs in the glyph array serve as data (operands) for the glyph substitution instructions.
script_id — identifies the script.
nr_of_glyphs — identifies the glyph substitution feature.
As mentioned above, this structure type defines a single glyph substitution instruction. In D-Type API, glyph substitution instructions can be 1-to-1, N-to-1, 1-to-N and N-to-M. A glyph substitution is 1-to-1 when a single glyph is substituted by another single glyph. This is the simplest substitution type. A glyph substitution is N-to-1 when several glyphs are substituted by a single glyph. This substitution type is also called glyph composition or ligature. Similarly, a glyph substitution is 1-to-N when a single glyph is substituted by several glyphs. This substitution type is also called glyph decomposition. Finally, a glyph substitution in N-to-M when N glyphs are substituted by M glyphs. The N-to-M substitution is the most generic glyph substitution type.
As it can be seen, 1-to-1, N-to-1 and 1-to-N glyph substitutions are all special cases of the N-to-M glyph substitution. Thus, applications that implement support for N-to-M substitutions can automatically support 1-to-1, N-to-1 and 1-to-N substitutions.
In D-Type API, glyphs that are to be substituted are also called in-glyphs while glyphs that substitute them are called out-glyphs.
The DT_AT_GLYPH_SUBSTS structure type is defined as follows:
/* A single N-to-M glyph substitution instruction */ typedef struct { DT_SLONG glyph_arr_offset; /* start location in the array of glyphs */ DT_UBYTE count_in; /* number of in-glyphs to read (N) */ DT_UBYTE count_out; /* number of out-glyphs to read (M) */ } DT_AT_GLYPH_SUBSTS;
This structure consists of the following components:
glyph_arr_offset — this is the start location (offset) in the array of glyphs at which the in-glyphs begin. The array of glyphs is accessed via the glyph_arr member of the DT_AT_GLYPH_SUBSTS_SET structure described above.
count_in — tells how many in-glyphs to read from the array of glyphs. This is the N value in the generic N-to-M glyph substitution type described above. For 1-to-1 and 1-to-N substitutions, count_in will be 1. The in-glyphs begin immediately at the glyph_arr_offset location in the array of glyphs.
count_out — tells how many out-glyphs to read from the array of glyphs. This is the M value in the generic N-to-M glyph substitution type described above. For 1-to-1 and N-to-1 substitutions, count_out will be 1. The out-glyphs immediately follow the in-glyphs in the array of glyphs.
The process of applying glyph substitution features and performing the actual glyph substitutions is not trivial, but is dictated by the OpenType architecture and the complexity of certain scripts and features. The following steps describe this process:
For each Unicode character code in the initial text string, retrieve its default (or nominal) glyph index by calling the dtFontGetGlyphIndex function. Based on this, generate an initial array of glyphs (or the initial glyph string).
Call dtFontGetGlyphSubsts to get a set of glyph substitutions for the specified font, script and feature. For example, to retrieve glyph substitutions necessary to implement the initial forms in the Arabic script, call dtFontGetGlyphSubsts and set the feature_id to DV_AT_GSUBST_INIT and script_id to DV_AT_SCRIPT_ARAB. The set of glyph substitution instructions will be returned via the DT_AT_GLYPH_SUBSTS_SET structure.
For each individual glyph substitution instruction in the set of glyph substitutions, test the initial glyph string for the presence of any matching in-glyphs. If they are found, replace them with the corresponding out-glyphs. To do so, you must respect the values in the DT_AT_GLYPH_SUBSTS structure. Furthermore, you must implement all the glyph lookups and substitutions in the string yourself. Note that after all the glyph substitutions are done, the resulting glyph string may have a diferent length than the initial glyph string (unless all the glyph substitution instructions are 1-to-1). Thus, you should allow the glyph array to change its size in a dynamic fashion.
Repeat step 2 and 3 for all the features that are required or you wish to support in the specified script. For example, initial forms (DV_AT_GSUBST_INIT), medial forms (DV_AT_GSUBST_MEDI), final forms (DV_AT_GSUBST_FINA), required ligatures (DV_AT_GSUBST_RLIG) and ligatures (DV_AT_GSUBST_LIGA) are all applicable to Arabic scripts. Or, required ligatures (DV_AT_GSUBST_RLIG) and discretionary ligatures (DV_AT_GSUBST_DLIG) may be applicable to Latin scripts.
In general, the order in which glyph substitution features are applied is important. For example, substitution of ligatures in Arabic scripts should be applied after the substitution of initial or final forms. Consequently, applying glyph substitution features in an incorrect order may result in a wrong output. Developers who wish to support these advanced typography features should consult OpenType specifications and its advanced typography guidelines for additional information. Alternatively, developers may use D-Type Power Engine that has built-in support some of the most important advanced typography scripts and features.