From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C Date: Fri, 25 Oct 2024 18:11:02 +0300 Message-ID: <86iktgb4l5.fsf@gnu.org> References: <86sesndz8v.fsf@gnu.org> <86ed46en1q.fsf@gnu.org> <86seslddvs.fsf@gnu.org> <86msitd0oy.fsf@gnu.org> <86h691cwuv.fsf@gnu.org> <86frolcrl2.fsf@gnu.org> <865xpgd4vi.fsf@gnu.org> Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22380"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Jimmy Yuen Ho Wong Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Oct 25 17:12:10 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1t4Lyz-0005eU-Qr for ged-emacs-devel@m.gmane-mx.org; Fri, 25 Oct 2024 17:12:09 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t4Ly6-0007XC-7J; Fri, 25 Oct 2024 11:11:14 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t4Ly4-0007Wy-8y for emacs-devel@gnu.org; Fri, 25 Oct 2024 11:11:12 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t4Ly3-0006m1-Vd; Fri, 25 Oct 2024 11:11:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=ptWgTVxJC4SmZ73MFQHiQpB4/p60H3SvaHa4DFIZMHM=; b=QP2aWVI2sSUk 1y2WhW0kkpnly7cg2IYG+qGFk4jDmhQ8cQMDWCO0PCoCjtJjolHk6UvqMUZLGzXnCUYWNEe6Mb9TT ZwCUxqDJaCoM7t/UYbk7MKw4ZWRcdzoT/pgngziOx6UgMZfd0Xvn24seFwzYoJIktoBOJjHhkiSzB Zi9hhtdSMbOweI4Q56F8BCG/vrKo+0i09evunU6l/27istzB7AnCbotdU6A0HMsrgMHNl/lRi8K9z qriA5L9mhK51zRLRQY8aGFqkNN4WFnMEaxxg1ipZu5GUYm9zObK33Jud5nM6R6zmNFXextPYzmdtY axV9P1IFtI9i3gAHMRWJ4A==; In-Reply-To: (message from Jimmy Yuen Ho Wong on Fri, 25 Oct 2024 14:35:16 +0100) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 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-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:324840 Archived-At: > From: Jimmy Yuen Ho Wong > Date: Fri, 25 Oct 2024 14:35:16 +0100 > Cc: emacs-devel@gnu.org > > Here are more gaps to fill in for you. The margin and the scroll bar widths are both calculated relative to the > `default-font-width`, the reason for that is, assuming most of the text is in the default font, if it is 20px wide, it's > undesirable to have a fixed scroll bar size of 3px. The scroll bar and the margin need to scale with the default > font size to fight for just enough of the user's attention when viewed. This can be known with some refactoring > by the time `string-pixel-width` is called on all the formatted completion strings, but the whole issue is the > "right" in :align-to (- right ) would be referring to the window from which you calculate > `string-pixel-width` from, not the window in the child frame, because we are trying calculate the child frame > width from the content width at this point. What you are suggesting has a logical circular dependency here, > which is why I explained to you that :align-to can only be calculated from `(+ prefix-column-width > candidate--column-width (- suffix-column-width suffix-width)`. The suffix width means the annotation's pixel > width, the part you keep calling type, which is not necessarily the case. I.e: So the problem is that you perform all the calculations _before_ the child frame is created and shown? If so, the :align-to will indeed be incorrect, but the difference between the alignment you calculate and the one you need is fixed: it's the difference in pixels between the width of the selected window when you calculate the alignment and the actual width of the window in the child frame where you will show the completion candidates. How hard is it to walk over all the candidates you prepared for display and adjust the :align-to values once the child frame is created? And if the problem is that the dimensions of the child frame depend on the width of the candidates+suffix to begin with, then you could perhaps break this circular dependency by estimating the expected width of the candidates by some coarse method that ignores the subtleties and adds some slack to be on the safe side. > IOW, your proposed idea will work for the simple cases, but falls > apart for a general-purpose API which will rightfully be expected to > work in any situation and use case supported by Emacs. > > Ok, makes sense. Thanks for filling in the missing parts for me. Here's some further questions. > > WRT case 1, translating tab sizes is a simple multiplication, it sounds to me it can still be fast by bypassing > windows. Is this correct? Anything else that can slow this case down? The problem is that the actual width of a TAB on display depends on the column where the TAB starts. IOW, a TAB is not shown as 8 columns, it is shown as the number of columns till the next tab stop. So its width cannot be reliably known for an arbitrary string until you know at which column that string will start on display. string-pixel-width assumes the string starts at column zero, but that might not be true. > WRT case 2, boldly extrapolating from my simple benchmarks, resolving the font from faces takes ~10% of the > time in `string-pixel-width`, besides saving and restoring window states and scanning window positions, what > else does "string-pixel-width" spend on the other 90% of the time? In what version of Emacs did you benchmark it? In Emacs 30, my profiling indicates a large portion of the time is taken by with-current-buffer. Emacs 31 cuts the time in half by using a fixed work buffer, but still, the actual pixel-width calculation takes only about 30% of the running time. (You can profile it yourself using profiler-start, but I suggest to load subr-x.el first as the .el file, so that the profile will be more detailed in terms of Lisp code.) Bottom line: string-pixel-width is hardly efficient enough when invoked in a tight loop, so if you need to call it many times for many strings, perhaps a better idea would be to insert all the strings into a work buffer, then measure their width one by one using window-text-pixel-size, each time calling it with different FROM and TO values? That involves switching a window's buffer and then switching it back, but maybe it will be faster? Alternatively, if you only need the width of the widest string in a collection, you could concatenate them separated by newlines, then call string-pixel-width on the result.