aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2020-04-23 18:40:42 +0300
committerEli Zaretskii2020-04-23 18:40:42 +0300
commit5ab80286f6f765ba41004030ea8cc19be7c1c098 (patch)
treee4923b8c1c20da115eb5a4423b36e6034b6ce0b7 /src
parent7b15cc3ebb45e50ac5faf3bbc2a813afffdaa418 (diff)
downloademacs-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/.gdbinit6
-rw-r--r--src/dispextern.h2
-rw-r--r--src/nsterm.m17
-rw-r--r--src/w32term.c51
-rw-r--r--src/xdisp.c18
-rw-r--r--src/xterm.c24
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"
558end 558end
559document pgx 559document 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,
1101static void 1101static void
1102w32_compute_glyph_string_overhangs (struct glyph_string *s) 1102w32_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);