2021年08月20日

emacs减少行高

emacs减少行高 [2021-08-20 Fri 09:45]

emacs在中英文显示使用更纱黑体时,行高比vim的大,导致同样是18象素的字体比vim要少显示几行。看看是否能减少行距,做到和vim一样的显示效果。

有修改配置、代码和字体三种方法。

修改配置

emacs有个variable line-spacing ,测试后发现只能增加行高,不能减少行高。

;; 只能在line的下面(descent)增加,不能减少行距,emacs就没有减少行高的方法。
;; 全局,浮点数的话,按比例
(setq-default line-spacing 0.2)

;; buffer-local variable, 整数的话,增加2个象素
(setq line-spacing 2)

M-x describe-font更纱黑 size:18px 的字体详细信息。

name (opened by): -*-Sarasa Mono T SC-normal-normal-normal-*-18-*-*-*-m-0-iso10646-1
       full name: Sarasa Mono T SC:pixelsize=18:weight=normal:slant=normal:width=normal:spacing=100:scalable=true
            size: 18
          height: 23 -> = ascent+descent
 baseline-offset:  0
relative-compose:  0
  default-ascent:  0
          ascent: 18
         descent:  5 -> 这里能改吗?
   average-width:  9
     space-width:  9
       max-width:  9

修改代码

通过配置无法减少行高,修改代码是否能做到呢?看了一下emacs的代码。大概的流程是这样的:

font.c -> 在不同操作系统中使用不同的font driver(macos上是 nsfont.m)加载fontinfo -> font_info->max_bounds.descent -> font->descent

而fontinfo是macos的系统级函数提供的(defined in nsgui.h)。

font->height = font->ascent + font->descent

中文和utf8(iso10646)的height和descent应该是一样的。通过 M-x describe-font 可以看出来。相同size的不同字体的height就不一定一样了。

如果能修改font的descent,应该能减少中文的height。问题是如何做到对特定的字体进行修改?

static Lisp_Object
calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
                           int boff, bool override)
  // calc这个函数里面怎么判断line_spacing为负数的情况?

  // 这个函数的参数descent是不是可以控制一下?
  normal_char_ascent_descent (font, -1, &ascent, &descent);

  height = ascent + descent;

https://www.gnu.org/software/emacs/manual/html_node/emacs/Fonts.html#Fonts 从这里可以看出来,没法在emacs配置字体的时候设置 ascent 和 descent,这是emacs在加载字体时,字体的fontinfo是根据每种字体的配置信息进行初始化的。

(set-face-attribute 'default nil :font "等距更纱黑体 T SC 18" :height 180)

因为是1/10,所以height是180/10=18,即设置的字体size是18象素。这里是不能设置每个字符的height,仅仅是height决定字体用什么字号而已。

height

    The font height on the screen, measured in tenths of a printer’s point. This is the point size of the font, times ten. For a given vertical resolution, height and pixels are proportional; therefore, it is common to specify just one of them and use ‘*’ for the other. 
/* A subroutine that computes "normal" values of ASCENT and DESCENT
   for FONT.  Values are taken from font-global ones, except for fonts
   that claim preposterously large values, but whose glyphs actually
   have reasonable dimensions.  C is the character to use for metrics
   if the font-global values are too large; if C is negative, the
   function selects a default character.  */
static void
normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
{
    *ascent = FONT_BASE (font);
    *descent = FONT_DESCENT (font); // 有希望改这里吗?

    if (FONT_TOO_HIGH (font))
    {
        unsigned char2b;

        /* Get metrics of C, defaulting to a reasonably sized ASCII
           character.  */
        if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
        {
            struct font_metrics *pcm = get_per_char_metric (font, &char2b);

            if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
            {
                /* We add 1 pixel to character dimensions as heuristics
                   that produces nicer display, e.g. when the face has
                   the box attribute.  */
                *ascent = pcm->ascent + 1;
                *descent = pcm->descent + 1;
            }
        }
    }
}

修改字体的高度

[2021-08-20 Fri 11:19] 看了大半天,搞不定,考虑修改更纱黑的高度吧。这个办法可以考虑,也不需要改emacs的代码。