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

Take (xft) font(s) into consideration? #1

Closed
blueyed opened this issue Oct 17, 2016 · 3 comments
Closed

Take (xft) font(s) into consideration? #1

blueyed opened this issue Oct 17, 2016 · 3 comments

Comments

@blueyed
Copy link

blueyed commented Oct 17, 2016

I am looking into rxvt-unicode's handling of wide characters once again, and
found the following:

The NerdFileTypes font for example seems to use private use codepoints:

E.g. 0xe612 () is defined as:

StartChar: uniE612
Encoding: 58898 58898 924
Width: 2592
GlyphClass: 2
Flags: MW

Source: https://github.com/ryanoasis/nerd-fonts/blob/72ca7b7c1f9e8e3c5e319e0703fd95fc827bf3b9/glyph-source-fonts/original-source.otf.

According to https://codepoints.net/U+e612 this is "U+E612 PRIVATE USE CODEPOINT", with Ambiguous East Asian Width, where http://unicode.org/reports/tr11/#Ambiguous says

Private-use character codes and the replacement character have
ambiguous width, because they may stand in for characters of any width.

This could be interpreted as "let the font decide", and therefore I've looked
into using the following method in rxvt-unicode to ask the font for the actual
width:

int rxvt_font_xft::get_wcwidth (unicode_t unicode)
{
  FcChar32 ch = unicode;
  XGlyphInfo g;
  XftTextExtents32 (term->dpy, f, &ch, 1, &g);

  int w = g.width - g.x;
  // int wcw = max (WCWIDTH (unicode), 1);
  int r = (w + term->fwidth - 1) / term->fwidth;
  printf("get_wcwidth: fwidth=%d, g.width=%d-g.x=%d => w=%d, xOff=%d => %d\n", term->fwidth, g.width, g.x, w, g.xOff, r);
  r = (g.xOff + term->fwidth - 1 - term->fwidth/2) / term->fwidth;
  return r;
}

Using this in rxvt_term::scr_add_lines then:

int width = WCWIDTH (c);
rxvt_fontset *fs = FONTSET (rstyle);
rxvt_font *f = (*fs)[fs->find_font_idx (c)];
int wcwidth = f->get_wcwidth(c);
printf("c: %c, f: %d, width=%d, wcwidth=%d\n", c, f, width, wcwidth);
width = wcwidth;

While this method works well for rxvt-unicode (but is slow, of course), it does not play well with the shell/programs being used therein (just like some custom wcwidth implementation).

Therefore this would need to be provided through wcwidth itself.

Do you think it would be feasible to add support for something like this to this library/project?

I could imagine this being opt-in, e.g. through defining some environment variable (containing a list of fonts, since for rxvt-unicode only a defined list would be used).
Also this would need to have some caching in place then probably.

The obvious workaround is to patch (this) wcwidth to just return what you expect, which works well already.

@blueyed
Copy link
Author

blueyed commented Nov 10, 2016

I've created hack for rxvt-unicode to inject a wcwidth(3) callback using LD_PRELOAD into clients. Works surprisingly well.. ;)

@blueyed
Copy link
Author

blueyed commented Nov 10, 2016

Here is some discussion / ideas to make shells (Zsh in this case) behave better: http://www.zsh.org/mla/workers/2016/msg02326.html.

@fornwall
Copy link
Member

fornwall commented Apr 6, 2017

Sorry for the late reply!

There are a lot of implementations of wcwidth(): this one, wcwidth in python, gnulib, glibc, wcwidth in nodejs, wcwidth in ruby, wcwidth in lua. utf8proc is getting more popular where people are using utf8proc_charwidth(c) (example), and so on.

Using something along your proposal wouldn't work with these freestanding implementations and is fragile and hard to work across e.g. ssh sessions across systems.

I think we need to standardise the width of code points (including private plane ones when necessary) in fonts intended to be used in terminals as well as possible, and then push out that to various wcwidth implementations.

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

No branches or pull requests

2 participants