Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[check_cjk_vertical_metrics] Update CJK vertical metrics requirements #5002

Open
aaronbell opened this issue Feb 28, 2025 · 1 comment
Open

Comments

@aaronbell
Copy link
Contributor

aaronbell commented Feb 28, 2025

Observed behaviour

The existing check is set on the previous requirements for CJK performance. Per approval of the new standard this check needs to be updated to reflect the new requirements.

Expected behaviour

For this requirement, we will need to update per the table below. Note that a BASE table, and vmtx / vhea tables must also be included to ensure broad support.

note:

  • Generally the emBox size = UPM
  • We can calculate the values of ideoEmboxTop and ideoEmboxBottom based on the BASE table (see below).
Attrib Value
OS/2.sTypoAscender ideoEmboxTop + (10–20% * emBox)/2
OS/2.sTypoDescender ideoEmboxBottom - (10–20% * emBox)/2
OS/2.sTypoLineGap 0
hhea.ascender OS/2.sTypoAscender
hhea.descender OS/2.sTypoDescender
hhea.lineGap 0
OS/2.usWinAscent abs(value) of yMax (same as normal check)
OS/2.usWinDescent abs(value) of yMin (same as normal check)
OS/2.fsSelection bit 7 (Use_Typo_Metrics) Enabled
OT BASE table Required
vhea / vmtx tables Required

The lack of a BASE table should be considered a FAIL. In terms of determining the accuracy of the BASE table, we can consider the following approach as WARN:

(314A) is a common character for Chinese / Japanese fonts and is often used as a reference for establishing the BASE table.

Image
MARGIN = (UPM-(B-A))/2

A = y-direction minimum of 永
B = y-direction maximum of 永
C = y-direction minimum of emBox:  A - MARGIN
D = MARGIN
E = UPM - MARGIN / x-maximum of 永 + (x-minimum of 永)-D 

notes

  • As the margin around the ideograph to the outer edge of the emBox should be consistent (per the BASE spec), we use the height of the glyph vs the UPM to determine the border, then implement that value to determine the correct values for D and E.
  • For E, we want to account for the possibility of a rectangular type body rather than a square one, so we must reference the difference between the margin value and outer edge of the design. But, if the width is the same as the UPM, we can just subtract the MARGIN from the UPM.
table BASE {
  HorizAxis.BaseTagList     icfb  icft  ideo  romn;
  HorizAxis.BaseScriptList  
                DFLT 	ideo  	A   B  C     0,
                hani  	ideo   	A   B  C     0,
                kana  	ideo   	A   B  C     0,
                latn  	romn   	A   B  C     0;

  VertAxis.BaseTagList      icfb  icft  ideo  romn;
  VertAxis.BaseScriptList 
                DFLT  	ideo    D   E     0   -C,
                hani  	ideo    D   E     0   -C,
                kana  	ideo    D   E     0   -C,
                latn  	romn    D   E     0   -C;
} BASE;

For Korean, there are some complications. In Source Han Sans, for example, the Korean glyphs are narrower than the Ideographs, but strangely have the same BASE table values. IMO these should be different to accurately reflect the type body that the Korean syllables sit on vs the ideographs.

Additionally, as not all Hangeul fonts will include ideographs, we must select alternate reference glyphs common to all fonts. To that end, I've suggested (BC08) & (BAA8).

For the hang entry, I'd suggest the following:

MARGIN = (UPM-(B-A))/2

A = y-direction minimum of 永 / y-direction minimum of 밈
B = y-direction maximum of 永 / y-direction minimum of 밈
C = y-direction minimum of emBox:  A - MARGIN
D = MARGIN
E = UPM - MARGIN / x-maximum of 모 + ((x-minimum of 모)-D)

Generally, the top, bottom, and left edges (A/B/D) of the Hangeul syllable align with the margins set for ideographs, so we can use the same reference glyph (if available) to determine what these values. However, in case of a Hangeul-only design where that glyph is not present, the glyph can be used instead.

(here's the entries for Hangeul)
Horiz:
hang ideo A B C 0,
Vert:
hang ideo D E 0 -C,

Here is how this would look for a Hangeul-only font like Hahmlet with the outer red lines denoting the edge of the emBox (C-bottommost), and inner lines (A-top, B-bottom, D-left, E-right) the border of the BASE entries:

Image

For the vhea / vmtx tables, we should just make sure that they're there for now as a FAIL.
I'd also suggest adding a WARN for the following:

  • vhea.ascender = UPM/2
  • vhea.descender = -UPM/2
  • vhea.lineGap = 0
  • non-combining mark glyphs should have vmtx advance height equal to the UPM. Otherwise equal to 0.

I suggest these as WARNs versus FAILs as actual implementations can vary and depend on the designer, but as a standardized approach for non-opinionated designers, the above is a good starting point I think.

@aaronbell
Copy link
Contributor Author

Here is a good example of why the value checker for the BASE table should be WARN vs FAIL:
Image

This is Source Han Sans with the embedded BASE table. For this design, the extremes of the glyph are not quite ideal for the position of the BASE table values, so this should be a WARN. Potentially, we could consider checking if the BASE entries are within a range of the extreme (like 2% UPM, or 20 units at 1000UPM)? That would enable Source Han Sans to pass without a WARN.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant