From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Alex Gramiak Newsgroups: gmane.emacs.bugs Subject: bug#35468: [PATCH] Refactor draw_glyph_string on X and w32 Date: Sat, 27 Apr 2019 19:29:30 -0600 Message-ID: <877ebeor2d.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="167627"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) To: 35468@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Apr 28 03:48:24 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hKYvX-000hRg-JB for geb-bug-gnu-emacs@m.gmane.org; Sun, 28 Apr 2019 03:48:24 +0200 Original-Received: from localhost ([127.0.0.1]:38322 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hKYvW-0001Oj-LZ for geb-bug-gnu-emacs@m.gmane.org; Sat, 27 Apr 2019 21:48:22 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:47297) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hKYvI-0001Oa-EU for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:48:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hKYvE-0001cT-4W for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:48:08 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:51115) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hKYvD-0001cN-SC for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:48:04 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1hKYvD-0004jp-Ig for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:48:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Alex Gramiak Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 28 Apr 2019 01:48:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 35468 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.155641606618186 (code B ref -1); Sun, 28 Apr 2019 01:48:03 +0000 Original-Received: (at submit) by debbugs.gnu.org; 28 Apr 2019 01:47:46 +0000 Original-Received: from localhost ([127.0.0.1]:36426 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1hKYuu-0004jB-RT for submit@debbugs.gnu.org; Sat, 27 Apr 2019 21:47:46 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:32812) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1hKYus-0004ix-4c for submit@debbugs.gnu.org; Sat, 27 Apr 2019 21:47:44 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:36208) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hKYum-0001S8-N8 for submit@debbugs.gnu.org; Sat, 27 Apr 2019 21:47:36 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:47064) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hKYui-00017P-9j for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:47:36 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hKYiM-0004D5-HY for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:34:50 -0400 Original-Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]:45063) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hKYiL-0004CQ-Ta for bug-gnu-emacs@gnu.org; Sat, 27 Apr 2019 21:34:46 -0400 Original-Received: by mail-pg1-x536.google.com with SMTP id y27so2684028pgl.12 for ; Sat, 27 Apr 2019 18:34:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:user-agent:mime-version; bh=GFaklXzamYDn62MpIP+cI13t1zpLJLxXReIMdGfWyG8=; b=Wcnmc9IoIdsJRlg+vmiDzJXwUT/OvQKaL54hrMqKih+9kyboZ/5Jyjl51a+aPWR+i3 e9k976WfUpZyGkTGZR/YD+DwO4NlGLkbf0PImt/j+5ReB0tLI7uKE517wysc1SNvylvp gGDKmpe4rBSMfE3+La+7D8lpJSwcO8a3qpX0lIczb5IzOSvP8Zfk+MBUJob4ock5V95h aFahDUn092KLUDEv9ZEpAhB8zRmti6qLder5gz9BW1zJ/c4V6w1oxgmSexU5CKvJ6h9N MvTKu5UvyjXD1FeHdL3ZaXNCISj2R3arW3jN/wCpbS9ReZmzSbvp3wOPv/DpOt0p5faa Ugog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version; bh=GFaklXzamYDn62MpIP+cI13t1zpLJLxXReIMdGfWyG8=; b=RLdZPW0C3jmLg3axy5fQg60yG2L3rm+f/7UQMsaP1I2Tw0KOReqLTMxhoxqnd7Z99B o9nPruFJFm7AAYHn+1dy74y9krtcv7762PNZ+FcT7A0tq3yCYjJp7XzI52t5rqc0oaWq tNSfh6AvJttHUhK7hWjtcyop5Jb8iuIV9Gz4H24Br6ufVcYWucX4RHHl5GotgZAjTzyR UuKGA2ez/msKgkCNx+U8TiKqRTgFcw7W4QVKxt0psyWdFyCK8Whkb0Uw5j5JLHvujl11 6SI05FEPMUhrVy9QXUOK5BYBLMGb3ND9R29fUKfklkF18iIy/0xbVzXK/RHEtLlxNZcf EWAQ== X-Gm-Message-State: APjAAAX/XBVUWV7qA89Ap8J2qqWH8Oe2qb3azFrcRhj8bQXyYdC7U3lD bSD4hbZSjnEAFhJilFBuFrk8Cvpq X-Google-Smtp-Source: APXvYqyaNaIvzWivsNeeS4ZW8NhgoTCVjAXFduScBySjTNnUjRaofFtq4fYmst+BjZbM4HZ3GyxQKA== X-Received: by 2002:a63:1359:: with SMTP id 25mr50741691pgt.92.1556415283900; Sat, 27 Apr 2019 18:34:43 -0700 (PDT) Original-Received: from lylat ([2604:3d09:e37f:1500:1a72:4878:e793:7302]) by smtp.gmail.com with ESMTPSA id 19sm40142426pga.88.2019.04.27.18.34.42 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 27 Apr 2019 18:34:42 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:158384 Archived-At: --=-=-= Content-Type: text/plain This merges x_draw_glyph_string and w32_draw_glyph_string together to remove duplicated code. I wanted to do it for NS as well, but it seems just a bit too different to make it easily work. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Refactor-draw_glyph_string-on-X-and-w32.patch >From 1cd69c3bcfb79f8df61d1cacf75effb1947d869f Mon Sep 17 00:00:00 2001 From: Alexander Gramiak Date: Sat, 27 Apr 2019 18:45:59 -0600 Subject: [PATCH] Refactor draw_glyph_string on X and w32 * src/dispextern.h (draw_glyph_string_interface): New interface for system-dependent functions for draw_glyph_string. (redisplay_interface): Add draw_glyph_string_interface. * src/xdisp.c (gui_draw_glyph_string): New function implementing the common behaviour of x_draw_glyph_string and w32_draw_glyph_string. * src/w32term.c (w32_draw_glyph_string): Remove in favour of gui_draw_glyph_string. (w32_draw_underwave): Rename to w32_draw_underwave_1. (w32_draw_underwave, w32_draw_underline, w32_draw_overline) (w32_draw_strike_through, w32_reset_glyph_string_clipping): Define extracted functions out of w32_draw_glyph_string. * src/xterm.c (x_draw_glyph_string): Remove in favour of gui_draw_glyph_string. (x_draw_underwave): Rename to x_draw_underwave_1. (x_draw_underwave, x_draw_underline, x_draw_overline) (x_draw_strike_through, x_reset_glyph_string_clipping): Define extracted functions out of x_draw_glyph_string. --- src/dispextern.h | 98 +++++++++++ src/nsterm.m | 14 +- src/w32term.c | 414 +++++++++++------------------------------------ src/xdisp.c | 292 +++++++++++++++++++++++++++++++++ src/xterm.c | 405 ++++++++++------------------------------------ 5 files changed, 568 insertions(+), 655 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index 827eed86f1..20124be817 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1389,6 +1389,98 @@ struct glyph_string struct glyph_string *next, *prev; }; +/* Structure holding system-dependent interface functions needed + for drawing glyph strings as used by `gui_draw_glyph_string'. + + * If gui_draw_glyph_string is used as the RIF draw_glyph_string, + then all of the following must be defined with the possible + exception of draw_xwidget. */ + +struct draw_glyph_string_interface +{ + /* Set S->gc of glyph string S for drawing that glyph string. */ + + void (*set_gc) (struct glyph_string *s); + + /* Set clipping for output of glyph string S. */ + + void (*set_clipping) (struct glyph_string *s); + + /* Set SRC's clipping for output of glyph string DST. This is + called when we are drawing DST's left_overhang or right_overhang + only in the area of SRC. */ + + void (*set_clipping_exactly) (struct glyph_string *src, + struct glyph_string *dst); + + /* Reset clipping for output of glyph string S. */ + + void (*reset_clipping) (struct glyph_string *s); + + /* Draw the background of glyph_string S. If S->background_filled_p + is non-zero don't draw it. FORCE_P non-zero means draw the + background even if it wouldn't be drawn normally. This is used + when a string preceding S draws into the background of S, or S + contains the first component of a composition. */ + + void (*draw_background) (struct glyph_string *s, bool force_p); + + /* Draw the foreground of glyph string S. */ + + void (*draw_foreground) (struct glyph_string *s); + + /* Draw a box around glyph string S. */ + + void (*draw_box) (struct glyph_string *s); + + /* Draw image glyph string S. + + s->y + s->x +------------------------- + | s->face->box + | + | +------------------------- + | | s->img->margin + | | + | | +------------------- + | | | the image + + */ + + void (*draw_image) (struct glyph_string *s); + + /* Draw stretch glyph string S. */ + + void (*draw_stretch) (struct glyph_string *s); + + /* Draw xwidget stretch glyph string S. */ + + void (*draw_xwidget) (struct glyph_string *s); + + /* Draw the foreground of composite glyph string S. */ + + void (*draw_composite_foreground) (struct glyph_string *s); + + /* Draw the foreground of glyph string S for glyphless characters. */ + + void (*draw_glyphless_foreground) (struct glyph_string *s); + + /* Draw underwave glyph string S. */ + + void (*draw_underwave) (struct glyph_string *s); + + /* Draw underline glyph string S. */ + + void (*draw_underline) (struct glyph_string *s); + + /* Draw overline glyph string S. */ + + void (*draw_overline) (struct glyph_string *s); + + /* Draw strike-through glyph string S. */ + + void (*draw_strike_through) (struct glyph_string *s, int y, int height); +}; #endif /* HAVE_WINDOW_SYSTEM */ @@ -2890,6 +2982,10 @@ struct redisplay_interface /* Draw a glyph string S. */ void (*draw_glyph_string) (struct glyph_string *s); + /* Interface for drawing glyph strings used by + gui_draw_glyph_string. */ + struct draw_glyph_string_interface *gsif; + /* Define cursor CURSOR on frame F. */ void (*define_frame_cursor) (struct frame *f, Cursor cursor); @@ -3288,6 +3384,8 @@ extern void gui_write_glyphs (struct window *, struct glyph_row *, struct glyph *, enum glyph_row_area, int); extern void gui_insert_glyphs (struct window *, struct glyph_row *, struct glyph *, enum glyph_row_area, int); +extern void gui_draw_glyph_string (struct glyph_string *); + extern void gui_clear_end_of_line (struct window *, struct glyph_row *, enum glyph_row_area, int); extern void gui_fix_overlapping_area (struct window *, struct glyph_row *, diff --git a/src/nsterm.m b/src/nsterm.m index 2a2b8cbaba..e7b3ab4ebf 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -5107,6 +5107,7 @@ static Lisp_Object ns_string_to_lispmod (const char *s) 0, /* destroy_fringe_bitmap */ ns_compute_glyph_string_overhangs, ns_draw_glyph_string, + NULL, /* draw_glyph_string_interface */ ns_define_frame_cursor, ns_clear_frame_area, 0, /* clear_under_internal_border */ @@ -9507,19 +9508,6 @@ Nil means use fullscreen the old (< 10.7) way. The old way works better with doc: /* SKIP: real doc in xterm.c. */); Vx_toolkit_scroll_bars = Qt; - DEFVAR_BOOL ("x-use-underline-position-properties", - x_use_underline_position_properties, - doc: /* SKIP: real doc in xterm.c. */); - x_use_underline_position_properties = 0; - DEFSYM (Qx_use_underline_position_properties, - "x-use-underline-position-properties"); - - DEFVAR_BOOL ("x-underline-at-descent-line", - x_underline_at_descent_line, - doc: /* SKIP: real doc in xterm.c. */); - x_underline_at_descent_line = 0; - DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line"); - /* Tell Emacs about this window system. */ Fprovide (Qns, Qnil); diff --git a/src/w32term.c b/src/w32term.c index 8d5f57836c..947c67abb3 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -328,7 +328,7 @@ w32_get_scale_factor(struct w32_display_info *dpyinfo, int *scale_x, int *scale_ */ static void -w32_draw_underwave (struct glyph_string *s, COLORREF color) +w32_draw_underwave_1 (struct glyph_string *s, COLORREF color) { struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f); @@ -394,6 +394,71 @@ w32_draw_underwave (struct glyph_string *s, COLORREF color) DeleteObject (hp); } +static void +w32_draw_underwave (struct glyph_string *s) +{ + COLORREF color; + + if (s->face->underline_defaulted_p) + color = s->gc->foreground; + else + color = s->face->underline_color; + + w32_draw_underwave_1 (s, color); +} + +static void +w32_draw_underline (struct glyph_string *s) +{ + const int y = s->ybase + s->underline_position; + + if (s->face->underline_defaulted_p) + { + w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, + y, s->width, 1); + } + else + { + w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, + y, s->width, 1); + } +} + +static void +w32_draw_overline (struct glyph_string *s) +{ + unsigned long dy = 0, h = 1; + + if (s->face->overline_color_defaulted_p) + { + w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, + s->y + dy, s->width, h); + } + else + { + w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x, + s->y + dy, s->width, h); + } +} + +static void +w32_draw_strike_through (struct glyph_string *s, int y, int height) +{ + if (!FONT_TEXTMETRIC (s->font).tmStruckOut) + { + if (s->face->strike_through_color_defaulted_p) + { + w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, + y, s->width, height); + } + else + { + w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x, + y, s->width, height); + } + } +} + /* Draw a hollow rectangle at the specified position. */ static void w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y, @@ -1132,6 +1197,13 @@ w32_set_glyph_string_clipping_exactly (struct glyph_string *src, w32_set_clip_rectangle (dst->hdc, &r); } +static void +w32_reset_glyph_string_clipping (struct glyph_string *s) +{ + w32_set_clip_rectangle (s->hdc, NULL); + s->num_clips = 0; +} + /* RIF: Compute left and right overhang of glyph string S. */ @@ -2384,308 +2456,6 @@ w32_draw_stretch_glyph_string (struct glyph_string *s) } -/* Draw glyph string S. */ - -static void -w32_draw_glyph_string (struct glyph_string *s) -{ - bool relief_drawn_p = 0; - - /* If S draws into the background of its successor, draw the - background of the successor first so that S can draw into it. - This makes S->next use XDrawString instead of XDrawImageString. */ - if (s->next && s->right_overhang && !s->for_overlaps) - { - int width; - struct glyph_string *next; - for (width = 0, next = s->next; - next && width < s->right_overhang; - width += next->width, next = next->next) - if (next->first_glyph->type != IMAGE_GLYPH) - { - w32_set_glyph_string_gc (next); - w32_set_glyph_string_clipping (next); - if (next->first_glyph->type == STRETCH_GLYPH) - w32_draw_stretch_glyph_string (next); - else - w32_draw_glyph_string_background (next, true); - next->num_clips = 0; - } - } - - /* Set up S->gc, set clipping and draw S. */ - w32_set_glyph_string_gc (s); - - /* Draw relief (if any) in advance for char/composition so that the - glyph string can be drawn over it. */ - if (!s->for_overlaps - && s->face->box != FACE_NO_BOX - && (s->first_glyph->type == CHAR_GLYPH - || s->first_glyph->type == COMPOSITE_GLYPH)) - - { - w32_set_glyph_string_clipping (s); - w32_draw_glyph_string_background (s, true); - w32_draw_glyph_string_box (s); - w32_set_glyph_string_clipping (s); - relief_drawn_p = 1; - } - else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ - && !s->clip_tail - && ((s->prev && s->prev->hl != s->hl && s->left_overhang) - || (s->next && s->next->hl != s->hl && s->right_overhang))) - /* We must clip just this glyph. left_overhang part has already - drawn when s->prev was drawn, and right_overhang part will be - drawn later when s->next is drawn. */ - w32_set_glyph_string_clipping_exactly (s, s); - else - w32_set_glyph_string_clipping (s); - - switch (s->first_glyph->type) - { - case IMAGE_GLYPH: - w32_draw_image_glyph_string (s); - break; - - case STRETCH_GLYPH: - w32_draw_stretch_glyph_string (s); - break; - - case CHAR_GLYPH: - if (s->for_overlaps) - s->background_filled_p = true; - else - w32_draw_glyph_string_background (s, false); - w32_draw_glyph_string_foreground (s); - break; - - case COMPOSITE_GLYPH: - if (s->for_overlaps || (s->cmp_from > 0 - && ! s->first_glyph->u.cmp.automatic)) - s->background_filled_p = true; - else - w32_draw_glyph_string_background (s, true); - w32_draw_composite_glyph_string_foreground (s); - break; - - case GLYPHLESS_GLYPH: - if (s->for_overlaps) - s->background_filled_p = true; - else - w32_draw_glyph_string_background (s, false); - w32_draw_glyphless_glyph_string_foreground (s); - break; - - default: - emacs_abort (); - } - - if (!s->for_overlaps) - { - /* Draw underline. */ - if (s->face->underline_p) - { - if (s->face->underline_type == FACE_UNDER_WAVE) - { - COLORREF color; - - if (s->face->underline_defaulted_p) - color = s->gc->foreground; - else - color = s->face->underline_color; - - w32_draw_underwave (s, color); - } - else if (s->face->underline_type == FACE_UNDER_LINE) - { - unsigned long thickness, position; - int y; - - if (s->prev && s->prev->face->underline_p - && s->prev->face->underline_type == FACE_UNDER_LINE) - { - /* We use the same underline style as the previous one. */ - thickness = s->prev->underline_thickness; - position = s->prev->underline_position; - } - else - { - struct font *font = font_for_underline_metrics (s); - unsigned long minimum_offset; - BOOL underline_at_descent_line; - BOOL use_underline_position_properties; - Lisp_Object val - = buffer_local_value (Qunderline_minimum_offset, - s->w->contents); - if (FIXNUMP (val)) - minimum_offset = XFIXNAT (val); - else - minimum_offset = 1; - val = buffer_local_value (Qx_underline_at_descent_line, - s->w->contents); - underline_at_descent_line - = !(NILP (val) || EQ (val, Qunbound)); - val - = buffer_local_value (Qx_use_underline_position_properties, - s->w->contents); - use_underline_position_properties - = !(NILP (val) || EQ (val, Qunbound)); - - /* Get the underline thickness. Default is 1 pixel. */ - if (font && font->underline_thickness > 0) - thickness = font->underline_thickness; - else - thickness = 1; - if (underline_at_descent_line - || !font) - position = (s->height - thickness) - (s->ybase - s->y); - else - { - /* Get the underline position. This is the - recommended vertical offset in pixels from - the baseline to the top of the underline. - This is a signed value according to the - specs, and its default is - - ROUND ((maximum_descent) / 2), with - ROUND (x) = floor (x + 0.5) */ - - if (use_underline_position_properties - && font->underline_position >= 0) - position = font->underline_position; - else - position = (font->descent + 1) / 2; - } - position = max (position, minimum_offset); - } - /* Check the sanity of thickness and position. We should - avoid drawing underline out of the current line area. */ - if (s->y + s->height <= s->ybase + position) - position = (s->height - 1) - (s->ybase - s->y); - if (s->y + s->height < s->ybase + position + thickness) - thickness = (s->y + s->height) - (s->ybase + position); - s->underline_thickness = thickness; - s->underline_position = position; - y = s->ybase + position; - if (s->face->underline_defaulted_p) - { - w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, - y, s->width, 1); - } - else - { - w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, - y, s->width, 1); - } - } - } - /* Draw overline. */ - if (s->face->overline_p) - { - unsigned long dy = 0, h = 1; - - if (s->face->overline_color_defaulted_p) - { - w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, - s->y + dy, s->width, h); - } - else - { - w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x, - s->y + dy, s->width, h); - } - } - - /* Draw strike-through. */ - if (s->face->strike_through_p - && !FONT_TEXTMETRIC (s->font).tmStruckOut) - { - /* Y-coordinate and height of the glyph string's first - glyph. We cannot use s->y and s->height because those - could be larger if there are taller display elements - (e.g., characters displayed with a larger font) in the - same glyph row. */ - int glyph_y = s->ybase - s->first_glyph->ascent; - int glyph_height = s->first_glyph->ascent + s->first_glyph->descent; - /* Strike-through width and offset from the glyph string's - top edge. */ - unsigned long h = 1; - unsigned long dy = (glyph_height - h) / 2; - - if (s->face->strike_through_color_defaulted_p) - { - w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, - glyph_y + dy, s->width, h); - } - else - { - w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x, - glyph_y + dy, s->width, h); - } - } - - /* Draw relief if not yet drawn. */ - if (!relief_drawn_p && s->face->box != FACE_NO_BOX) - w32_draw_glyph_string_box (s); - - if (s->prev) - { - struct glyph_string *prev; - - for (prev = s->prev; prev; prev = prev->prev) - if (prev->hl != s->hl - && prev->x + prev->width + prev->right_overhang > s->x) - { - /* As prev was drawn while clipped to its own area, we - must draw the right_overhang part using s->hl now. */ - enum draw_glyphs_face save = prev->hl; - - prev->hl = s->hl; - w32_set_glyph_string_gc (prev); - w32_set_glyph_string_clipping_exactly (s, prev); - if (prev->first_glyph->type == CHAR_GLYPH) - w32_draw_glyph_string_foreground (prev); - else - w32_draw_composite_glyph_string_foreground (prev); - w32_set_clip_rectangle (prev->hdc, NULL); - prev->hl = save; - prev->num_clips = 0; - } - } - - if (s->next) - { - struct glyph_string *next; - - for (next = s->next; next; next = next->next) - if (next->hl != s->hl - && next->x - next->left_overhang < s->x + s->width) - { - /* As next will be drawn while clipped to its own area, - we must draw the left_overhang part using s->hl now. */ - enum draw_glyphs_face save = next->hl; - - next->hl = s->hl; - w32_set_glyph_string_gc (next); - w32_set_glyph_string_clipping_exactly (s, next); - if (next->first_glyph->type == CHAR_GLYPH) - w32_draw_glyph_string_foreground (next); - else - w32_draw_composite_glyph_string_foreground (next); - w32_set_clip_rectangle (next->hdc, NULL); - next->hl = save; - next->num_clips = 0; - next->clip_head = s->next; - } - } - } - - /* Reset clipping. */ - w32_set_clip_rectangle (s->hdc, NULL); - s->num_clips = 0; -} - - /* Shift display to make room for inserted glyphs. */ static void @@ -7077,6 +6847,26 @@ w32_make_rdb (char *xrm_option) extern frame_parm_handler w32_frame_parm_handlers[]; +static struct draw_glyph_string_interface w32_draw_glyph_string_interface = +{ + w32_set_glyph_string_gc, + w32_set_glyph_string_clipping, + w32_set_glyph_string_clipping_exactly, + w32_reset_glyph_string_clipping, + w32_draw_glyph_string_background, + w32_draw_glyph_string_foreground, + w32_draw_glyph_string_box, + w32_draw_image_glyph_string, + w32_draw_stretch_glyph_string, + NULL, /* draw_xwidget_glyph_string */ + w32_draw_composite_glyph_string_foreground, + w32_draw_glyphless_glyph_string_foreground, + w32_draw_underwave, + w32_draw_underline, + w32_draw_overline, + w32_draw_strike_through +}; + static struct redisplay_interface w32_redisplay_interface = { w32_frame_parm_handlers, @@ -7096,7 +6886,8 @@ static struct redisplay_interface w32_redisplay_interface = w32_define_fringe_bitmap, w32_destroy_fringe_bitmap, w32_compute_glyph_string_overhangs, - w32_draw_glyph_string, + gui_draw_glyph_string, + &w32_draw_glyph_string_interface, w32_define_frame_cursor, w32_clear_frame_area, w32_clear_under_internal_border, @@ -7471,21 +7262,6 @@ the cursor have no effect. */); w32_use_visible_system_caret = 0; - /* We don't yet support this, but defining this here avoids whining - from cus-start.el and other places, like "M-x set-variable". */ - DEFVAR_BOOL ("x-use-underline-position-properties", - x_use_underline_position_properties, - doc: /* SKIP: real doc in xterm.c. */); - x_use_underline_position_properties = 0; - DEFSYM (Qx_use_underline_position_properties, - "x-use-underline-position-properties"); - - DEFVAR_BOOL ("x-underline-at-descent-line", - x_underline_at_descent_line, - doc: /* SKIP: real doc in xterm.c. */); - x_underline_at_descent_line = 0; - DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line"); - DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, doc: /* SKIP: real doc in xterm.c. */); Vx_toolkit_scroll_bars = Qt; diff --git a/src/xdisp.c b/src/xdisp.c index a3dddfa8a5..2f5aaf6aff 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -29099,6 +29099,269 @@ gui_insert_glyphs (struct window *w, struct glyph_row *updated_row, unblock_input (); } +/* EXPORT for RIF: + Draw glyph string S. */ + +void +gui_draw_glyph_string (struct glyph_string *s) +{ + bool relief_drawn_p = false; + struct draw_glyph_string_interface *gsif = FRAME_RIF (s->f)->gsif; + + if (!gsif) + emacs_abort (); + + /* If S draws into the background of its successors, draw the + background of the successors first so that S can draw into it. */ + if (s->next && s->right_overhang && !s->for_overlaps) + { + int width; + struct glyph_string *next; + + for (width = 0, next = s->next; + next && width < s->right_overhang; + width += next->width, next = next->next) + if (next->first_glyph->type != IMAGE_GLYPH) + { + gsif->set_gc (next); + gsif->set_clipping (next); + if (next->first_glyph->type == STRETCH_GLYPH) + gsif->draw_stretch (next); + else + gsif->draw_background (next, true); + next->num_clips = 0; + } + } + + /* Set up S->gc, set clipping and draw S. */ + gsif->set_gc (s); + + /* Draw relief (if any) in advance for char/composition so that the + glyph string can be drawn over it. */ + if (!s->for_overlaps + && s->face->box != FACE_NO_BOX + && (s->first_glyph->type == CHAR_GLYPH + || s->first_glyph->type == COMPOSITE_GLYPH)) + + { + gsif->set_clipping (s); + gsif->draw_background (s, true); + gsif->draw_box (s); + gsif->set_clipping (s); + relief_drawn_p = true; + } + else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ + && !s->clip_tail + && ((s->prev && s->prev->hl != s->hl && s->left_overhang) + || (s->next && s->next->hl != s->hl && s->right_overhang))) + /* We must clip just this glyph. left_overhang part has already + drawn when s->prev was drawn, and right_overhang part will be + drawn later when s->next is drawn. */ + gsif->set_clipping_exactly (s, s); + else + gsif->set_clipping (s); + + switch (s->first_glyph->type) + { + case IMAGE_GLYPH: + gsif->draw_image (s); + break; + + case STRETCH_GLYPH: + gsif->draw_stretch (s); + break; + + case CHAR_GLYPH: + if (s->for_overlaps) + s->background_filled_p = true; + else + gsif->draw_background (s, false); + gsif->draw_foreground (s); + break; + + case COMPOSITE_GLYPH: + if (s->for_overlaps || (s->cmp_from > 0 + && ! s->first_glyph->u.cmp.automatic)) + s->background_filled_p = true; + else + gsif->draw_background (s, true); + gsif->draw_composite_foreground (s); + break; + + case XWIDGET_GLYPH: + if (gsif->draw_xwidget) + gsif->draw_xwidget (s); + break; + + case GLYPHLESS_GLYPH: + if (s->for_overlaps) + s->background_filled_p = true; + else + gsif->draw_background (s, true); + gsif->draw_glyphless_foreground (s); + break; + + default: + emacs_abort (); + } + + if (!s->for_overlaps) + { + /* Draw underline. */ + if (s->face->underline_p) + { + if (s->face->underline_type == FACE_UNDER_WAVE) + gsif->draw_underwave (s); + else if (s->face->underline_type == FACE_UNDER_LINE) + { + unsigned long thickness, position; + + if (s->prev && s->prev->face->underline_p + && s->prev->face->underline_type == FACE_UNDER_LINE) + { + /* We use the same underline style as the previous one. */ + thickness = s->prev->underline_thickness; + position = s->prev->underline_position; + } + else + { + struct font *font = font_for_underline_metrics (s); + unsigned long minimum_offset; + bool underline_at_descent_line; + bool use_underline_position_properties; + Lisp_Object val + = buffer_local_value (Qunderline_minimum_offset, + s->w->contents); + if (FIXNUMP (val)) + minimum_offset = XFIXNAT (val); + else + minimum_offset = 1; + val = buffer_local_value (Qx_underline_at_descent_line, + s->w->contents); + underline_at_descent_line + = !(NILP (val) || EQ (val, Qunbound)); + val + = buffer_local_value (Qx_use_underline_position_properties, + s->w->contents); + use_underline_position_properties + = !(NILP (val) || EQ (val, Qunbound)); + + /* Get the underline thickness. Default is 1 pixel. */ + if (font && font->underline_thickness > 0) + thickness = font->underline_thickness; + else + thickness = 1; + if (underline_at_descent_line) + position = (s->height - thickness) - (s->ybase - s->y); + else + { + /* Get the underline position. This is the + recommended vertical offset in pixels from + the baseline to the top of the underline. + This is a signed value according to the + specs, and its default is + + ROUND ((maximum descent) / 2), with + ROUND(x) = floor (x + 0.5) */ + + if (use_underline_position_properties + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = (font->descent + 1) / 2; + else + position = minimum_offset; + } + position = max (position, minimum_offset); + } + /* Check the sanity of thickness and position. We should + avoid drawing underline out of the current line area. */ + if (s->y + s->height <= s->ybase + position) + position = (s->height - 1) - (s->ybase - s->y); + if (s->y + s->height < s->ybase + position + thickness) + thickness = (s->y + s->height) - (s->ybase + position); + s->underline_thickness = thickness; + s->underline_position = position; + gsif->draw_underline (s); + } + } + /* Draw overline. */ + if (s->face->overline_p) + gsif->draw_overline (s); + + /* Draw strike-through. */ + if (s->face->strike_through_p) + { + /* Y-coordinate and height of the glyph string's first + glyph. We cannot use s->y and s->height because those + could be larger if there are taller display elements + (e.g., characters displayed with a larger font) in the + same glyph row. */ + int glyph_y = s->ybase - s->first_glyph->ascent; + int glyph_height = s->first_glyph->ascent + s->first_glyph->descent; + /* Strike-through width and offset from the glyph string's + top edge. */ + unsigned long dy = (glyph_height - 1) / 2; + gsif->draw_strike_through (s, glyph_y + dy, 1); + } + + /* Draw relief if not yet drawn. */ + if (!relief_drawn_p && s->face->box != FACE_NO_BOX) + gsif->draw_box (s); + + if (s->prev) + { + struct glyph_string *prev; + + for (prev = s->prev; prev; prev = prev->prev) + if (prev->hl != s->hl + && prev->x + prev->width + prev->right_overhang > s->x) + { + /* As prev was drawn while clipped to its own area, we + must draw the right_overhang part using s->hl now. */ + enum draw_glyphs_face save = prev->hl; + + prev->hl = s->hl; + gsif->set_gc (prev); + gsif->set_clipping_exactly (s, prev); + if (prev->first_glyph->type == CHAR_GLYPH) + gsif->draw_foreground (prev); + else + gsif->draw_composite_foreground (prev); + gsif->reset_clipping (prev); + prev->hl = save; + } + } + + if (s->next) + { + struct glyph_string *next; + + for (next = s->next; next; next = next->next) + if (next->hl != s->hl + && next->x - next->left_overhang < s->x + s->width) + { + /* As next will be drawn while clipped to its own area, + we must draw the left_overhang part using s->hl now. */ + enum draw_glyphs_face save = next->hl; + + next->hl = s->hl; + gsif->set_gc (next); + gsif->set_clipping_exactly (s, next); + if (next->first_glyph->type == CHAR_GLYPH) + gsif->draw_foreground (next); + else + gsif->draw_composite_foreground (next); + gsif->reset_clipping (next); + next->hl = save; + next->clip_head = s->next; + } + } + } + + /* Reset clipping. */ + gsif->reset_clipping (s); +} /* EXPORT for RIF: Erase the current text line from the nominal cursor position @@ -33344,6 +33607,35 @@ baseline. The default value is 1. */); underline_minimum_offset = 1; DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset"); +#ifdef HAVE_WINDOW_SYSTEM + DEFVAR_BOOL ("x-use-underline-position-properties", + x_use_underline_position_properties, + doc: /* Non-nil means make use of UNDERLINE_POSITION font properties. +A value of nil means ignore them. If you encounter fonts with bogus +UNDERLINE_POSITION font properties, set this to nil. You can also use +`underline-minimum-offset' to override the font's UNDERLINE_POSITION for +small font display sizes. */); +# ifdef HAVE_X_WINDOWS + x_use_underline_position_properties = true; +# else + /* Other terms don't support this (yet?). */ + x_use_underline_position_properties = false; +# endif + DEFSYM (Qx_use_underline_position_properties, + "x-use-underline-position-properties"); + + DEFVAR_BOOL ("x-underline-at-descent-line", + x_underline_at_descent_line, + doc: /* Non-nil means to draw the underline at the same place as the descent line. +(If `line-spacing' is in effect, that moves the underline lower by +that many pixels.) +A value of nil means to draw the underline according to the value of the +variable `x-use-underline-position-properties', which is usually at the +baseline level. The default value is nil. */); + x_underline_at_descent_line = false; + DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line"); +#endif + DEFVAR_BOOL ("display-hourglass", display_hourglass_p, doc: /* Non-nil means show an hourglass pointer, when Emacs is busy. This feature only works when on a window system that can change diff --git a/src/xterm.c b/src/xterm.c index b08f5f6a62..5fe4491f7e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1626,6 +1626,12 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_stri x_set_clip_rectangles (dst->f, dst->gc, &r, 1); } +static void +x_reset_glyph_string_clipping (struct glyph_string *s) +{ + x_reset_clip_rectangles (s->f, s->gc); + s->num_clips = 0; +} /* RIF: Compute left and right overhang of glyph string S. */ @@ -3468,7 +3474,7 @@ x_get_scale_factor(Display *disp, int *scale_x, int *scale_y) */ static void -x_draw_underwave (struct glyph_string *s) +x_draw_underwave_1 (struct glyph_string *s) { /* Adjust for scale/HiDPI. */ int scale_x, scale_y; @@ -3535,319 +3541,73 @@ x_draw_underwave (struct glyph_string *s) #endif /* not USE_CAIRO */ } - -/* Draw glyph string S. */ - static void -x_draw_glyph_string (struct glyph_string *s) +x_draw_underwave (struct glyph_string *s) { - bool relief_drawn_p = false; - - /* If S draws into the background of its successors, draw the - background of the successors first so that S can draw into it. - This makes S->next use XDrawString instead of XDrawImageString. */ - if (s->next && s->right_overhang && !s->for_overlaps) + if (s->face->underline_defaulted_p) + x_draw_underwave_1 (s); + else { - int width; - struct glyph_string *next; - - for (width = 0, next = s->next; - next && width < s->right_overhang; - width += next->width, next = next->next) - if (next->first_glyph->type != IMAGE_GLYPH) - { - x_set_glyph_string_gc (next); - x_set_glyph_string_clipping (next); - if (next->first_glyph->type == STRETCH_GLYPH) - x_draw_stretch_glyph_string (next); - else - x_draw_glyph_string_background (next, true); - next->num_clips = 0; - } + XGCValues xgcv; + XGetGCValues (s->display, s->gc, GCForeground, &xgcv); + XSetForeground (s->display, s->gc, s->face->underline_color); + x_draw_underwave_1 (s); + XSetForeground (s->display, s->gc, xgcv.foreground); } +} - /* Set up S->gc, set clipping and draw S. */ - x_set_glyph_string_gc (s); - - /* Draw relief (if any) in advance for char/composition so that the - glyph string can be drawn over it. */ - if (!s->for_overlaps - && s->face->box != FACE_NO_BOX - && (s->first_glyph->type == CHAR_GLYPH - || s->first_glyph->type == COMPOSITE_GLYPH)) +static void +x_draw_underline (struct glyph_string *s) +{ + const int y = s->ybase + s->underline_position; + const int thickness = s->underline_thickness; - { - x_set_glyph_string_clipping (s); - x_draw_glyph_string_background (s, true); - x_draw_glyph_string_box (s); - x_set_glyph_string_clipping (s); - relief_drawn_p = true; - } - else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ - && !s->clip_tail - && ((s->prev && s->prev->hl != s->hl && s->left_overhang) - || (s->next && s->next->hl != s->hl && s->right_overhang))) - /* We must clip just this glyph. left_overhang part has already - drawn when s->prev was drawn, and right_overhang part will be - drawn later when s->next is drawn. */ - x_set_glyph_string_clipping_exactly (s, s); + if (s->face->underline_defaulted_p) + x_fill_rectangle (s->f, s->gc, + s->x, y, s->width, thickness); else - x_set_glyph_string_clipping (s); - - switch (s->first_glyph->type) { - case IMAGE_GLYPH: - x_draw_image_glyph_string (s); - break; - - case XWIDGET_GLYPH: - x_draw_xwidget_glyph_string (s); - break; - - case STRETCH_GLYPH: - x_draw_stretch_glyph_string (s); - break; - - case CHAR_GLYPH: - if (s->for_overlaps) - s->background_filled_p = true; - else - x_draw_glyph_string_background (s, false); - x_draw_glyph_string_foreground (s); - break; - - case COMPOSITE_GLYPH: - if (s->for_overlaps || (s->cmp_from > 0 - && ! s->first_glyph->u.cmp.automatic)) - s->background_filled_p = true; - else - x_draw_glyph_string_background (s, true); - x_draw_composite_glyph_string_foreground (s); - break; + XGCValues xgcv; + XGetGCValues (s->display, s->gc, GCForeground, &xgcv); + XSetForeground (s->display, s->gc, s->face->underline_color); + x_fill_rectangle (s->f, s->gc, + s->x, y, s->width, thickness); + XSetForeground (s->display, s->gc, xgcv.foreground); + } +} - case GLYPHLESS_GLYPH: - if (s->for_overlaps) - s->background_filled_p = true; - else - x_draw_glyph_string_background (s, true); - x_draw_glyphless_glyph_string_foreground (s); - break; +static void +x_draw_overline (struct glyph_string *s) +{ + unsigned long dy = 0, h = 1; - default: - emacs_abort (); + if (s->face->overline_color_defaulted_p) + x_fill_rectangle (s->f, s->gc, s->x, s->y + dy, + s->width, h); + else + { + XGCValues xgcv; + XGetGCValues (s->display, s->gc, GCForeground, &xgcv); + XSetForeground (s->display, s->gc, s->face->overline_color); + x_fill_rectangle (s->f, s->gc, s->x, s->y + dy, + s->width, h); + XSetForeground (s->display, s->gc, xgcv.foreground); } +} - if (!s->for_overlaps) +static void +x_draw_strike_through (struct glyph_string *s, int y, int height) +{ + if (s->face->strike_through_color_defaulted_p) + x_fill_rectangle (s->f, s->gc, s->x, y, s->width, height); + else { - /* Draw underline. */ - if (s->face->underline_p) - { - if (s->face->underline_type == FACE_UNDER_WAVE) - { - if (s->face->underline_defaulted_p) - x_draw_underwave (s); - else - { - XGCValues xgcv; - XGetGCValues (s->display, s->gc, GCForeground, &xgcv); - XSetForeground (s->display, s->gc, s->face->underline_color); - x_draw_underwave (s); - XSetForeground (s->display, s->gc, xgcv.foreground); - } - } - else if (s->face->underline_type == FACE_UNDER_LINE) - { - unsigned long thickness, position; - int y; - - if (s->prev && s->prev->face->underline_p - && s->prev->face->underline_type == FACE_UNDER_LINE) - { - /* We use the same underline style as the previous one. */ - thickness = s->prev->underline_thickness; - position = s->prev->underline_position; - } - else - { - struct font *font = font_for_underline_metrics (s); - unsigned long minimum_offset; - bool underline_at_descent_line; - bool use_underline_position_properties; - Lisp_Object val - = buffer_local_value (Qunderline_minimum_offset, - s->w->contents); - if (FIXNUMP (val)) - minimum_offset = XFIXNAT (val); - else - minimum_offset = 1; - val = buffer_local_value (Qx_underline_at_descent_line, - s->w->contents); - underline_at_descent_line - = !(NILP (val) || EQ (val, Qunbound)); - val - = buffer_local_value (Qx_use_underline_position_properties, - s->w->contents); - use_underline_position_properties - = !(NILP (val) || EQ (val, Qunbound)); - - /* Get the underline thickness. Default is 1 pixel. */ - if (font && font->underline_thickness > 0) - thickness = font->underline_thickness; - else - thickness = 1; - if (underline_at_descent_line) - position = (s->height - thickness) - (s->ybase - s->y); - else - { - /* Get the underline position. This is the - recommended vertical offset in pixels from - the baseline to the top of the underline. - This is a signed value according to the - specs, and its default is - - ROUND ((maximum descent) / 2), with - ROUND(x) = floor (x + 0.5) */ - - if (use_underline_position_properties - && font && font->underline_position >= 0) - position = font->underline_position; - else if (font) - position = (font->descent + 1) / 2; - else - position = minimum_offset; - } - position = max (position, minimum_offset); - } - /* Check the sanity of thickness and position. We should - avoid drawing underline out of the current line area. */ - if (s->y + s->height <= s->ybase + position) - position = (s->height - 1) - (s->ybase - s->y); - if (s->y + s->height < s->ybase + position + thickness) - thickness = (s->y + s->height) - (s->ybase + position); - s->underline_thickness = thickness; - s->underline_position = position; - y = s->ybase + position; - if (s->face->underline_defaulted_p) - x_fill_rectangle (s->f, s->gc, - s->x, y, s->width, thickness); - else - { - XGCValues xgcv; - XGetGCValues (s->display, s->gc, GCForeground, &xgcv); - XSetForeground (s->display, s->gc, s->face->underline_color); - x_fill_rectangle (s->f, s->gc, - s->x, y, s->width, thickness); - XSetForeground (s->display, s->gc, xgcv.foreground); - } - } - } - /* Draw overline. */ - if (s->face->overline_p) - { - unsigned long dy = 0, h = 1; - - if (s->face->overline_color_defaulted_p) - x_fill_rectangle (s->f, s->gc, s->x, s->y + dy, - s->width, h); - else - { - XGCValues xgcv; - XGetGCValues (s->display, s->gc, GCForeground, &xgcv); - XSetForeground (s->display, s->gc, s->face->overline_color); - x_fill_rectangle (s->f, s->gc, s->x, s->y + dy, - s->width, h); - XSetForeground (s->display, s->gc, xgcv.foreground); - } - } - - /* Draw strike-through. */ - if (s->face->strike_through_p) - { - /* Y-coordinate and height of the glyph string's first - glyph. We cannot use s->y and s->height because those - could be larger if there are taller display elements - (e.g., characters displayed with a larger font) in the - same glyph row. */ - int glyph_y = s->ybase - s->first_glyph->ascent; - int glyph_height = s->first_glyph->ascent + s->first_glyph->descent; - /* Strike-through width and offset from the glyph string's - top edge. */ - unsigned long h = 1; - unsigned long dy = (glyph_height - h) / 2; - - if (s->face->strike_through_color_defaulted_p) - x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy, - s->width, h); - else - { - XGCValues xgcv; - XGetGCValues (s->display, s->gc, GCForeground, &xgcv); - XSetForeground (s->display, s->gc, s->face->strike_through_color); - x_fill_rectangle (s->f, s->gc, s->x, glyph_y + dy, - s->width, h); - XSetForeground (s->display, s->gc, xgcv.foreground); - } - } - - /* Draw relief if not yet drawn. */ - if (!relief_drawn_p && s->face->box != FACE_NO_BOX) - x_draw_glyph_string_box (s); - - if (s->prev) - { - struct glyph_string *prev; - - for (prev = s->prev; prev; prev = prev->prev) - if (prev->hl != s->hl - && prev->x + prev->width + prev->right_overhang > s->x) - { - /* As prev was drawn while clipped to its own area, we - must draw the right_overhang part using s->hl now. */ - enum draw_glyphs_face save = prev->hl; - - prev->hl = s->hl; - x_set_glyph_string_gc (prev); - x_set_glyph_string_clipping_exactly (s, prev); - if (prev->first_glyph->type == CHAR_GLYPH) - x_draw_glyph_string_foreground (prev); - else - x_draw_composite_glyph_string_foreground (prev); - x_reset_clip_rectangles (prev->f, prev->gc); - prev->hl = save; - prev->num_clips = 0; - } - } - - if (s->next) - { - struct glyph_string *next; - - for (next = s->next; next; next = next->next) - if (next->hl != s->hl - && next->x - next->left_overhang < s->x + s->width) - { - /* As next will be drawn while clipped to its own area, - we must draw the left_overhang part using s->hl now. */ - enum draw_glyphs_face save = next->hl; - - next->hl = s->hl; - x_set_glyph_string_gc (next); - x_set_glyph_string_clipping_exactly (s, next); - if (next->first_glyph->type == CHAR_GLYPH) - x_draw_glyph_string_foreground (next); - else - x_draw_composite_glyph_string_foreground (next); - x_reset_clip_rectangles (next->f, next->gc); - next->hl = save; - next->num_clips = 0; - next->clip_head = s->next; - } - } + XGCValues xgcv; + XGetGCValues (s->display, s->gc, GCForeground, &xgcv); + XSetForeground (s->display, s->gc, s->face->strike_through_color); + x_fill_rectangle (s->f, s->gc, s->x, y, s->width, height); + XSetForeground (s->display, s->gc, xgcv.foreground); } - - /* Reset clipping. */ - x_reset_clip_rectangles (s->f, s->gc); - s->num_clips = 0; } /* Shift display to make room for inserted glyphs. */ @@ -13060,6 +12820,26 @@ x_activate_timeout_atimer (void) extern frame_parm_handler x_frame_parm_handlers[]; +static struct draw_glyph_string_interface x_draw_glyph_string_interface = + { + x_set_glyph_string_gc, + x_set_glyph_string_clipping, + x_set_glyph_string_clipping_exactly, + x_reset_glyph_string_clipping, + x_draw_glyph_string_background, + x_draw_glyph_string_foreground, + x_draw_glyph_string_box, + x_draw_image_glyph_string, + x_draw_stretch_glyph_string, + x_draw_xwidget_glyph_string, + x_draw_composite_glyph_string_foreground, + x_draw_glyphless_glyph_string_foreground, + x_draw_underwave, + x_draw_underline, + x_draw_overline, + x_draw_strike_through + }; + static struct redisplay_interface x_redisplay_interface = { x_frame_parm_handlers, @@ -13084,7 +12864,8 @@ static struct redisplay_interface x_redisplay_interface = 0, /* destroy_fringe_bitmap */ #endif x_compute_glyph_string_overhangs, - x_draw_glyph_string, + gui_draw_glyph_string, + &x_draw_glyph_string_interface, x_define_frame_cursor, x_clear_frame_area, x_clear_under_internal_border, @@ -13327,28 +13108,6 @@ syms_of_xterm (void) DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); #endif - DEFVAR_BOOL ("x-use-underline-position-properties", - x_use_underline_position_properties, - doc: /* Non-nil means make use of UNDERLINE_POSITION font properties. -A value of nil means ignore them. If you encounter fonts with bogus -UNDERLINE_POSITION font properties, set this to nil. You can also use -`underline-minimum-offset' to override the font's UNDERLINE_POSITION for -small font display sizes. */); - x_use_underline_position_properties = true; - DEFSYM (Qx_use_underline_position_properties, - "x-use-underline-position-properties"); - - DEFVAR_BOOL ("x-underline-at-descent-line", - x_underline_at_descent_line, - doc: /* Non-nil means to draw the underline at the same place as the descent line. -(If `line-spacing' is in effect, that moves the underline lower by -that many pixels.) -A value of nil means to draw the underline according to the value of the -variable `x-use-underline-position-properties', which is usually at the -baseline level. The default value is nil. */); - x_underline_at_descent_line = false; - DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line"); - DEFVAR_BOOL ("x-mouse-click-focus-ignore-position", x_mouse_click_focus_ignore_position, doc: /* Non-nil means that a mouse click to focus a frame does not move point. -- 2.21.0 --=-=-=--