Subject: bug#7887: Emacs will render some fonts under Mac OS X one pixel too tall (patch supplied)

From: "Jan D." <[email-masked]>
Date: Tue, 25 Jan 2011 14:03:02 +0100

Anders Lindgren skrev 2011-01-22 10:43:
> Hi!
>
> I have notices that Emacs will render some fonts under Mac OS X one
> pixel too tall.
>
> The current implementation for handling fonts under NextStep always
> round the descender to the next full integer, to avoid clipping. (As
> descenders under NextStep are negative, this is done using the
> function "floor"). Unfortunately, some fonts do not specify the
> descender as exactly as desired. Concretely, a 6x8 bitmap font could
> report a descender of -2.0000040531158447 (represented by
> 0xc000000220000000), which Emacs rounds to -3. The result is that the
> font will be drawn one pixel taller than expected.
>
> The patch below is one example of how to handle this, it will
> circumvent the problem by adding a small value to the descender,
> making sure that values close enough to an integer will be rounded to
> that integer.

How about checking if it is negative and then use ceil instead of floor, 
and keeping floor for the positive case?

	Jan D.

>
>      -- Anders Lindgren
>
> 2011-01-22  Anders Lindgren<[email-masked]>
>
> 	* nsfont.m (nsfont_open): Ensure that fonts with inexact
> 	descenders would not become one pixel too tall.
>
>
> === modified file 'src/nsfont.m'
> --- src/nsfont.m	2011-01-19 22:11:33 +0000
> +++ src/nsfont.m	2011-01-22 09:03:56 +0000
> @@ -809,6 +809,15 @@
>       const char *fontName = [[nsfont fontName] UTF8String];
>       int len = strlen (fontName);
>
> +    /* The values specified by fonts are not always exact. For
> +     * example, a 6x8 font could specify that the descender is
> +     * -2.00000405... (represented by 0xc000000220000000).  Without
> +     * adjustment, the code below would round the descender to -3,
> +     * resulting in a font that would be one pixel higher than
> +     * intended. */
> +
> +    CGFloat adjusted_descender = [sfont descender] + 0.0001;
> +
>   #ifdef NS_IMPL_GNUSTEP
>       font_info->nsfont = sfont;
>   #else
> @@ -830,7 +839,7 @@
>
>       brect =  [sfont boundingRectForFont];
>       full_height = brect.size.height;
> -    min_height = [sfont ascender] - [sfont descender];
> +    min_height = [sfont ascender] - adjusted_descender;
>       hd = full_height - min_height;
>
>       /* standard height, similar to Carbon. Emacs.app: was 0.5 by default. */
> @@ -845,10 +854,10 @@
>       /* max bounds */
>       font_info->max_bounds.ascent =
>         lrint (hshrink * [sfont ascender] + expand * hd/2);
> -    /* [sfont descender] is usually negative.  Use floor to avoid
> -       clipping descenders. */
> +    /* Descender is usually negative.  Use floor to avoid clipping
> +       descenders. */
>       font_info->max_bounds.descent =
> -      -lrint (floor(hshrink* [sfont descender] - expand*hd/2));
> +      -lrint (floor(hshrink * adjusted_descender - expand * hd/2));
>       font_info->height =
>         font_info->max_bounds.ascent + font_info->max_bounds.descent;
>       font_info->max_bounds.width = lrint (font_info->width);
> @@ -884,7 +893,7 @@
>
>       /* set up metrics portion of font struct */
>       font->ascent = lrint([sfont ascender]);
> -    font->descent = -lrint(floor([sfont descender]));
> +    font->descent = -lrint(floor(adjusted_descender));
>       font->min_width = ns_char_width(sfont, '|');
>       font->space_width = lrint (ns_char_width (sfont, ' '));
>       font->average_width = lrint (font_info->width);
>
>
>
>
> In GNU Emacs 24.0.50.1 (x86_64-apple-darwin10.5.0, NS apple-appkit-1038.35)
>   of 2011-01-14 on macpro.local
> Windowing system distributor `Apple', version 10.3.1038
> configured using `configure  '--with-ns''
>
> Important settings:
>    value of $LC_ALL: nil
>    value of $LC_COLLATE: nil
>    value of $LC_CTYPE: nil
>    value of $LC_MESSAGES: nil
>    value of $LC_MONETARY: nil
>    value of $LC_NUMERIC: nil
>    value of $LC_TIME: nil
>    value of $LANG: nil
>    value of $XMODIFIERS: nil
>    locale-coding-system: nil
>    default enable-multibyte-characters: t
>
> Major mode: ObjC/lw
>
> Minor modes in effect:
>    diff-auto-refine-mode: t
>    subword-mode: t
>    global-auto-revert-mode: t
>    global-cwarn-mode: t
>    minibuffer-electric-file-mode: t
>    recentf-mode: t
>    msb-mode: t
>    display-time-mode: t
>    tooltip-mode: t
>    mouse-wheel-mode: t
>    menu-bar-mode: t
>    file-name-shadow-mode: t
>    global-font-lock-mode: t
>    font-lock-mode: t
>    auto-composition-mode: t
>    auto-encryption-mode: t
>    auto-compression-mode: t
>    column-number-mode: t
>    line-number-mode: t
>    transient-mark-mode: t
>    abbrev-mode: t
>
> Recent input:
> <down>  <down>  <down>  <down>  <down>  <down>  <down>  <down>
> <down>  <down>  <down>  <down>  <down>  <down>  <down>  <down>
> <down>  <down>  <down>  <down>  <down>  <down>  <down>  <down>
> <down>  <down>  <down>  C-SPC<down>  C-w<down>  C-SPC
> <down>  <down>  <down>  C-w<up>  C-e<left>  <left>  <left>
> <M-backspace>  <backspace>  <backspace>  <backspace>  C-a
> C-x C-s C-M-a C-s e p s C-a C-x C-f s a<backspace>
> l a s j .<backspace>  <backspace>  k . c<return>  <C-tab>
> C-x o<C-S-tab>  C-x p C-M-a<up>  <up>  <up>  <up>  <up>
> <up>  <up>  <up>  <up>  C-SPC<down>  <down>  <down>  <down>
> <down>  <down>  <down>  C-w C-x C-s C-x o C-y C-x p<down>
> C-v C-l C-v<down>  <down-mouse-1>  <mouse-1>  C-a C-SPC
> <down>  <down>  <down>  <down>  <down>  <down>  <down>  C-w
> C-x C-s C-x o C-y C-x C-s C-x p<down-mouse-1>  <mouse-1>
> M-d M-d M-d c o u l y<backspace>  d SPC<backspace>
> M-f<backspace>  <backspace>  <backspace>  y<escape>
> q<M-left>  <M-left>  <M-backspace>  <escape>  q<down>
> <down>  M-f M-f M-f<M-backspace>  t h e SPC d e s c
> M--<escape>  q C-x C-s<down-mouse-1>  <mouse-1>  <down-mouse-1>
> <mouse-1>  <backspace>  C-a C-x C-s<down-mouse-1>  <mouse-1>
> SPC<down-mouse-1>  <mouse-1>  SPC C-a C-x C-s<down-mouse-1>
> <mouse-1>  SPC<down-mouse-1>  <mouse-1>  SPC C-a C-x
> C-s<down-mouse-1>  <mouse-1>  C-a<down>  SPC<backspace>
> <down>  <down>  <down>  <down>  <down>  <up>  SPC<backspace>
> C-a C-x C-s<up>  <up>  <up>  <up>  M-f<right>  <right>
> C-s C-w C-s C-a<down-mouse-1>  <mouse-1>  a<backspace>
> a d j u s t m e n t<escape>  d<escape>  q<up>  <up>
> <up>  C-a C-SPC<down>  <down>  <down>  <down>  <down>  <down>
> <escape>  x i s p l l<backspace>  <backspace>  e l l
> - r e g<tab>  '<backspace>  <return>  q<up>  C-g<up>
> <down-mouse-1>  <mouse-1>  c<escape>  q<down-mouse-1>
> <mouse-1>  C-d<backspace>  <backspace>  <backspace>  i
> f y C-a C-x C-s<menu-bar>  <help-menu>  <send-emacs
> -bug-report>
>
> Recent messages:
> Wrote /Users/anders/build/emacs/trunk/src/nsfont.m
> Mark saved where search started
> Mark set
> Starting new Ispell process [default] ...
> Entering debugger...
> Back to top level.
> Quit
> Auto-saving...done
> Saving file /Users/anders/build/emacs/trunk/src/nsfont.m...
> Wrote /Users/anders/build/emacs/trunk/src/nsfont.m
>
> Load-path shadows:
> ~/emacs/lisp/table hides
> /Applications/Emacs24.app/Contents/Resources/lisp/textmodes/table
> ~/emacs/lisp/ruby-mode hides
> /Applications/Emacs24.app/Contents/Resources/lisp/progmodes/ruby-mode
> ~/emacs/src/asm-mode-new/src/asm-mode hides
> /Applications/Emacs24.app/Contents/Resources/lisp/progmodes/asm-mode
>
> Features:
> (ispell smerge-mode diff-mode texinfo autoconf autoconf-mode conf-mode
> shadow sort gnus-util mail-extr message rfc822 mml mml-sec mm-decode
> mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 ietf-drums
> mm-util mail-prsvr mailabbrev mail-utils gmm-utils mailheader emacsbug
> subword newcomment ctypes grep compile etags jka-compr find-func follow
> my-end-of-buffer-log c-electric-operator c-indent-operator dired-aux
> dired vc-bzr sha1 hex-util add-log vc-dispatcher vc-svn pp apropos
> multi-isearch debug dabbrev help-mode eldoc ps-print ps-def lpr
> autorevert folding-isearch folding view rdebug cwarn prepaint cc-mode
> cc-fonts cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs
> tempo edg-mode split-nways toggle-file-read-only lockdir uniquify
> ange-ftp comint regexp-opt ring paren mic-paren iso-insert
> minibuf-elfile easy-mmode recentf tree-widget wid-edit easymenu msb
> edmacro kmacro warnings disp-table time advice help-fns advice-preload
> cl tooltip ediff-hook vc-hooks lisp-float-type mwheel ns-win tool-bar
> dnd fontset image fringe lisp-mode register page menu-bar rfn-eshadow
> timer select scroll-bar mouse jit-lock font-lock syntax facemenu
> font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan
> thai tai-viet lao korean japanese hebrew greek romanian slovak czech
> european ethiopic indian cyrillic chinese case-table epa-hook
> jka-cmpr-hook help simple abbrev loaddefs button minibuffer faces
> cus-face files text-properties overlay md5 base64 format env code-pages
> mule custom widget hashtable-print-readable backquote
> make-network-process ns multi-tty emacs)
>
>