AFDKO “features” File Tips & Tricks, Part 1: ‘vmtx’ Table Overrides

Given that I seem to be on a roll, it seems appropriate to begin a new AFDKO series that focuses on the all-important “features” file that is used to define GSUB and GPOS features, and to override the settings of various tables. Let’s begin with something relatively simple, such as overriding the ‘vmtx‘ table for a very specific class of glyphs: full-width Latin or Latin-like glyphs that rest on a Latin baseline, but which should be centered along the Y-axis when in vertical writing mode. Click here to download an archive that includes the various files and resources that are referenced in this article.

To better illustrate the issue to be solved, I have excerpted Table 7-14 that spans pp 495 and 496 of CJKV Information Processing, Second Edition (O’Reilly Media, 1999):
CJKV Information Processing, Second Edition, Table 7-14
Note how the full-width glyphs with descenders and ascenders, especially when they are contiguous and in that sequence, collide with one another. The “p” followed by “h” sequence is the most striking. When set in vertical writing mode, these glyphs clearly do not benefit from the Latin baseline on which they rest. In fact, it becomes detrimental. And, unlike their proportional and half-width counterparts that rotate 90 degrees clockwise, they remain upright in vertical writing mode.

The obvious solution is to simply center these glyphs along the Y-axis. One might think that having separate glyphs for this purpose might be appropriate, but given the fact that the context of this metrics adjustment is limited to vertical writing mode, the ideal way is to specify new vertical origins for the appropriate glyphs. This does not affect the glyphs in horizontal writing mode.

The best way to accomplish this task, in my opinion and experience, is through automation and clever text processing, and by specifying ‘vmtx’ overrides for the appropriate glyphs, which are also reflected in the ‘VORG‘ table when the OpenType font is built using the AFDKO makeotf tool. I developed a relatively simple Perl script called mkvmtx.pl that takes two files as input. One is an AFM file that is easily generated from the CIDFont resource that corresponds to the target font by executing the AFDKO tx tool with its “-afm” option, as follows:

% tx -afm cidfont.ps AFM

An OpenType font can also be specified, as long as it is CID-keyed:

% tx -afm RyoGothicPlusN-Light.otf AFM

The other file is effectively a coverage table that is specific to each character collection (aka, ROS: /Registry, /Ordering, and /Supplement, referring to the three entries of the /CIDSystemInfo dictionary that is present in a CIDFont resource), and specifies the CIDs and CID ranges that require this treatment. The included “vmtx.AJ16″ file is meant for Adobe-Japan1-6 (and earlier /Supplement) fonts, whose content is as follows:

710-720
758
771-772
780-841
1011-1124
7575-7584
7601-7607
7610-7612
8020-8037
8053
8055
8092-8101
8182
8186-8190
8192-8194
8225-8226
8295-8307
9779
9872-9883
11846-11870
12089-12096
16222
20427-20472
20919-20928

The mkvmtx.pl tool is executed as follows:

% mkvmtx.pl vmtx.AJ16 < AFM > vmtx.txt

The output is a fully-defined ‘vmtx’ table override that can be added to the “features” file for the target font, which is the following for RyoGothicPlusN-Light:

table vmtx {
  VertOriginY \710 893;
  VertOriginY \711 865;
  VertOriginY \713 871;
  VertOriginY \714 873;
  VertOriginY \715 868;
  VertOriginY \716 865;
  VertOriginY \718 888;
  VertOriginY \720 857;
  VertOriginY \758 1256;
  VertOriginY \771 935;
  VertOriginY \772 865;
  VertOriginY \780 873;
  VertOriginY \781 873;
  VertOriginY \783 873;
  VertOriginY \784 873;
  VertOriginY \785 867;
  VertOriginY \786 873;
  VertOriginY \787 868;
  VertOriginY \788 873;
  VertOriginY \789 873;
  VertOriginY \795 874;
  VertOriginY \801 885;
  VertOriginY \806 835;
  VertOriginY \809 874;
  VertOriginY \816 770;
  VertOriginY \817 897;
  VertOriginY \818 770;
  VertOriginY \819 897;
  VertOriginY \820 770;
  VertOriginY \821 912;
  VertOriginY \822 658;
  VertOriginY \823 898;
  VertOriginY \825 766;
  VertOriginY \826 898;
  VertOriginY \827 898;
  VertOriginY \828 771;
  VertOriginY \829 771;
  VertOriginY \830 770;
  VertOriginY \831 658;
  VertOriginY \832 658;
  VertOriginY \833 771;
  VertOriginY \834 770;
  VertOriginY \835 824;
  VertOriginY \836 769;
  VertOriginY \837 770;
  VertOriginY \838 770;
  VertOriginY \839 770;
  VertOriginY \840 650;
  VertOriginY \841 770;
  VertOriginY \1013 875;
  VertOriginY \1014 885;
  VertOriginY \1026 875;
  VertOriginY \1029 875;
  VertOriginY \1034 886;
  VertOriginY \1035 770;
  VertOriginY \1036 794;
  VertOriginY \1037 664;
  VertOriginY \1038 900;
  VertOriginY \1039 770;
  VertOriginY \1040 823;
  VertOriginY \1041 665;
  VertOriginY \1042 900;
  VertOriginY \1043 769;
  VertOriginY \1044 770;
  VertOriginY \1045 899;
  VertOriginY \1046 664;
  VertOriginY \1047 770;
  VertOriginY \1048 828;
  VertOriginY \1049 770;
  VertOriginY \1050 765;
  VertOriginY \1051 665;
  VertOriginY \1052 770;
  VertOriginY \1053 764;
  VertOriginY \1054 769;
  VertOriginY \1055 665;
  VertOriginY \1056 659;
  VertOriginY \1057 730;
  VertOriginY \1058 769;
  VertOriginY \1063 792;
  VertOriginY \1065 955;
  VertOriginY \1069 950;
  VertOriginY \1071 874;
  VertOriginY \1078 875;
  VertOriginY \1082 792;
  VertOriginY \1085 791;
  VertOriginY \1092 770;
  VertOriginY \1093 900;
  VertOriginY \1094 770;
  VertOriginY \1095 765;
  VertOriginY \1096 686;
  VertOriginY \1097 770;
  VertOriginY \1098 864;
  VertOriginY \1099 770;
  VertOriginY \1100 770;
  VertOriginY \1101 770;
  VertOriginY \1102 874;
  VertOriginY \1103 770;
  VertOriginY \1104 764;
  VertOriginY \1105 770;
  VertOriginY \1106 770;
  VertOriginY \1107 770;
  VertOriginY \1108 765;
  VertOriginY \1109 659;
  VertOriginY \1110 770;
  VertOriginY \1111 765;
  VertOriginY \1112 650;
  VertOriginY \1113 791;
  VertOriginY \1114 770;
  VertOriginY \1115 691;
  VertOriginY \1116 770;
  VertOriginY \1117 775;
  VertOriginY \1118 691;
  VertOriginY \1119 767;
  VertOriginY \1120 770;
  VertOriginY \1121 772;
  VertOriginY \1122 770;
  VertOriginY \1123 770;
  VertOriginY \1124 768;
  VertOriginY \7601 771;
  VertOriginY \7602 770;
  VertOriginY \7603 898;
  VertOriginY \7604 716;
  VertOriginY \7605 843;
  VertOriginY \7606 770;
  VertOriginY \7607 933;
  VertOriginY \8020 932;
  VertOriginY \8021 933;
  VertOriginY \8022 930;
  VertOriginY \8023 931;
  VertOriginY \8024 897;
  VertOriginY \8025 897;
  VertOriginY \8026 897;
  VertOriginY \8027 770;
  VertOriginY \8028 716;
  VertOriginY \8029 770;
  VertOriginY \8030 716;
  VertOriginY \8036 897;
  VertOriginY \8037 897;
  VertOriginY \8055 874;
  VertOriginY \8096 770;
  VertOriginY \8101 770;
  VertOriginY \8186 933;
  VertOriginY \8187 931;
  VertOriginY \8188 931;
  VertOriginY \8189 770;
  VertOriginY \8190 873;
  VertOriginY \8192 897;
  VertOriginY \8193 898;
  VertOriginY \8194 898;
  VertOriginY \8302 770;
  VertOriginY \8303 771;
  VertOriginY \8304 716;
  VertOriginY \8305 894;
  VertOriginY \9779 874;
} vmtx;

I have included coverage tables for our other character collections, such as Adobe-CNS1-6 (“vmtx.AC16″), Adobe-GB1-5 (“vmtx.AG15″), and Adobe-Korea1-2 (“vmtx.AK12″). For those who develop OpenType fonts that specify the Adobe-Identity-0 ROS, you need to develop your own coverage table to use with the mkvmtx.pl tool. The coverage tables that I provided should serve as an example of which glyphs should be included for this treatment.

Edited to add the following additional note:

For those font developers whose fonts do not share the same vertical origin as our fonts, which is Y=880, the mkvmtx.pl tool should be modified accordingly, specifically the following two lines:

$ybottomlimit = -120;
$ytoplimit = 880;

Our fonts use an em-box that is 12% below the Latin baseline (Y=−120), meaning that the vertical origin is Y=880. For example, if the em-box for your fonts is set 20% below the Latin baseline, those two lines should be modified as follows:

$ybottomlimit = -200;
$ytoplimit = 800;

Being aware of vertical origin differences is important, because it can vary from font developer to font developer.

Comments are closed.