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

Fonts without Microsoft-platform cmaps use Mac NameRecord #679

Open
moi15moi opened this issue Jan 26, 2023 · 12 comments
Open

Fonts without Microsoft-platform cmaps use Mac NameRecord #679

moi15moi opened this issue Jan 26, 2023 · 12 comments

Comments

@moi15moi
Copy link
Contributor

Screenshots

VSFilter
image

Libass (With DirectWrite)
image

Description of the issue

This font.zip doens't contain an OS/2 table.

When it is the case, GDI seems to only use the name from the namerecord with the platformID 1 (mac platform)

Here is the font naming table (I removed anything that is not family or fullname):

  <name>
    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Brushstroke Plain
    </namerecord>
    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Brushstroke test
    </namerecord>
    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
      Brushstroke family
    </namerecord>
  </name>

libass version

0.16.0

Is it a regression?

No response

ASS Sample

[Script Info]
; Script generated by Aegisub 9519-feature-92510945c
; http://www.aegisub.org/
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: None
PlayResX: 1280
PlayResY: 720

[Aegisub Project Garbage]
Video File: ?dummy:23.976000:40000:1280:720:47:163:254:
Video AR Value: 1.777778
Active Line: 2

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,100,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,5,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\fnBrushstroke Plain}Example
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\fnBrushstroke test}Example
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\fnBrushstroke family}Example

Special Fonts

I uploaded or linked to the required font

System Information

OS: Windows

Log

It seems that the mpv log miss the Brushstroke font

[   0.013][d][osd/libass] ASS library version: 0x1600010 (runtime 0x1600010)
[   0.013][v][osd/libass] libass API version: 0x1600010
[   0.013][v][osd/libass] libass source: commit: 4eb5c6dcff48628772568a7a185fbb1b0e57c014
[   0.015][v][osd/libass] Shaper: FriBidi 1.0.12 (SIMPLE) HarfBuzz-ng 5.3.1 (COMPLEX)
[   0.016][v][osd/libass] Setting up fonts...
[   0.017][v][osd/libass] Using font provider directwrite (with GDI)
[   0.017][v][osd/libass] Done.
[   0.174][d][osd/libass] ASS library version: 0x1600010 (runtime 0x1600010)
[   0.174][v][osd/libass] libass API version: 0x1600010
[   0.174][v][osd/libass] libass source: commit: 4eb5c6dcff48628772568a7a185fbb1b0e57c014
[   0.175][v][osd/libass] Shaper: FriBidi 1.0.12 (SIMPLE) HarfBuzz-ng 5.3.1 (COMPLEX)
[   0.175][v][osd/libass] Setting up fonts...
[   0.176][v][osd/libass] Using font provider directwrite (with GDI)
[   0.176][v][osd/libass] Done.
[   1.374][v][osd/libass] fontselect: (sans-serif, 400, 0) -> ArialMT, 0, ArialMT
[   1.378][v][osd/libass] fontselect: (mpv-osd-symbols, 400, 0) -> mpv-osd-symbols-Regular, 0, mpv-osd-symbols-Regular

Additional info

No response

@rcombs
Copy link
Member

rcombs commented Jan 26, 2023

It'll also fall back on the macStyle field in the head table when computing the bold and italic flags; I forget what it does for numeric weight.

@moi15moi
Copy link
Contributor Author

It'll also fall back on the macStyle field in the head table when computing the bold and italic flags

I just saw that when the bold bit is set, GDI considered it like 800 which is kinda strange.

@rcombs
Copy link
Member

rcombs commented Jan 26, 2023

Yes, if the OS/2 table is absent, then as far as I can tell:

  • Bold and italic flags come from macStyle
  • Numeric weight is 800 if bold, 400 otherwise
  • Ascent is hhea ascent; descent is inverse of hhea descent
  • Charset is guessed based on the glyphs present (rather than ulCodePageRange1)
    • There's also a fallback on usFirstCharIndex and usLastCharIndex in some cases

@astiob astiob added the fonts label Jan 26, 2023
@astiob
Copy link
Member

astiob commented Jan 26, 2023

This isn’t because the font lacks an OS/2 table; it may well have one (and I’ve just verified this by adding one via TTX).

This is because the font lacks a Microsoft-platform cmap, as detailed on our wiki.

I should note that my debug-fonts branch does list a Microsoft-platform cmap, so I’m guessing FreeType must be synthesizing one—and doing it badly, judging by the screenshot. TTX confirms that the font only has a single MacRoman cmap.

This also shows that DirectWrite, yet again, behaves differently from GDI and we have yet another reason to feed ass_directwrite fonts through get_font_info.

(I had thought there’s some other reason that makes GDI not actually support such fonts at all, because Zapfino is definitely not supported. But clearly, GDI does support this font, and there’s a specific problem with Zapfino instead. Now I can’t help but wonder what’s wrong with it—I don’t immediately see what it could be.)

@astiob
Copy link
Member

astiob commented Jan 26, 2023

there’s a specific problem with Zapfino instead. Now I can’t help but wonder what’s wrong with it

OK, looks like Windows only recognizes cmap format 0 for Macintosh-platform cmaps. (Brushstroke here uses format 0; Zapfino uses format 6.) And even for Microsoft-platform cmaps, not all formats seem to be recognized, e. g. format 6 fails. Weird.

@astiob
Copy link
Member

astiob commented Jan 26, 2023

I’m guessing FreeType must be synthesizing one—and doing it badly, judging by the screenshot

FreeType is indeed synthesizing a Unicode cmap, and it’s almost right in how it’s doing it… except it forgets the main law of fontology: if there is a chance for a font not to do the sensible thing, there will be a font that does not do the sensible thing. The Brushstroke font labels its glyphs with names that correspond to standard character names… but are offset by one starting from “A”, which is labelled at—whereas the actual “@” code point does not have a glyph at all. FreeType synthesizes the Unicode cmap based on glyph names, so all code points from @ onwards appear offset by one.

@moi15moi
Copy link
Contributor Author

This is because the font lacks a Microsoft-platform cmap, as detailed on our wiki.

Since you already know it, do I close the issue?

@astiob
Copy link
Member

astiob commented Jan 26, 2023

Thanks for asking, but no! This is still something that we ideally want to add support for, and it’s always good to have an issue tracking it.

(By the way, this was also mentioned in #643, but it’s good to keep this separate.)


Here’s how we can detect the FreeType-synthesized cmap:

FT_Get_CMap_Format(cmap) == -1

We should only use it as a last resort when we can’t find any actual cmaps that we understand.

@astiob astiob changed the title Rendering: Font without OS/2 table use Mac NameRecord Fonts without Microsoft-platform cmaps use Mac NameRecord Jan 26, 2023
@moi15moi
Copy link
Contributor Author

moi15moi commented Feb 22, 2023

I am not 100% sure, but it seems GDI use iso-8859-1 to decode name with the platform ID 1 and the platform encoding ID="0".

I still have no idea if it also use iso-8859-1 to decode cmap with also platform ID 1 and the platform encoding ID="0".

Edit: It use mac_roman for the cmap with platform 1 and platform encoding id 0.

@astiob
Copy link
Member

astiob commented Feb 23, 2023

Not MacRoman?

@moi15moi
Copy link
Contributor Author

Run this code with the font I provided earlier:

from fontTools.ttLib.ttFont import TTFont

font = TTFont("test.ttf")

font["name"].setName("Test®".encode("macroman"), 1, 1, 0, 0)
font.save("test - new.ttf")

If it would use mac_roman, GDI would return Test®, but it return Test¨ which correspond to the iso-8859-1 encoding.

@rcombs
Copy link
Member

rcombs commented Feb 23, 2023

GDI name lookup works like this:

  • If there is a cmap with platform 3 (Windows), use names with platform=3 and encoding=the encoding from the cmap
    • Names are decoded using Big5 (CP950), Wansung (CP949), or GB (CP936) for the associated encoding IDs, otherwise Unicode
    • If the cmap encoding is 0, the format number is 4, the high byte of endCode[0] is not 0x00 or 0xe0, and endCode[0] is not 0x20, the font is treated as a symbol font, otherwise as a regular font (using either Unicode, Big5, Wansung, GB, or SJIS)
  • Otherwise, if there is a cmap with platform 1 (Mac), use names with platform=1 and encoding=0
    • Names are simply zero-extended from 8-bit chars to 16-bit UTF-16 code units (so, effectively treating the input as ISO-8859-1)
    • Depending on the content of the post table, characters are treated as either MacRoman (default), or… some other weird thing I don't yet understand the details of (if post table has version 2.0 and glyphNameIndex contains at least one entry with a non-zero low byte and a high byte >1; this is intended to apply to a font named symbol.ttf)

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

3 participants