From 3f37f14db3eca36a2abb37223ce62469cd69571b Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Mon, 10 Mar 2025 20:55:10 -0700 Subject: [PATCH 1/6] Updating the vertical metrics requirements for CJK --- gf-guide/metrics.md | 86 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index 7531365..21cce17 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -248,26 +248,86 @@ If the font is already hosted on [fonts.google.com](http://fonts.google.com/), y ## CJK Vertical Metrics -CJK vertical metrics are based on Source Han Sans and Noto CJK fonts. +Vertical metrics for CJK fonts are based on the font emBox values. This ensures that the ideographs (or syllables) are properly positioned in the center of the emBox both in horizontal and vertical typesetting. -The following vertical metric values must be applied to all CJK fonts +The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the emBox values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: -| Attrib | Value | Example using 1000upm font | + +| Attrib | Value | Example using Iansui | |-------------------------------------------|------------------------------------------|----------------------------| -| OS/2.sTypoAscender | 0.88 \* font upm | 880 | -| OS/2.sTypoDescender | -0.12 \* font upm | -120 | +| OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* emBox)/2 | 940 | +| OS/2.sTypoDescender | ideoEmBoxBottom \- (10–20% \* emBox)/2 | -180 | | OS/2.sTypoLineGap | 0 | 0 | -| hhea.ascender | Set to look comfortable (\~1.16 \* upm) | 1160 | -| hhea.descender | Set to look comfortable (\~0.288 \* upm) | -288 | +| hhea.ascender | OS/2.sTypeAscender | 940 | +| hhea.descender | OS/2.sTypoDescender | -180 | | hhea.lineGap | 0 | 0 | -| OS/2.usWinAscent | Same as hhea.ascent | 1160 | -| OS/2.usWinDescent | abs(value) of hhea.descent | 288 | -| OS/2.fsSelection bit 7 (Use_Typo_Metrics) | Do not set / disabled | 0 | +| OS/2.usWinAscent | Font bbox yMax | 1066 | +| OS/2.usWinDescent | Font bbox yMin | 273 | +| OS/2.fsSelection bit 7 (Use_Typo_Metrics) | Set / enabled | ✅ | +| BASE table | Required | | + +For `sTypoAscender` and `sTypoDescender`, a range of values is acceptable, per the designer's perspective and specific needs. Generally ~18% tends to produce good results, but depending on the project, wider or narrower metrics may be required. + +**Note** If the font is being built with `makeotf`, be aware that Adobe\'s default settings expect `sTypoMetrics` to match the emBox. Unless glyph heights are manually set for all glyphs, the `vmtx` values will not be set properly. As such, it may be easier to set vertical metrics as usual in the source, and adjust in post-production. + +These metrics were established based on investigations into improving metrics performance of CJK fonts across the library. Please see the following issue for more information: +- -Our decision to follow the Adobe schema was based on Dr. Ken Lunde’s comments and his release notes on Source Han Sans: +### Base Table -- -- [SourceHanSansReadMe.pdf](https://github.com/adobe-fonts/source-han-sans/raw/release/SourceHanSansReadMe.pdf) +In addition to the above metrics, CJK fonts are now required to include a `BASE` table (https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags) to ensure broad compatibility. + +For a standard square emBox font (1000 units wide for a 1000 UPM font), such as Iansui, the following BASE table was added to the `.fea` file. +``` +table BASE { + HorizAxis.BaseTagList icfb icft ideo romn; + HorizAxis.BaseScriptList DFLT ideo -83 843 -120 0, + hani ideo -67 827 -120 0, + kana ideo -67 827 -120 0, + latn romn -67 827 -120 0, + cyrl romn -67 827 -120 0, + grek romn -67 827 -120 0; + + VertAxis.BaseTagList icfb icft ideo romn; + VertAxis.BaseScriptList DFLT ideo 37 963 0 120, + hani ideo 53 947 0 120, + kana ideo 53 947 0 120, + latn romn 53 947 0 120, + cyrl romn 53 947 0 120, + grek romn 53 947 0 120; +} BASE; +``` +The BASE tags above are: + +- `icfb`: Ideographic character face bottom edge (in HorizAxis) / left edge (in VertAxis) +- `icft`: Ideographic character face top edge (in HorizAxis) / right edge (in VertAxis) +- `ideo`: ideographic em-box bottom edge (in HorizAxis) / left edge (in VertAxis) +- `romn`: Latin baseline. Usually 0 in HorizAxis, inverse of ideo in VertAxis + +Some additional tags which may be useful can be reviewed on the [official documentation](https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags). + +In the case of a design that is narrower than the usual square emBox, it is recommended to also include `idtp` to mark the top edge (opposite of `ideo`). For example, WD XL Lubrifont, which has an advance width of 765, has the following base table: + +``` +table BASE { + HorizAxis.BaseTagList icfb icft ideo idtp romn; + HorizAxis.BaseScriptList DFLT ideo -104 814 -120 880 0, + hani ideo -104 814 -120 880 0, + kana ideo -104 814 -120 880 0, + latn romn -104 814 -120 880 0, + cyrl romn -104 814 -120 880 0, + grek romn -104 814 -120 880 0; + + VertAxis.BaseTagList icfb icft ideo idtp romn; + VertAxis.BaseScriptList DFLT ideo 49 716 0 765 0, + hani ideo 49 716 0 765 0, + kana ideo 49 716 0 765 0, + latn romn 49 716 0 765 0, + cyrl romn 49 716 0 765 0, + grek romn 49 716 0 765 0; +} BASE; +``` +Note the `idtp` value in the VertAxis is present to indicaate the narrower width. ------------------------------------------------------------------------ From 9d6fbec9799074d1793292c4adf32af5e40f99f3 Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Mon, 10 Mar 2025 21:02:47 -0700 Subject: [PATCH 2/6] Update metrics.md better positioning and some adjusted language --- gf-guide/metrics.md | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index 21cce17..b6afec2 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -252,7 +252,6 @@ Vertical metrics for CJK fonts are based on the font emBox values. This ensures The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the emBox values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: - | Attrib | Value | Example using Iansui | |-------------------------------------------|------------------------------------------|----------------------------| | OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* emBox)/2 | 940 | @@ -266,7 +265,7 @@ The following metrics are a distinct split from the standard approach of setting | OS/2.fsSelection bit 7 (Use_Typo_Metrics) | Set / enabled | ✅ | | BASE table | Required | | -For `sTypoAscender` and `sTypoDescender`, a range of values is acceptable, per the designer's perspective and specific needs. Generally ~18% tends to produce good results, but depending on the project, wider or narrower metrics may be required. +In the case of `sTypoAscender` and `sTypoDescender`, a range of values is acceptable, per the designer's perspective and specific needs. Generally ~18% tends to produce good results, but depending on the project, wider or narrower metrics may be required. **Note** If the font is being built with `makeotf`, be aware that Adobe\'s default settings expect `sTypoMetrics` to match the emBox. Unless glyph heights are manually set for all glyphs, the `vmtx` values will not be set properly. As such, it may be easier to set vertical metrics as usual in the source, and adjust in post-production. @@ -280,21 +279,21 @@ In addition to the above metrics, CJK fonts are now required to include a `BASE` For a standard square emBox font (1000 units wide for a 1000 UPM font), such as Iansui, the following BASE table was added to the `.fea` file. ``` table BASE { - HorizAxis.BaseTagList icfb icft ideo romn; - HorizAxis.BaseScriptList DFLT ideo -83 843 -120 0, - hani ideo -67 827 -120 0, - kana ideo -67 827 -120 0, - latn romn -67 827 -120 0, - cyrl romn -67 827 -120 0, - grek romn -67 827 -120 0; - - VertAxis.BaseTagList icfb icft ideo romn; - VertAxis.BaseScriptList DFLT ideo 37 963 0 120, - hani ideo 53 947 0 120, - kana ideo 53 947 0 120, - latn romn 53 947 0 120, - cyrl romn 53 947 0 120, - grek romn 53 947 0 120; + HorizAxis.BaseTagList icfb icft ideo romn; + HorizAxis.BaseScriptList DFLT ideo -67 827 -120 0, + hani ideo -67 827 -120 0, + kana ideo -67 827 -120 0, + latn romn -67 827 -120 0, + cyrl romn -67 827 -120 0, + grek romn -67 827 -120 0, + + VertAxis.BaseTagList icfb icft ideo romn; + VertAxis.BaseScriptList DFLT ideo 53 947 0 120, + hani ideo 53 947 0 120, + kana ideo 53 947 0 120, + latn romn 53 947 0 120, + cyrl romn 53 947 0 120, + grek romn 53 947 0 120, } BASE; ``` The BASE tags above are: From e0b73c54f6205cf2a92751d4d815125d1424c21a Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Mon, 10 Mar 2025 21:05:42 -0700 Subject: [PATCH 3/6] Update metrics.md --- gf-guide/metrics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index b6afec2..326cdae 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -252,7 +252,7 @@ Vertical metrics for CJK fonts are based on the font emBox values. This ensures The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the emBox values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: -| Attrib | Value | Example using Iansui | +| Attrib | Value | Example using [Iansui](https://github.com/ButTaiwan/iansui) | |-------------------------------------------|------------------------------------------|----------------------------| | OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* emBox)/2 | 940 | | OS/2.sTypoDescender | ideoEmBoxBottom \- (10–20% \* emBox)/2 | -180 | @@ -300,12 +300,12 @@ The BASE tags above are: - `icfb`: Ideographic character face bottom edge (in HorizAxis) / left edge (in VertAxis) - `icft`: Ideographic character face top edge (in HorizAxis) / right edge (in VertAxis) -- `ideo`: ideographic em-box bottom edge (in HorizAxis) / left edge (in VertAxis) +- `ideo`: ideographic emBox bottom edge (in HorizAxis) / left edge (in VertAxis) - `romn`: Latin baseline. Usually 0 in HorizAxis, inverse of ideo in VertAxis Some additional tags which may be useful can be reviewed on the [official documentation](https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags). -In the case of a design that is narrower than the usual square emBox, it is recommended to also include `idtp` to mark the top edge (opposite of `ideo`). For example, WD XL Lubrifont, which has an advance width of 765, has the following base table: +In the case of a design that is narrower than the usual square emBox, it is recommended to also include `idtp` to mark the top edge of the emBox (opposite of `ideo`). For example, [WD XL Lubrifont](https://github.com/NightFurySL2001/WD-XL-font), which has an advance width of 765, has the following base table: ``` table BASE { From 693acbb2162f1d16d7f0ef49c50149a42b4641af Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Sat, 15 Mar 2025 06:40:42 -0700 Subject: [PATCH 4/6] Update metrics.md Updating based on feedback from NightFury and to clarify the situation around the vmtx / vhea tables. --- gf-guide/metrics.md | 50 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index 326cdae..8d709a1 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -252,22 +252,23 @@ Vertical metrics for CJK fonts are based on the font emBox values. This ensures The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the emBox values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: -| Attrib | Value | Example using [Iansui](https://github.com/ButTaiwan/iansui) | +| Attrib | Value | Example using a 1000 UPM font such as [Iansui](https://github.com/ButTaiwan/iansui) | |-------------------------------------------|------------------------------------------|----------------------------| | OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* emBox)/2 | 940 | | OS/2.sTypoDescender | ideoEmBoxBottom \- (10–20% \* emBox)/2 | -180 | | OS/2.sTypoLineGap | 0 | 0 | -| hhea.ascender | OS/2.sTypeAscender | 940 | +| hhea.ascender | OS/2.sTypoAscender | 940 | | hhea.descender | OS/2.sTypoDescender | -180 | | hhea.lineGap | 0 | 0 | | OS/2.usWinAscent | Font bbox yMax | 1066 | | OS/2.usWinDescent | Font bbox yMin | 273 | | OS/2.fsSelection bit 7 (Use_Typo_Metrics) | Set / enabled | ✅ | | BASE table | Required | | +| vhea / vmtx tables | Required | | In the case of `sTypoAscender` and `sTypoDescender`, a range of values is acceptable, per the designer's perspective and specific needs. Generally ~18% tends to produce good results, but depending on the project, wider or narrower metrics may be required. -**Note** If the font is being built with `makeotf`, be aware that Adobe\'s default settings expect `sTypoMetrics` to match the emBox. Unless glyph heights are manually set for all glyphs, the `vmtx` values will not be set properly. As such, it may be easier to set vertical metrics as usual in the source, and adjust in post-production. +Unfortunately, many typesetting environments still expect that the `sTypoMetrics` will align with the emBox. As such, the `BASE` table and `vhea` / `vmtx` tables are now required. See sections below. These metrics were established based on investigations into improving metrics performance of CJK fonts across the library. Please see the following issue for more information: - @@ -276,7 +277,7 @@ These metrics were established based on investigations into improving metrics pe In addition to the above metrics, CJK fonts are now required to include a `BASE` table (https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags) to ensure broad compatibility. -For a standard square emBox font (1000 units wide for a 1000 UPM font), such as Iansui, the following BASE table was added to the `.fea` file. +For a standard square emBox font (1000 units / 1000UPM), such as [Iansui](https://github.com/ButTaiwan/iansui), the following BASE table is added to the `.fea` file. ``` table BASE { HorizAxis.BaseTagList icfb icft ideo romn; @@ -305,7 +306,7 @@ The BASE tags above are: Some additional tags which may be useful can be reviewed on the [official documentation](https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags). -In the case of a design that is narrower than the usual square emBox, it is recommended to also include `idtp` to mark the top edge of the emBox (opposite of `ideo`). For example, [WD XL Lubrifont](https://github.com/NightFurySL2001/WD-XL-font), which has an advance width of 765, has the following base table: +In the case of a design that varies from the standard square emBox, you must also include `idtp` to mark the 'top' / 'right' edge of the emBox (opposite of `ideo`). For example, [WD XL Lubrifont](https://github.com/NightFurySL2001/WD-XL-font), which has a rectangular emBox with an advance width of 765, has the following base table: ``` table BASE { @@ -326,7 +327,44 @@ table BASE { grek romn 49 716 0 765 0; } BASE; ``` -Note the `idtp` value in the VertAxis is present to indicaate the narrower width. +Note the `idtp` value in the VertAxis is present to indicate the narrower width. + +### vhea and vmtx tables + +Most build systems (such as `makeotf` & `glyphsLib`) expect the `sTypoMetrics` to align with the font emBox, and use the `sTypoMetrics` to determine values in the `vmtx` and `vhea` tables. + +For the `vmtx` table, the `advanceHeight` value should align with the emBox height (usually the font UPM). If it doesn't, then the values (both `advanceHeight` and `topSideBearing`) in the table will need to be corrected using a post-production script. + +The `vhea` table also includes several fields that are determined based on the data from the `vmtx` table. However, once the `vmtx` table is corrected, these values can be recalculated by `fontTools`. + +Here is an example script that will address these issues: + +``` +import glob +from pathlib import Path +from fontTools.ttLib import TTFont +from fontTools.ttLib.tables._v_h_e_a import table__v_h_e_a + +for file in Path("fonts").glob("**/*.ttf"): + font = TTFont(file) + + #Calculate the adjustment to the sTypo metrics versus the emBox. (this assumes sTypo is set based on emBox) + glyphHeight = font["OS/2"].sTypoAscender - font["OS/2"].sTypoDescender + newHeight = font["head"].unitsPerEm + adjustment = int((glyphHeight - newHeight) / 2) + + #if this adjustment value is 0, as in to say the sTypo values are set aligned with the emBox, then no adjustments will occur. + + for i in font["vmtx"].metrics: + # want to make sure that if a glyph height is set differently that we don't modify it. Only the ones that match sTypo. + if font["vmtx"].metrics[i][0] == glyphHeight: + font["vmtx"].metrics[i] = (newHeight,font["vmtx"].metrics[i][1]-adjustment) + + table__v_h_e_a.recalc(font["vhea"],font) + font.save(file) +``` + + ------------------------------------------------------------------------ From b3bf866b85031a408eab012e5bd16d86a4ffe423 Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Sat, 15 Mar 2025 10:42:47 -0700 Subject: [PATCH 5/6] Update metrics.md changing naming --- gf-guide/metrics.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index 8d709a1..344a2f7 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -248,14 +248,14 @@ If the font is already hosted on [fonts.google.com](http://fonts.google.com/), y ## CJK Vertical Metrics -Vertical metrics for CJK fonts are based on the font emBox values. This ensures that the ideographs (or syllables) are properly positioned in the center of the emBox both in horizontal and vertical typesetting. +Vertical metrics for CJK fonts are based on the font em-box values. This ensures that the ideographs (or syllables) are properly positioned in the center of the em-box both in horizontal and vertical typesetting. -The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the emBox values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: +The following metrics are a distinct split from the standard approach of setting vertical metrics for CJK fonts, which normally set the `sTypo` metrics to align with the em-box values. This is also how the [OT spec recommendations](https://learn.microsoft.com/en-us/typography/opentype/spec/os2#stypoascender) are written. However, following [investigation into performance of CJK fonts](https://github.com/google/fonts/issues/8911) under the primary scenarios that Google Fonts prioritizes, the following new metrics have been established: | Attrib | Value | Example using a 1000 UPM font such as [Iansui](https://github.com/ButTaiwan/iansui) | |-------------------------------------------|------------------------------------------|----------------------------| -| OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* emBox)/2 | 940 | -| OS/2.sTypoDescender | ideoEmBoxBottom \- (10–20% \* emBox)/2 | -180 | +| OS/2.sTypoAscender | ideoEmBoxTop \+ (10–20% \* em-box)/2 | 940 | +| OS/2.sTypoDescender | ideoEmBoxBottom \- (10–20% \* em-box)/2 | -180 | | OS/2.sTypoLineGap | 0 | 0 | | hhea.ascender | OS/2.sTypoAscender | 940 | | hhea.descender | OS/2.sTypoDescender | -180 | @@ -268,7 +268,7 @@ The following metrics are a distinct split from the standard approach of setting In the case of `sTypoAscender` and `sTypoDescender`, a range of values is acceptable, per the designer's perspective and specific needs. Generally ~18% tends to produce good results, but depending on the project, wider or narrower metrics may be required. -Unfortunately, many typesetting environments still expect that the `sTypoMetrics` will align with the emBox. As such, the `BASE` table and `vhea` / `vmtx` tables are now required. See sections below. +Unfortunately, many typesetting environments still expect that the `sTypoMetrics` will align with the em-box. As such, the `BASE` table and `vhea` / `vmtx` tables are now required. See sections below. These metrics were established based on investigations into improving metrics performance of CJK fonts across the library. Please see the following issue for more information: - @@ -277,7 +277,7 @@ These metrics were established based on investigations into improving metrics pe In addition to the above metrics, CJK fonts are now required to include a `BASE` table (https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags) to ensure broad compatibility. -For a standard square emBox font (1000 units / 1000UPM), such as [Iansui](https://github.com/ButTaiwan/iansui), the following BASE table is added to the `.fea` file. +For a standard square em-box font (1000 units / 1000UPM), such as [Iansui](https://github.com/ButTaiwan/iansui), the following BASE table is added to the `.fea` file. ``` table BASE { HorizAxis.BaseTagList icfb icft ideo romn; @@ -301,12 +301,12 @@ The BASE tags above are: - `icfb`: Ideographic character face bottom edge (in HorizAxis) / left edge (in VertAxis) - `icft`: Ideographic character face top edge (in HorizAxis) / right edge (in VertAxis) -- `ideo`: ideographic emBox bottom edge (in HorizAxis) / left edge (in VertAxis) +- `ideo`: ideographic em-box bottom edge (in HorizAxis) / left edge (in VertAxis) - `romn`: Latin baseline. Usually 0 in HorizAxis, inverse of ideo in VertAxis Some additional tags which may be useful can be reviewed on the [official documentation](https://learn.microsoft.com/en-us/typography/opentype/spec/baselinetags). -In the case of a design that varies from the standard square emBox, you must also include `idtp` to mark the 'top' / 'right' edge of the emBox (opposite of `ideo`). For example, [WD XL Lubrifont](https://github.com/NightFurySL2001/WD-XL-font), which has a rectangular emBox with an advance width of 765, has the following base table: +In the case of a design that varies from the standard square em-box, you must also include `idtp` to mark the 'top' / 'right' edge of the em-box (opposite of `ideo`). For example, [WD XL Lubrifont](https://github.com/NightFurySL2001/WD-XL-font), which has a rectangular em-box with an advance width of 765, has the following base table: ``` table BASE { @@ -331,9 +331,9 @@ Note the `idtp` value in the VertAxis is present to indicate the narrower width. ### vhea and vmtx tables -Most build systems (such as `makeotf` & `glyphsLib`) expect the `sTypoMetrics` to align with the font emBox, and use the `sTypoMetrics` to determine values in the `vmtx` and `vhea` tables. +Most build systems (such as `makeotf` & `glyphsLib`) expect the `sTypoMetrics` to align with the font em-box, and use the `sTypoMetrics` to determine values in the `vmtx` and `vhea` tables. -For the `vmtx` table, the `advanceHeight` value should align with the emBox height (usually the font UPM). If it doesn't, then the values (both `advanceHeight` and `topSideBearing`) in the table will need to be corrected using a post-production script. +For the `vmtx` table, the `advanceHeight` value should align with the em-box height (usually the font UPM). If it doesn't, then the values (both `advanceHeight` and `topSideBearing`) in the table will need to be corrected using a post-production script. The `vhea` table also includes several fields that are determined based on the data from the `vmtx` table. However, once the `vmtx` table is corrected, these values can be recalculated by `fontTools`. @@ -348,12 +348,12 @@ from fontTools.ttLib.tables._v_h_e_a import table__v_h_e_a for file in Path("fonts").glob("**/*.ttf"): font = TTFont(file) - #Calculate the adjustment to the sTypo metrics versus the emBox. (this assumes sTypo is set based on emBox) + #Calculate the adjustment to the sTypo metrics versus the em-box. (this assumes sTypo is set based on em-box) glyphHeight = font["OS/2"].sTypoAscender - font["OS/2"].sTypoDescender newHeight = font["head"].unitsPerEm adjustment = int((glyphHeight - newHeight) / 2) - #if this adjustment value is 0, as in to say the sTypo values are set aligned with the emBox, then no adjustments will occur. + #if this adjustment value is 0, as in to say the sTypo values are set aligned with the em-box, then no adjustments will occur. for i in font["vmtx"].metrics: # want to make sure that if a glyph height is set differently that we don't modify it. Only the ones that match sTypo. From 6090edb849dbc77fa542590b4c3550066ffa0db8 Mon Sep 17 00:00:00 2001 From: Aaron Bell Date: Sat, 15 Mar 2025 14:58:09 -0700 Subject: [PATCH 6/6] Update metrics.md adding further information about the vhea / vmtx table and how to set them correctly. --- gf-guide/metrics.md | 53 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/gf-guide/metrics.md b/gf-guide/metrics.md index 344a2f7..8c09c7f 100644 --- a/gf-guide/metrics.md +++ b/gf-guide/metrics.md @@ -330,40 +330,41 @@ table BASE { Note the `idtp` value in the VertAxis is present to indicate the narrower width. ### vhea and vmtx tables +In order for the `vmtx` and `vhea` tables to be generated via `fontTools`, vert-specific metrics must be set in the source prior to build. -Most build systems (such as `makeotf` & `glyphsLib`) expect the `sTypoMetrics` to align with the font em-box, and use the `sTypoMetrics` to determine values in the `vmtx` and `vhea` tables. +In `Glyphs`, these are: +- `vheaVertAscender` +- `vheaVertDescender` +- `vheaLineGap` -For the `vmtx` table, the `advanceHeight` value should align with the em-box height (usually the font UPM). If it doesn't, then the values (both `advanceHeight` and `topSideBearing`) in the table will need to be corrected using a post-production script. +If building from `.ufo`, these are: +- `openTypeVheaVertTypoAscender` +- `openTypeVheaVertDescender` +- `openTypeVheaLineGap` -The `vhea` table also includes several fields that are determined based on the data from the `vmtx` table. However, once the `vmtx` table is corrected, these values can be recalculated by `fontTools`. +`vheaVertAscender` is the distance from the center of the glyph to the left edge (generally 500 for a `1000UPM` font). +`vheaVertDescender` is the distance from the center of the glyph to the right edge (generally -500 for a `1000UPM` font). +`vheaLineGap` is the horizontal space between lines of text. -Here is an example script that will address these issues: +Most build systems (such as `makeotf` & `glyphsLib`) expect the `sTypoMetrics` to align with the font em-box, and use the `sTypoMetrics` to determine values in the `vmtx` and `vhea` tables. So the advancedHeight set in the `vmtx` table will be larger than the intended em-box value, leading to undesireable space when the font is set vertically. + +**Solutions** +It is possible to add in an override method into the `.fea` file which can correct for this issue. For example: ``` -import glob -from pathlib import Path -from fontTools.ttLib import TTFont -from fontTools.ttLib.tables._v_h_e_a import table__v_h_e_a - -for file in Path("fonts").glob("**/*.ttf"): - font = TTFont(file) - - #Calculate the adjustment to the sTypo metrics versus the em-box. (this assumes sTypo is set based on em-box) - glyphHeight = font["OS/2"].sTypoAscender - font["OS/2"].sTypoDescender - newHeight = font["head"].unitsPerEm - adjustment = int((glyphHeight - newHeight) / 2) - - #if this adjustment value is 0, as in to say the sTypo values are set aligned with the em-box, then no adjustments will occur. - - for i in font["vmtx"].metrics: - # want to make sure that if a glyph height is set differently that we don't modify it. Only the ones that match sTypo. - if font["vmtx"].metrics[i][0] == glyphHeight: - font["vmtx"].metrics[i] = (newHeight,font["vmtx"].metrics[i][1]-adjustment) - - table__v_h_e_a.recalc(font["vhea"],font) - font.save(file) +table vmtx { + VertOriginY uni30FC.vert 830; + VertAdvanceY uni30FC.vert 900; +} vmtx; ``` +However, this approach (unless scripted), is cumbersome for a font on the scale of CJK. + +Two alternate options using a post-production script: + +1) Insert the incorrect `sTypo` data into the font, then correct the font metrics afterwards. The downside of this approach is that the source is not accurate to the output of the font. + +2) Use the correct `sTypo` data in the font, then correct the `vhea` and `vmtx` tables in post-production to follow the em-box data. While this approach is not ideal either, once the toolchains catch up, the post-production script can be removed and the output will remain the same. ------------------------------------------------------------------------