-
Notifications
You must be signed in to change notification settings - Fork 11
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
How to render vertical texts #111
Comments
Hi ! I think rendering vertical text has not been tested thoroughly yet, but it is definitively an area we would like to improve ! PS : As an aside, I've skimmed your project issue tracker, and found hajimehoshi/ebiten#788. Perhaps you will be interested by the |
Thank you for your quick response!
Thanks, I'll take a look! |
From a first research, I've understood that :
So basically, go-text/harfbuzz should do all the work. Could you paste the Mongolian and Japanese strings you have used so that I can reproduce and hopefully fix the issue ? |
Thank you for taking a look!
Here you are: "ᠬᠦᠮᠦᠨ ᠪᠦᠷ ᠲᠥᠷᠥᠵᠦ ᠮᠡᠨᠳᠡᠯᠡᠬᠦ\nᠡᠷᠬᠡ ᠴᠢᠯᠥᠭᠡ ᠲᠡᠢ᠂ ᠠᠳᠠᠯᠢᠬᠠᠨ" "あのイーハトーヴォの\nすきとおった風、\n夏でも底に冷たさを\nもつ青いそら…" |
I will have to learn about this to update the |
Here is what I found after more digging. There is an ambiguity when we say "vertical text" : it may be that we want to render glyphs upright, on top of each other; or that we want to rotate glyphs (that is, basically, to render them as in horizontal mode, and then rotate the whole line). Depending on the context and script, both ways may be "acceptable", or sometimes one way is more natural than the other. Here are whats Firefox renders : HTML source<style>
.vert {
writing-mode: vertical-lr;
text-orientation: mixed;
}
.sideways {
writing-mode: vertical-lr;
text-orientation: sideways;
}
.upright {
writing-mode: vertical-lr;
text-orientation: upright;
}
</style>
<body>
<div
style="
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
row-gap: 20px;
"
>
<div><b>Script</b></div>
<div><b>Horizontal</b></div>
<div><b>Upright</b></div>
<div><b>Sideways</b></div>
<div><b>Browser default</b></div>
<div>Latin</div>
<div>ABCD</div>
<div class="upright">ABCD</div>
<div class="sideways">ABCD</div>
<div class="vert">ABCD</div>
<div>Mongolian</div>
<div>ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="upright">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="sideways">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="vert">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div>Japanese</div>
<div>もつ青いそら…</div>
<div class="upright">もつ青いそら…</div>
<div class="sideways">もつ青いそら…</div>
<div class="vert">もつ青いそら…</div>
</div>
</body> Now, notice that Harfbuzz has no precise notion of this difference : using a direction of TopToBottom will generate the upright form, never the sideways one. So my first conclusion is that we should support the two ways. The upright mode is already covered by Harfbuzz. A sketch of implementation for the sideways one would be to 1) shape horizontally 2) rotate the whole output. This means that we will have to add a flag to glyphs indicating that their content should be rotated when rendering (so that go-text/render and other consumer may properly rotate the glyph) A second step would be to select the "best way" to render vertical text, given an input text, that is, matching what web browsers do by default. This is where the famous Unicode Vertical_Orientation table is useful: if I'm not mistaken, it gives us a way to segment the text according to the U or Tu (=upright) / R or Tr (=sideways) alternative. Side note : the upright rendering of the Mongolian text using Harfbuzz seems indeed "broken". I've checked the NotoSansMongolian font and found that the vertical advance values are constant. It means that the font is not designed for this rendering. By the way, you can see that Firefox doesn't even support it ! |
Thank you for taking a look! "…" (U+2026) in the all above figure seems not rendered expectedly at least to me. Probably the browser behaves correctly as they prefer English fonts for this glyph for "…". If a Japanese font is used, it should have its own special vertical glyph for "…", as I shown in the first comment. "…" is grouped as "R" in the Unicode spec, but this actually should NOT be rotated when a Japanese glyph is used. If CSS font-family prefers a Japanese font over others, the result should be changed. This is complicated! Yeah, I feel like the second step seems the best. As I said above, some glyphs should not be rotated against the Unicode spec, so func shouldRotateGlyph() bool {
// This is for "…" for example
if theGlyphIsAlreadySpecialVerticalGlyph {
return false
}
if theUnicodePropertyIsROrTr {
return true
}
return false
} would be what we need. What do you think?
When rotating glyphs, shouldn't horizontal advances be used for them instead of vertical ones? It makes sense if the Monglian font doesn't have vertical advance info as the font has only horizontal glyphs. |
That will be the case using the "sideways" mode (like browsers do), but the "upright" mode will stay broken, and I think the real solution would be for the font author to include proper vertical metrics ('vtmx' table). |
Yes, you have nicely sum up the issue, and I overall agree with your pseudo-code solution. However, I don't think there is a proper way to detect |
I tested the HTML with a Japanese font (Noto Sans CJK JP), and the default rendering result worked well on my Chrome. On Firefox, the results seems a little suspicious. In Chrome, the browser default seems expected to me, since alphabets are rotated, and a special vertical glyph is used for "…". I don't know how browser works, but as you explained, emulating this behavior is pretty difficult, right? HTML<html lang="ja">
<style>
body {
font-family: "Noto Sans CJK JP";
}
.vert {
writing-mode: vertical-lr;
text-orientation: mixed;
}
.sideways {
writing-mode: vertical-lr;
text-orientation: sideways;
}
.upright {
writing-mode: vertical-lr;
text-orientation: upright;
}
</style>
<body>
<div
style="
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
row-gap: 20px;
"
>
<div><b>Script</b></div>
<div><b>Horizontal</b></div>
<div><b>Upright</b></div>
<div><b>Sideways</b></div>
<div><b>Browser default</b></div>
<div>Latin</div>
<div>ABCD</div>
<div class="upright">ABCD</div>
<div class="sideways">ABCD</div>
<div class="vert">ABCD</div>
<div>Mongolian</div>
<div>ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="upright">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="sideways">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div class="vert">ᠬᠦᠮᠦᠨ ᠪᠦᠷ</div>
<div>Japanese</div>
<div>ABCDもつ青いそら…</div>
<div class="upright">ABCDもつ青いそら…</div>
<div class="sideways">ABCD青いそら…</div>
<div class="vert">ABCD青いそら…</div>
</div>
</body>
</html>
I see. I don't think I need 'upright' mode for Mongolian scripts in any environments, so I am OK.
Interesting. From the above result, I thought Chrome has a special magic that does theGlyphIsAlreadySpecialVerticalGlyph, but I am not sure. If we don't follow the Chrome way, maybe is this the compromise? func shouldRotateGlyph() bool {
if theFontUsesVertFeature {
return false
}
if theUnicodePropertyIsROrTr {
return true
}
return false
} In this case, "ABCD" in the Japanese text in the above example's "browser default" would not be rotated. Well, I think that's fine, though that's not the best... |
You can check of the |
Thank you for the nice pointer ! (Also, generally speaking, I would like to avoid interfering with Harfbuzz and avoid guessing what it will do or not... ) |
Hi, I'm using this library for my game engine. This is awesome!
I have several questions about vertical texts:
(The left-bottom texts are in Mongolian. This rendering result is without Vertical_Orientation)
(This rendering result is with Vertical_Orientation)
Thanks!
The text was updated successfully, but these errors were encountered: