diff options
| author | Eli Zaretskii | 2020-04-23 18:40:42 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2020-04-23 18:40:42 +0300 |
| commit | 5ab80286f6f765ba41004030ea8cc19be7c1c098 (patch) | |
| tree | e4923b8c1c20da115eb5a4423b36e6034b6ce0b7 /src | |
| parent | 7b15cc3ebb45e50ac5faf3bbc2a813afffdaa418 (diff) | |
| download | emacs-5ab80286f6f765ba41004030ea8cc19be7c1c098.tar.gz emacs-5ab80286f6f765ba41004030ea8cc19be7c1c098.zip | |
Fix display of composed text with :box face attribute
* src/xdisp.c (get_next_display_element): For a composition on a
display or overlay string, set the end_of_box_run_p flag if the
string ends at the last character included in the composition.
(fill_gstring_glyph_string): Fix the way the width of a gstring
glyph string is calculated: use the values calculated in
gui_produce_glyphs, since the latter adjusts the width due to the
face's ':box' attribute.
* src/xterm.c (x_draw_glyph_string_box):
* src/w32term.c (w32_draw_glyph_string_box):
* src/nsterm.m (ns_dumpglyphs_box_or_relief): Support automatic
compositions, which have the right_box_line_p flag set on the last
glyph produced from the composition. (Bug#40687)
* src/w32term.c (w32_compute_glyph_string_overhangs): Update to be
consistent with xterm.c in its support of automatic composition
glyph strings.
* src/dispextern.h (enum glyph_type): More accurate commentary.
* src/.gdbinit (pgx): Display slice.img members only for image
glyphs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gdbinit | 6 | ||||
| -rw-r--r-- | src/dispextern.h | 2 | ||||
| -rw-r--r-- | src/nsterm.m | 17 | ||||
| -rw-r--r-- | src/w32term.c | 51 | ||||
| -rw-r--r-- | src/xdisp.c | 18 | ||||
| -rw-r--r-- | src/xterm.c | 24 |
6 files changed, 92 insertions, 26 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 30c7b055ce0..78536fc01fb 100644 --- a/src/.gdbinit +++ b/src/.gdbinit | |||
| @@ -500,6 +500,9 @@ define pgx | |||
| 500 | # IMAGE_GLYPH | 500 | # IMAGE_GLYPH |
| 501 | if ($g.type == 3) | 501 | if ($g.type == 3) |
| 502 | printf "IMAGE[%d]", $g.u.img_id | 502 | printf "IMAGE[%d]", $g.u.img_id |
| 503 | if ($g.slice.img.x || $g.slice.img.y || $g.slice.img.width || $g.slice.img.height) | ||
| 504 | printf " slice=%d,%d,%d,%d" ,$g.slice.img.x, $g.slice.img.y, $g.slice.img.width, $g.slice.img.height | ||
| 505 | end | ||
| 503 | end | 506 | end |
| 504 | # STRETCH_GLYPH | 507 | # STRETCH_GLYPH |
| 505 | if ($g.type == 4) | 508 | if ($g.type == 4) |
| @@ -551,9 +554,6 @@ define pgx | |||
| 551 | if ($g.right_box_line_p) | 554 | if ($g.right_box_line_p) |
| 552 | printf " ]" | 555 | printf " ]" |
| 553 | end | 556 | end |
| 554 | if ($g.slice.img.x || $g.slice.img.y || $g.slice.img.width || $g.slice.img.height) | ||
| 555 | printf " slice=%d,%d,%d,%d" ,$g.slice.img.x, $g.slice.img.y, $g.slice.img.width, $g.slice.img.height | ||
| 556 | end | ||
| 557 | printf "\n" | 557 | printf "\n" |
| 558 | end | 558 | end |
| 559 | document pgx | 559 | document pgx |
diff --git a/src/dispextern.h b/src/dispextern.h index d6fe68cf99f..0b1f3d14aeb 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -369,7 +369,7 @@ enum glyph_type | |||
| 369 | /* Glyph describes a character. */ | 369 | /* Glyph describes a character. */ |
| 370 | CHAR_GLYPH, | 370 | CHAR_GLYPH, |
| 371 | 371 | ||
| 372 | /* Glyph describes a static composition. */ | 372 | /* Glyph describes a static or automatic composition. */ |
| 373 | COMPOSITE_GLYPH, | 373 | COMPOSITE_GLYPH, |
| 374 | 374 | ||
| 375 | /* Glyph describes a glyphless character. */ | 375 | /* Glyph describes a glyphless character. */ |
diff --git a/src/nsterm.m b/src/nsterm.m index 5eb44639f56..a8f7540ea20 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -3872,8 +3872,21 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s) | |||
| 3872 | last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) | 3872 | last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) |
| 3873 | ? WINDOW_RIGHT_EDGE_X (s->w) | 3873 | ? WINDOW_RIGHT_EDGE_X (s->w) |
| 3874 | : window_box_right (s->w, s->area)); | 3874 | : window_box_right (s->w, s->area)); |
| 3875 | last_glyph = (s->cmp || s->img | 3875 | if (s->cmp || s->img) |
| 3876 | ? s->first_glyph : s->first_glyph + s->nchars-1); | 3876 | last_glyph = s->first_glyph; |
| 3877 | else if (s->first_glyph->type == COMPOSITE_GLYPH | ||
| 3878 | && s->first_glyph->u.cmp.automatic) | ||
| 3879 | { | ||
| 3880 | struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area]; | ||
| 3881 | struct glyph *g = s->first_glyph; | ||
| 3882 | for (last_glyph = g++; | ||
| 3883 | g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id | ||
| 3884 | && g->slice.cmp.to < s->cmp_to; | ||
| 3885 | last_glyph = g++) | ||
| 3886 | ; | ||
| 3887 | } | ||
| 3888 | else | ||
| 3889 | last_glyph = s->first_glyph + s->nchars - 1; | ||
| 3877 | 3890 | ||
| 3878 | right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p | 3891 | right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p |
| 3879 | ? last_x - 1 : min (last_x, s->x + s->background_width) - 1)); | 3892 | ? last_x - 1 : min (last_x, s->x + s->background_width) - 1)); |
diff --git a/src/w32term.c b/src/w32term.c index 108cb7922fb..1766b32514f 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -1101,19 +1101,28 @@ w32_set_glyph_string_clipping_exactly (struct glyph_string *src, | |||
| 1101 | static void | 1101 | static void |
| 1102 | w32_compute_glyph_string_overhangs (struct glyph_string *s) | 1102 | w32_compute_glyph_string_overhangs (struct glyph_string *s) |
| 1103 | { | 1103 | { |
| 1104 | if (s->cmp == NULL | 1104 | if (s->cmp == NULL) |
| 1105 | && s->first_glyph->type == CHAR_GLYPH | ||
| 1106 | && !s->font_not_found_p) | ||
| 1107 | { | 1105 | { |
| 1108 | struct font *font = s->font; | ||
| 1109 | struct font_metrics metrics; | 1106 | struct font_metrics metrics; |
| 1107 | if (s->first_glyph->type == CHAR_GLYPH && !s->font_not_found_p) | ||
| 1108 | { | ||
| 1109 | struct font *font = s->font; | ||
| 1110 | font->driver->text_extents (font, s->char2b, s->nchars, &metrics); | ||
| 1111 | s->right_overhang = (metrics.rbearing > metrics.width | ||
| 1112 | ? metrics.rbearing - metrics.width : 0); | ||
| 1113 | s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0; | ||
| 1114 | } | ||
| 1115 | else if (s->first_glyph->type == COMPOSITE_GLYPH) | ||
| 1116 | { | ||
| 1117 | Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); | ||
| 1110 | 1118 | ||
| 1111 | font->driver->text_extents (font, s->char2b, s->nchars, &metrics); | 1119 | composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics); |
| 1112 | s->right_overhang = (metrics.rbearing > metrics.width | 1120 | s->right_overhang = (metrics.rbearing > metrics.width |
| 1113 | ? metrics.rbearing - metrics.width : 0); | 1121 | ? metrics.rbearing - metrics.width : 0); |
| 1114 | s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0; | 1122 | s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0; |
| 1123 | } | ||
| 1115 | } | 1124 | } |
| 1116 | else if (s->cmp) | 1125 | else |
| 1117 | { | 1126 | { |
| 1118 | s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; | 1127 | s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; |
| 1119 | s->left_overhang = -s->cmp->lbearing; | 1128 | s->left_overhang = -s->cmp->lbearing; |
| @@ -1725,10 +1734,26 @@ w32_draw_glyph_string_box (struct glyph_string *s) | |||
| 1725 | ? WINDOW_RIGHT_EDGE_X (s->w) | 1734 | ? WINDOW_RIGHT_EDGE_X (s->w) |
| 1726 | : window_box_right (s->w, s->area)); | 1735 | : window_box_right (s->w, s->area)); |
| 1727 | 1736 | ||
| 1728 | /* The glyph that may have a right box line. */ | 1737 | /* The glyph that may have a right box line. For static |
| 1729 | last_glyph = (s->cmp || s->img | 1738 | compositions and images, the right-box flag is on the first glyph |
| 1730 | ? s->first_glyph | 1739 | of the glyph string; for other types it's on the last glyph. */ |
| 1731 | : s->first_glyph + s->nchars - 1); | 1740 | if (s->cmp || s->img) |
| 1741 | last_glyph = s->first_glyph; | ||
| 1742 | else if (s->first_glyph->type == COMPOSITE_GLYPH | ||
| 1743 | && s->first_glyph->u.cmp.automatic) | ||
| 1744 | { | ||
| 1745 | /* For automatic compositions, we need to look up the last glyph | ||
| 1746 | in the composition. */ | ||
| 1747 | struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area]; | ||
| 1748 | struct glyph *g = s->first_glyph; | ||
| 1749 | for (last_glyph = g++; | ||
| 1750 | g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id | ||
| 1751 | && g->slice.cmp.to < s->cmp_to; | ||
| 1752 | last_glyph = g++) | ||
| 1753 | ; | ||
| 1754 | } | ||
| 1755 | else | ||
| 1756 | last_glyph = s->first_glyph + s->nchars - 1; | ||
| 1732 | 1757 | ||
| 1733 | vwidth = eabs (s->face->box_vertical_line_width); | 1758 | vwidth = eabs (s->face->box_vertical_line_width); |
| 1734 | hwidth = eabs (s->face->box_horizontal_line_width); | 1759 | hwidth = eabs (s->face->box_horizontal_line_width); |
diff --git a/src/xdisp.c b/src/xdisp.c index 01f272033e5..32588939564 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -7617,7 +7617,13 @@ get_next_display_element (struct it *it) | |||
| 7617 | /* Otherwise, the box comes from the underlying face. | 7617 | /* Otherwise, the box comes from the underlying face. |
| 7618 | If this is the last string character displayed, check | 7618 | If this is the last string character displayed, check |
| 7619 | the next buffer location. */ | 7619 | the next buffer location. */ |
| 7620 | else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1) | 7620 | else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1) |
| 7621 | /* For a composition, see if the string ends | ||
| 7622 | at the last character included in the | ||
| 7623 | composition. */ | ||
| 7624 | || (it->what == IT_COMPOSITION | ||
| 7625 | && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars | ||
| 7626 | >= SCHARS (it->string)))) | ||
| 7621 | /* n_overlay_strings is unreliable unless | 7627 | /* n_overlay_strings is unreliable unless |
| 7622 | overlay_string_index is non-negative. */ | 7628 | overlay_string_index is non-negative. */ |
| 7623 | && ((it->current.overlay_string_index >= 0 | 7629 | && ((it->current.overlay_string_index >= 0 |
| @@ -27567,12 +27573,18 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, | |||
| 27567 | s->face = FACE_FROM_ID (s->f, face_id); | 27573 | s->face = FACE_FROM_ID (s->f, face_id); |
| 27568 | lgstring = composition_gstring_from_id (s->cmp_id); | 27574 | lgstring = composition_gstring_from_id (s->cmp_id); |
| 27569 | s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring)); | 27575 | s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring)); |
| 27576 | /* The width of a composition glyph string is the sum of the | ||
| 27577 | composition's glyph widths. */ | ||
| 27578 | s->width = s->first_glyph->pixel_width; | ||
| 27570 | glyph++; | 27579 | glyph++; |
| 27571 | while (glyph < last | 27580 | while (glyph < last |
| 27572 | && glyph->u.cmp.automatic | 27581 | && glyph->u.cmp.automatic |
| 27573 | && glyph->u.cmp.id == s->cmp_id | 27582 | && glyph->u.cmp.id == s->cmp_id |
| 27574 | && s->cmp_to == glyph->slice.cmp.from) | 27583 | && s->cmp_to == glyph->slice.cmp.from) |
| 27575 | s->cmp_to = (glyph++)->slice.cmp.to + 1; | 27584 | { |
| 27585 | s->width += glyph->pixel_width; | ||
| 27586 | s->cmp_to = (glyph++)->slice.cmp.to + 1; | ||
| 27587 | } | ||
| 27576 | 27588 | ||
| 27577 | for (i = s->cmp_from; i < s->cmp_to; i++) | 27589 | for (i = s->cmp_from; i < s->cmp_to; i++) |
| 27578 | { | 27590 | { |
| @@ -27582,7 +27594,7 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, | |||
| 27582 | /* Ensure that the code is only 2 bytes wide. */ | 27594 | /* Ensure that the code is only 2 bytes wide. */ |
| 27583 | s->char2b[i] = code & 0xFFFF; | 27595 | s->char2b[i] = code & 0xFFFF; |
| 27584 | } | 27596 | } |
| 27585 | s->width = composition_gstring_width (lgstring, s->cmp_from, s->cmp_to, NULL); | 27597 | |
| 27586 | return glyph - s->row->glyphs[s->area]; | 27598 | return glyph - s->row->glyphs[s->area]; |
| 27587 | } | 27599 | } |
| 27588 | 27600 | ||
diff --git a/src/xterm.c b/src/xterm.c index afe9c3da5b8..7989cecec7f 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -2986,10 +2986,26 @@ x_draw_glyph_string_box (struct glyph_string *s) | |||
| 2986 | ? WINDOW_RIGHT_EDGE_X (s->w) | 2986 | ? WINDOW_RIGHT_EDGE_X (s->w) |
| 2987 | : window_box_right (s->w, s->area)); | 2987 | : window_box_right (s->w, s->area)); |
| 2988 | 2988 | ||
| 2989 | /* The glyph that may have a right box line. */ | 2989 | /* The glyph that may have a right box line. For static |
| 2990 | last_glyph = (s->cmp || s->img | 2990 | compositions and images, the right-box flag is on the first glyph |
| 2991 | ? s->first_glyph | 2991 | of the glyph string; for other types it's on the last glyph. */ |
| 2992 | : s->first_glyph + s->nchars - 1); | 2992 | if (s->cmp || s->img) |
| 2993 | last_glyph = s->first_glyph; | ||
| 2994 | else if (s->first_glyph->type == COMPOSITE_GLYPH | ||
| 2995 | && s->first_glyph->u.cmp.automatic) | ||
| 2996 | { | ||
| 2997 | /* For automatic compositions, we need to look up the last glyph | ||
| 2998 | in the composition. */ | ||
| 2999 | struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area]; | ||
| 3000 | struct glyph *g = s->first_glyph; | ||
| 3001 | for (last_glyph = g++; | ||
| 3002 | g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id | ||
| 3003 | && g->slice.cmp.to < s->cmp_to; | ||
| 3004 | last_glyph = g++) | ||
| 3005 | ; | ||
| 3006 | } | ||
| 3007 | else | ||
| 3008 | last_glyph = s->first_glyph + s->nchars - 1; | ||
| 2993 | 3009 | ||
| 2994 | vwidth = eabs (s->face->box_vertical_line_width); | 3010 | vwidth = eabs (s->face->box_vertical_line_width); |
| 2995 | hwidth = eabs (s->face->box_horizontal_line_width); | 3011 | hwidth = eabs (s->face->box_horizontal_line_width); |