From 8c2da0fa6ca49777fdcc7266cbdfe7d0e0a024d0 Mon Sep 17 00:00:00 2001 From: Steven Tamm Date: Mon, 24 Jan 2005 17:59:36 +0000 Subject: [PATCH] * dispextern.h (struct glyph_string): New members clip_head and clip_tail. * xdisp.c (get_glyph_string_clip_rect): Restrict horizontal clip region to the area between clip_head and clip_tail. (draw_glyphs): Record the area that need to be actually redrawn to the new variables clip_head and clip_tail when there are overhangs. Set values of these variables to the corresponding members in struct glyph_string. Refine x coordinates for * macgui.h (STORE_XCHARSETSTRUCT): New macro. * macterm.c (mac_compute_glyph_string_overhangs): Implement with QDTextBounds. (x_draw_glyph_string): Don't fill the background of the successor of a glyph with a right overhang if the successor will draw a cursor. (XLoadQueryFont): Obtain font metrics using QDTextBounds. (x_redisplay_interface): Add entry for compute_glyph_string_overhangs. --- src/dispextern.h | 5 +++ src/macgui.h | 7 ++++ src/macterm.c | 105 ++++++++++++++++++++++++++++++++--------------- src/xdisp.c | 34 ++++++++++++++- 4 files changed, 117 insertions(+), 34 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index 53ae50f3c2a..89a8fe39aeb 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1193,6 +1193,11 @@ struct glyph_string /* Slice */ struct glyph_slice slice; + /* Non-null means the horizontal clipping region starts from the + left edge of *clip_head, and ends with the right edge of + *clip_tail, not including their overhangs. */ + struct glyph_string *clip_head, *clip_tail; + struct glyph_string *next, *prev; }; diff --git a/src/macgui.h b/src/macgui.h index 1e1447dfaa8..cb157bb8c25 100644 --- a/src/macgui.h +++ b/src/macgui.h @@ -92,6 +92,13 @@ typedef struct _XCharStruct int descent; } XCharStruct; +#define STORE_XCHARSTRUCT(xcs, w, bds) \ + ((xcs).width = (w), \ + (xcs).lbearing = (bds).left, \ + (xcs).rbearing = (bds).right, \ + (xcs).ascent = -(bds).top, \ + (xcs).descent = (bds).bottom) + struct MacFontStruct { char *fontname; diff --git a/src/macterm.c b/src/macterm.c index 24aaa52947b..60eee6a4a84 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -1991,20 +1991,33 @@ static void mac_compute_glyph_string_overhangs (s) struct glyph_string *s; { -#if 0 - /* MAC_TODO: XTextExtents16 does nothing yet... */ + Rect r; + MacFontStruct *font = s->font; + + TextFont (font->mac_fontnum); + TextSize (font->mac_fontsize); + TextFace (font->mac_fontface); - if (s->cmp == NULL - && s->first_glyph->type == CHAR_GLYPH) + if (s->two_byte_p) + QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); + else { - XCharStruct cs; - int direction, font_ascent, font_descent; - XTextExtents16 (s->font, s->char2b, s->nchars, &direction, - &font_ascent, &font_descent, &cs); - s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; - s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; + int i; + char *buf = xmalloc (s->nchars); + + if (buf == NULL) + SetRect (&r, 0, 0, 0, 0); + else + { + for (i = 0; i < s->nchars; ++i) + buf[i] = s->char2b[i].byte2; + QDTextBounds (s->nchars, buf, &r); + xfree (buf); + } } -#endif + + s->right_overhang = r.right > s->width ? r.right - s->width : 0; + s->left_overhang = r.left < 0 ? -r.left : 0; } @@ -3072,10 +3085,12 @@ x_draw_glyph_string (s) { int 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_p) + /* If S draws into the background of its successor that does not + draw a cursor, 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_p + && s->next->hl != DRAW_CURSOR) { xassert (s->next->img == NULL); x_set_glyph_string_gc (s->next); @@ -6756,30 +6771,40 @@ XLoadQueryFont (Display *dpy, char *fontname) returns 15 for 12-point Monaco! */ char_width = CharWidth ('m'); - font->max_bounds.rbearing = char_width; - font->max_bounds.lbearing = 0; - font->max_bounds.width = char_width; - font->max_bounds.ascent = the_fontinfo.ascent; - font->max_bounds.descent = the_fontinfo.descent; + if (is_two_byte_font) + { + font->per_char = NULL; - font->min_bounds = font->max_bounds; + if (fontface & italic) + font->max_bounds.rbearing = char_width + 1; + else + font->max_bounds.rbearing = char_width; + font->max_bounds.lbearing = 0; + font->max_bounds.width = char_width; + font->max_bounds.ascent = the_fontinfo.ascent; + font->max_bounds.descent = the_fontinfo.descent; - if (is_two_byte_font || CharWidth ('m') == CharWidth ('i')) - font->per_char = NULL; + font->min_bounds = font->max_bounds; + } else { font->per_char = (XCharStruct *) xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); { - int c, min_width, max_width; + int c, min_width, max_width; + Rect char_bounds, min_bounds, max_bounds; + char ch; min_width = max_width = char_width; + SetRect (&min_bounds, -32767, -32767, 32767, 32767); + SetRect (&max_bounds, 0, 0, 0, 0); for (c = 0x20; c <= 0xff; c++) { - font->per_char[c - 0x20] = font->max_bounds; - char_width = CharWidth (c); - font->per_char[c - 0x20].width = char_width; - font->per_char[c - 0x20].rbearing = char_width; + ch = c; + char_width = CharWidth (ch); + QDTextBounds (1, &ch, &char_bounds); + STORE_XCHARSTRUCT (font->per_char[c - 0x20], + char_width, char_bounds); /* Some Japanese fonts (in SJIS encoding) return 0 as the character width of 0x7f. */ if (char_width > 0) @@ -6787,9 +6812,25 @@ XLoadQueryFont (Display *dpy, char *fontname) min_width = min (min_width, char_width); max_width = max (max_width, char_width); } - } - font->min_bounds.width = min_width; - font->max_bounds.width = max_width; + if (!EmptyRect (&char_bounds)) + { + SetRect (&min_bounds, + max (min_bounds.left, char_bounds.left), + max (min_bounds.top, char_bounds.top), + min (min_bounds.right, char_bounds.right), + min (min_bounds.bottom, char_bounds.bottom)); + UnionRect (&max_bounds, &char_bounds, &max_bounds); + } + } + STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); + STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); + if (min_width == max_width + && max_bounds.left >= 0 && max_bounds.right <= max_width) + { + /* Fixed width and no overhangs. */ + xfree (font->per_char); + font->per_char = NULL; + } } } @@ -9693,7 +9734,7 @@ static struct redisplay_interface x_redisplay_interface = 0, /* destroy_fringe_bitmap */ mac_per_char_metric, mac_encode_char, - NULL, /* mac_compute_glyph_string_overhangs */ + mac_compute_glyph_string_overhangs, x_draw_glyph_string, mac_define_frame_cursor, mac_clear_frame_area, diff --git a/src/xdisp.c b/src/xdisp.c index afcc4844ab2..5f09fcc68b6 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1786,6 +1786,24 @@ get_glyph_string_clip_rect (s, nr) r.height = s->row->visible_height; } + if (s->clip_head) + if (r.x < s->clip_head->x) + { + if (r.width >= s->clip_head->x - r.x) + r.width -= s->clip_head->x - r.x; + else + r.width = 0; + r.x = s->clip_head->x; + } + if (s->clip_tail) + if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width) + { + if (s->clip_tail->x + s->clip_tail->background_width >= r.x) + r.width = s->clip_tail->x + s->clip_tail->background_width - r.x; + else + r.width = 0; + } + /* If S draws overlapping rows, it's sufficient to use the top and bottom of the window for clipping because this glyph string intentionally draws over other lines. */ @@ -18233,6 +18251,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) { struct glyph_string *head, *tail; struct glyph_string *s; + struct glyph_string *clip_head = NULL, *clip_tail = NULL; int last_x, area_width; int x_reached; int i, j; @@ -18301,6 +18320,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) start = i; compute_overhangs_and_x (t, head->x, 1); prepend_glyph_string_lists (&head, &tail, h, t); + clip_head = head; } /* Prepend glyph strings for glyphs in front of the first glyph @@ -18313,6 +18333,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) i = left_overwriting (head); if (i >= 0) { + clip_head = head; BUILD_GLYPH_STRINGS (i, start, h, t, DRAW_NORMAL_TEXT, dummy_x, last_x); for (s = h; s; s = s->next) @@ -18332,6 +18353,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) DRAW_NORMAL_TEXT, x, last_x); compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); + clip_tail = tail; } /* Append glyph strings for glyphs following the last glyph @@ -18342,6 +18364,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) i = right_overwriting (tail); if (i >= 0) { + clip_tail = tail; BUILD_GLYPH_STRINGS (end, i, h, t, DRAW_NORMAL_TEXT, x, last_x); for (s = h; s; s = s->next) @@ -18349,6 +18372,12 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); } + if (clip_head || clip_tail) + for (s = head; s; s = s->next) + { + s->clip_head = clip_head; + s->clip_tail = clip_tail; + } } /* Draw all strings. */ @@ -18362,8 +18391,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) completely. */ && !overlaps_p) { - int x0 = head ? head->x : x; - int x1 = tail ? tail->x + tail->background_width : x; + int x0 = clip_head ? clip_head->x : (head ? head->x : x); + int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width + : (tail ? tail->x + tail->background_width : x)); int text_left = window_box_left (w, TEXT_AREA); x0 -= text_left; -- 2.39.2