From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Titus von der Malsburg Newsgroups: gmane.emacs.devel Subject: [PATCH] Implement functions for measuring fonts and max chars per line Date: Mon, 22 Dec 2014 15:39:56 +0100 Message-ID: <87k31j3g03.fsf@posteo.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; protocol="application/pgp-signature" X-Trace: ger.gmane.org 1419261134 31681 80.91.229.3 (22 Dec 2014 15:12:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 22 Dec 2014 15:12:14 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Dec 22 16:12:09 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Y34eM-0001ZB-Iq for ged-emacs-devel@m.gmane.org; Mon, 22 Dec 2014 16:11:58 +0100 Original-Received: from localhost ([::1]:40916 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y34eL-0001zv-SY for ged-emacs-devel@m.gmane.org; Mon, 22 Dec 2014 10:11:57 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53844) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y349Z-0002AE-UV for emacs-devel@gnu.org; Mon, 22 Dec 2014 09:40:17 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y349S-0008NB-Ei for emacs-devel@gnu.org; Mon, 22 Dec 2014 09:40:09 -0500 Original-Received: from mx02.posteo.de ([89.146.194.165]:54244) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y349S-0008LP-6X for emacs-devel@gnu.org; Mon, 22 Dec 2014 09:40:02 -0500 Original-Received: from dovecot03.posteo.de (unknown [185.67.36.28]) by mx02.posteo.de (Postfix) with ESMTPS id 7168525AF523 for ; Mon, 22 Dec 2014 15:40:01 +0100 (CET) Original-Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3k5jy90Slvz5vNF for ; Mon, 22 Dec 2014 15:40:00 +0100 (CET) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 89.146.194.165 X-Mailman-Approved-At: Mon, 22 Dec 2014 10:11:46 -0500 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:180502 Archived-At: --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Hi, I produced a patch that adds convenient capabilities for measuring font sizes and for calculating how many characters fit on a line given a window and a font. This is in response to bug#19395 and builds on Eli Zaretskii's recent extension of `font-info' (commit b1978229162b0d4c3b14d8ad8bff383eb3511969). I'm a first-time submitter and would appreciate some feedback and additional information. Question 1: The file CONTRIBUTING says that I should ask on the list for the procedure regarding the copyright assignment. I currently live in the US but I think I do not have resident status. Question 2: It there a 1-to-1 relationship of commit messages and ChangeLog entries? The file CONTRIBUTING makes it sound like that but I see that some entries in ChangeLog are quite heavy which makes me suspect that they may represent several commits. Description of the new features: The background for this work is that I need a reliable way to determine how many characters I can fit on a line in a given font and window. This information is needed for presenting data in table format, for instance, when displaying search results in Helm. `window-width' looks like a solution for that but there are two problems: it assumes the frame's default font when doing the calculations and it does not account for the column reserved for the continuation glyph. (If either one of the fringes is zero, a column is reserved but not when both fringes are non-zero.) The solution to this problem is the new function `window-max-chars-per-line' which optionally accepts a window and font argument. For measuring the width of a character in the given window and font, this function uses another new function, `window-font-width'. For completeness, I also added `window-font-height'. The latter function is different from the existing function `default-font-height' in simple.el because it takes the window and font into account. `default-font-height' assumes the default font (possibly remapped in the current buffer). `window-font-height' and `window-font-width' both take an optional window argument because the relevant buffer may be displayed in several frames at the same time and different frames may use different fonts. So the result depends not just on the face but also on the window. For completeness, I also added a function `default-font-width' in simple.el which was previously missing. Many thanks to Eli for providing crucial input while I worked on this. All errors are obviously my fault. Titus The patch: Implement functions for measuring fonts and max chars per line * simple.el (default-font-width): new function. * (default-font-height): elaborate doc-string * window.el (window-font-width): new function (window-font-height): new function (window-max-chars-per-line): new function =2D-- lisp/simple.el | 24 +++++++++++++++++++++++- lisp/window.el | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/lisp/simple.el b/lisp/simple.el index 0fcd5db..72dcbb2 100644 =2D-- a/lisp/simple.el +++ b/lisp/simple.el @@ -5377,7 +5377,10 @@ lines." (declare-function font-info "font.c" (name &optional frame)) =20 (defun default-font-height () =2D "Return the height in pixels of the current buffer's default face font= ." + "Return the height in pixels of the current buffer's default face font. + +If the default font is remapped (see `face-remapping-alist'), the +function returns the width of the remapped face." (let ((default-font (face-font 'default))) (cond ((and (display-multi-font-p) @@ -5388,6 +5391,25 @@ lines." (aref (font-info default-font) 3)) (t (frame-char-height))))) =20 +(defun default-font-width () + "Return the width in pixels of the current buffer's default face font. + +If the default font is remapped (see `face-remapping-alist'), the +function returns the width of the remapped face." + (let ((default-font (face-font 'default))) + (cond + ((and (display-multi-font-p) + ;; Avoid calling font-info if the frame's default font was + ;; not changed since the frame was created. That's because + ;; font-info is expensive for some fonts, see bug #14838. + (not (string=3D (frame-parameter nil 'font) default-font))) + (let* ((info (font-info (face-font 'default))) + (width (aref info 11))) + (if (> width 0) + width + (aref info 10)))) + (t (frame-char-width))))) + (defun default-line-height () "Return the pixel height of current buffer's default-face text line. =20 diff --git a/lisp/window.el b/lisp/window.el index c95b0d6..990f953 100644 =2D-- a/lisp/window.el +++ b/lisp/window.el @@ -1830,6 +1830,57 @@ optional argument PIXELWISE is passed to the functio= ns." (window-body-width window pixelwise) (window-body-height window pixelwise))) =20 +(defun window-font-width (&optional window face) + "Return average character width for the font of FACE used in WINDOW. +WINDOW must be a live window and defaults to the selected one. + +If FACE is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function returns the +information for the remapped face." + (with-selected-window (window-normalize-window window t) + (let* ((face (if face face 'default)) + (info (font-info (face-font face))) + (width (aref info 11))) + (if (> width 0) + width + (aref info 10))))) + +(defun window-font-height (&optional window face) + "Return character height for the font of FACE used in WINDOW. +WINDOW must be a live window and defaults to the selected one. + +If FACE is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function returns the +information for the remapped face." + (with-selected-window (window-normalize-window window t) + (let* ((face (if face face 'default)) + (info (font-info (face-font face)))) + (aref info 3)))) + +(defun window-max-chars-per-line (&optional window face) + "Return the number of characters that can be displayed on one line in WI= NDOW. +WINDOW must be a live window and defaults to the selected one. + +The character width of FACE is used for the calculation. If FACE +is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function uses the +remapped face. + +This function is different from `window-body-width' in two +ways. First, it accounts for the portions of the line reserved +for the continuation glyph. Second, it accounts for the size of +the font." + (with-selected-window (window-normalize-window window t) + (let* ((window-width (window-body-width window t)) + (font-width (window-font-width window face)) + (ncols (/ window-width font-width))) + (if (and (display-graphic-p) + overflow-newline-into-fringe + (/=3D (frame-parameter nil 'left-fringe) 0) + (/=3D (frame-parameter nil 'right-fringe) 0)) + ncols + (1- ncols))))) + (defun window-current-scroll-bars (&optional window) "Return the current scroll bar types for WINDOW. WINDOW must be a live window and defaults to the selected one. =2D-=20 1.9.1 --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJUmC09AAoJEK40WfPGE2idOLwIAKW4KuCvZGc+I2XfbnsqGw0J jXCcip+LQvh/lYl2McA92PS6E+x+/O8eckBqISNnWCiz/6NYBMQOBuL7RXEf23Uj 8l8/M0Yf/B5MGMahLbx9H/yV6kRQxA1IeLb7AH0H86iMNpcVvmW2Gh4Om+7UaDCD hJBiIbuYPPJxigDsG5eD2fAq70n7DfKKMucV+tpDpzrdOKbwkzs2N1HSPBi363VG inu2kYCjcUSPZ9tgDC9NRyVZSddG1hYWD0yp8iZ0V8XcEgcGFSNvTCjfSoivjcG/ LiQRiCqAiKqEvzXkmQgqFhahbPW1UYzqtfnT9U/N5zrLXNgg7U9D/0oH11YaoAw= =XD8Z -----END PGP SIGNATURE----- --=-=-=--