Hi,
I used a modified version of Gio editor to view code, and realized
that it does not handle control
characters such as tab(U+0009) as most fonts out there do not provide
tab glyph. I tried fonts with
tab character such as Ubuntu Mono. But I am not satisfied with the
result, because the tab width is
the same as space in a monospace font. So I am looking for other ways
to solve this issue.
I know that the shaper queries fontMap to find a glyph for the target
rune, when no mapped glyph is found,
it returns a placeholder glyph for it. And this is typically a
rectangular box. I am wondering whether it is possible
to let the shaper replace tab (or any other rune) with some printable
runes(one or more). Could anyone give me
some guide?
Best Regards,
Zhijian Zhang
On Mon, Sep 16, 2024 at 12:29 AM zhang zj <zhangzj33@gmail.com> wrote:
>> Hi,>> I used a modified version of Gio editor to view code, and realized> that it does not handle control> characters such as tab(U+0009) as most fonts out there do not provide> tab glyph. I tried fonts with> tab character such as Ubuntu Mono. But I am not satisfied with the> result, because the tab width is> the same as space in a monospace font. So I am looking for other ways> to solve this issue.>> I know that the shaper queries fontMap to find a glyph for the target> rune, when no mapped glyph is found,> it returns a placeholder glyph for it. And this is typically a> rectangular box. I am wondering whether it is possible> to let the shaper replace tab (or any other rune) with some printable> runes(one or more). Could anyone give me> some guide?
What I have typically done is expand tabs to spaces when they are read
by the shaper. The shaper accepts an io.Reader, and you can give it a
special io.Reader that provides N spaces each time it encounters a tab
in the original document.
That being said, I don't think overriding the unknown glyph tofu is a
reliable way to fix this problem. It would also hide any other use of
unsupported glyphs that were intended to be graphical.
I could see supporting tabs more explicitly though. The width of a tab
could be a text shaper input, and the shaper could handle tab
characters specially. That would be a little work, but is likely the
best approach in the long term.
Cheers,
Chris
> > I am wondering whether it is possible> > to let the shaper replace tab (or any other rune) with some printable> > runes(one or more). Could anyone give me> > some guide?>> What I have typically done is expand tabs to spaces when they are read> by the shaper. The shaper accepts an io.Reader, and you can give it a> special io.Reader that provides N spaces each time it encounters a tab> in the original document.>
Another option is to layout a string using the shaper, then use the
NextGlyph() method to read the glyphs one by one and substitute the
tab glyphs with extra space before performing the shaping. I do
something similar in Anvil. When I come across a tab in a Glyph, I
overwrite the Advance on that Glyph so that it would offset the next
Glyph by the amount needed to align with the next tabstop, which is a
variable amount depending on how far the next tabstop is. I also
replace the ID with the Glyph ID for a space so nothing is rendered
there, and reset the Ascent and Offset to constant values.
This requires more code than Chris' suggestion though.
> What I have typically done is expand tabs to spaces when they are read> by the shaper. The shaper accepts an io.Reader, and you can give it a> special io.Reader that provides N spaces each time it encounters a tab> in the original document.
That is really a good point! It is even possible to add a prefix
symbol to the expanded runes.
> That being said, I don't think overriding the unknown glyph tofu is a> reliable way to fix this problem. It would also hide any other use of> unsupported glyphs that were intended to be graphical.
Yes, this would cause chaos.
> I could see supporting tabs more explicitly though. The width of a tab> could be a text shaper input, and the shaper could handle tab> characters specially. That would be a little work, but is likely the> best approach in the long term.
That would be really good.
Best Regards,
Zhijian Zhang
Thank you, Jeff and Chris. These two options are inspiring. The later
option give us more control
of the width of the final "Tab" and could be useful if we have better alignment.
Best Regards,
Zhijian Zhang
On Tue, Sep 17, 2024 at 9:31 PM Jeff Williams <kanobe@gmail.com> wrote:
>> > > I am wondering whether it is possible> > > to let the shaper replace tab (or any other rune) with some printable> > > runes(one or more). Could anyone give me> > > some guide?> >> > What I have typically done is expand tabs to spaces when they are read> > by the shaper. The shaper accepts an io.Reader, and you can give it a> > special io.Reader that provides N spaces each time it encounters a tab> > in the original document.> >>> Another option is to layout a string using the shaper, then use the> NextGlyph() method to read the glyphs one by one and substitute the> tab glyphs with extra space before performing the shaping. I do> something similar in Anvil. When I come across a tab in a Glyph, I> overwrite the Advance on that Glyph so that it would offset the next> Glyph by the amount needed to align with the next tabstop, which is a> variable amount depending on how far the next tabstop is. I also> replace the ID with the Glyph ID for a space so nothing is rendered> there, and reset the Ascent and Offset to constant values.>> This requires more code than Chris' suggestion though.