summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/composite.c6
-rw-r--r--src/dispextern.h8
-rw-r--r--src/font.c7
-rw-r--r--src/nsterm.m9
-rw-r--r--src/w32font.c25
-rw-r--r--src/w32term.c12
-rw-r--r--src/xdisp.c210
-rw-r--r--src/xftfont.c22
-rw-r--r--src/xterm.c10
9 files changed, 274 insertions, 35 deletions
diff --git a/src/composite.c b/src/composite.c
index 1c9c62bf910..1c18165599d 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -732,9 +732,11 @@ composition_gstring_width (Lisp_Object gstring, ptrdiff_t from, ptrdiff_t to,
if (FONT_OBJECT_P (font_object))
{
struct font *font = XFONT_OBJECT (font_object);
+ int font_ascent, font_descent;
- metrics->ascent = font->ascent;
- metrics->descent = font->descent;
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ metrics->ascent = font_ascent;
+ metrics->descent = font_descent;
}
else
{
diff --git a/src/dispextern.h b/src/dispextern.h
index d9d4d2300fa..5202142313a 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1526,6 +1526,12 @@ struct glyph_string
+ (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
- (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
+/* A heuristic test for fonts that claim they need a preposterously
+ large vertical space. The heuristics is in the factor of 3. We
+ ignore the ascent and descent values reported by such fonts, and
+ instead go by the values reported for individual glyphs. */
+#define FONT_TOO_HIGH(ft) ((ft)->ascent + (ft)->descent > 3*(ft)->pixel_size)
+
/***********************************************************************
Faces
@@ -3240,6 +3246,8 @@ extern ptrdiff_t compute_display_string_end (ptrdiff_t,
extern void produce_stretch_glyph (struct it *);
extern int merge_glyphless_glyph_face (struct it *);
+extern void get_font_ascent_descent (struct font *, int *, int *);
+
#ifdef HAVE_WINDOW_SYSTEM
#ifdef GLYPH_DEBUG
diff --git a/src/font.c b/src/font.c
index 1405d437241..556f32bb432 100644
--- a/src/font.c
+++ b/src/font.c
@@ -2908,7 +2908,12 @@ font_open_entity (struct frame *f, Lisp_Object entity, int pixel_size)
: font->average_width ? font->average_width
: font->space_width ? font->space_width
: 1);
- height = (font->height ? font->height : 1);
+
+ int font_ascent, font_descent;
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ height = font_ascent + font_descent;
+ if (height <= 0)
+ height = 1;
#ifdef HAVE_WINDOW_SYSTEM
FRAME_DISPLAY_INFO (f)->n_fonts++;
if (FRAME_DISPLAY_INFO (f)->n_fonts == 1)
diff --git a/src/nsterm.m b/src/nsterm.m
index 67a03898d13..2806f31155d 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2928,6 +2928,11 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
{
int box_line_width = max (s->face->box_line_width, 0);
if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
+ dimensions, since the actual glyphs might be much
+ smaller. So in that case we always clear the rectangle
+ with background color. */
+ || FONT_TOO_HIGH (s->font)
|| s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
{
struct face *face;
@@ -7687,6 +7692,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
EmacsView *view = FRAME_NS_VIEW (f);
+ int font_ascent, font_descent;
if (fontset < 0)
fontset = fontset_from_font (font_object);
@@ -7701,7 +7707,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_LINE_HEIGHT (f) = font->height;
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
/* Compute the scroll bar width in character columns. */
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
diff --git a/src/w32font.c b/src/w32font.c
index 6306a8460e7..1c2f9665037 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -650,12 +650,31 @@ w32font_draw (struct glyph_string *s, int from, int to,
HBRUSH brush;
RECT rect;
struct font *font = s->font;
-
+ int ascent = font->ascent, descent = font->descent;
+
+ /* Font's global ascent and descent values might be
+ preposterously large for some fonts. We fix here the case
+ when those fonts are used for display of glyphless
+ characters, because drawing background with font dimensions
+ in those cases makes the display illegible. There's only one
+ more call to the draw method with with_background set to
+ true, and that's in x_draw_glyph_string_foreground, when
+ drawing the cursor, where we have no such heuristics
+ available. FIXME. */
+ if (s->first_glyph->type == GLYPHLESS_GLYPH
+ && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
+ || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
+ {
+ ascent =
+ s->first_glyph->slice.glyphless.lower_yoff
+ - s->first_glyph->slice.glyphless.upper_yoff;
+ descent = 0;
+ }
brush = CreateSolidBrush (s->gc->background);
rect.left = x;
- rect.top = y - font->ascent;
+ rect.top = y - ascent;
rect.right = x + s->width;
- rect.bottom = y + font->descent;
+ rect.bottom = y + descent;
FillRect (s->hdc, &rect, brush);
DeleteObject (brush);
}
diff --git a/src/w32term.c b/src/w32term.c
index 0bc2e980214..b7c6e13c8a8 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1218,7 +1218,12 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
}
else
#endif
- if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
+ font dimensions, since the actual glyphs might be
+ much smaller. So in that case we always clear the
+ rectangle with background color. */
+ || FONT_TOO_HIGH (s->font)
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| force_p)
@@ -5827,7 +5832,7 @@ Lisp_Object
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
- int unit;
+ int unit, font_ascent, font_descent;
if (fontset < 0)
fontset = fontset_from_font (font_object);
@@ -5840,7 +5845,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
- FRAME_LINE_HEIGHT (f) = font->height;
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
/* Compute number of scrollbar columns. */
unit = FRAME_COLUMN_WIDTH (f);
diff --git a/src/xdisp.c b/src/xdisp.c
index 05862d276ef..14385fa8421 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -833,6 +833,9 @@ static void x_draw_bottom_divider (struct window *w);
static void notice_overwritten_cursor (struct window *,
enum glyph_row_area,
int, int, int, int);
+static int normal_char_height (struct font *, int);
+static void normal_char_ascent_descent (struct font *, int, int *, int *);
+
static void append_stretch_glyph (struct it *, Lisp_Object,
int, int, int);
@@ -1761,7 +1764,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
if (face)
{
if (face->font)
- height = FONT_HEIGHT (face->font);
+ height = normal_char_height (face->font, -1);
if (face->box_line_width > 0)
height += 2 * face->box_line_width;
}
@@ -2150,7 +2153,7 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
struct glyph *glyph, int *xp, int *yp, int *heightp)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
- int x, y, wd, h, h0, y0;
+ int x, y, wd, h, h0, y0, ascent;
/* Compute the width of the rectangle to draw. If on a stretch
glyph, and `x-stretch-block-cursor' is nil, don't draw a
@@ -2170,13 +2173,21 @@ get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
wd = min (FRAME_COLUMN_WIDTH (f), wd);
w->phys_cursor_width = wd;
- y = w->phys_cursor.y + row->ascent - glyph->ascent;
+ /* Don't let the hollow cursor glyph descend below the glyph row's
+ ascent value, lest the hollow cursor looks funny. */
+ y = w->phys_cursor.y;
+ ascent = row->ascent;
+ if (row->ascent < glyph->ascent)
+ {
+ y =- glyph->ascent - row->ascent;
+ ascent = glyph->ascent;
+ }
/* If y is below window bottom, ensure that we still see a cursor. */
h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
- h = max (h0, glyph->ascent + glyph->descent);
- h0 = min (h0, glyph->ascent + glyph->descent);
+ h = max (h0, ascent + glyph->descent);
+ h0 = min (h0, ascent + glyph->descent);
y0 = WINDOW_HEADER_LINE_HEIGHT (w);
if (y < y0)
@@ -4880,7 +4891,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
{
struct face *face = FACE_FROM_ID (it->f, it->face_id);
it->voffset = - (XFLOATINT (value)
- * (FONT_HEIGHT (face->font)));
+ * (normal_char_height (face->font, -1)));
}
#endif /* HAVE_WINDOW_SYSTEM */
}
@@ -19157,6 +19168,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
+ struct glyph *g;
saved_object = it->object;
saved_pos = it->position;
@@ -19188,6 +19200,23 @@ append_space_for_newline (struct it *it, bool default_face_p)
PRODUCE_GLYPHS (it);
+ /* Make sure this space glyph has the right ascent and
+ descent values, or else cursor at end of line will look
+ funny. */
+ g = it->glyph_row->glyphs[TEXT_AREA] + n;
+ struct font *font = face->font ? face->font : FRAME_FONT (it->f);
+ if (n == 0 || it->glyph_row->height < font->pixel_size)
+ {
+ normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
+ it->max_ascent = it->ascent;
+ it->max_descent = it->descent;
+ /* Make sure compute_line_metrics recomputes the row height. */
+ it->glyph_row->height = 0;
+ }
+
+ g->ascent = it->max_ascent;
+ g->descent = it->max_descent;
+
it->override_ascent = -1;
it->constrain_row_ascent_descent_p = false;
it->current_x = saved_x;
@@ -23900,9 +23929,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
#ifdef HAVE_WINDOW_SYSTEM
if (EQ (prop, Qheight))
- return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
+ return OK_PIXELS (font
+ ? normal_char_height (font, -1)
+ : FRAME_LINE_HEIGHT (it->f));
if (EQ (prop, Qwidth))
- return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
+ return OK_PIXELS (font
+ ? FONT_WIDTH (font)
+ : FRAME_COLUMN_WIDTH (it->f));
#else
if (EQ (prop, Qheight) || EQ (prop, Qwidth))
return OK_PIXELS (1);
@@ -24032,6 +24065,17 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
return false;
}
+void
+get_font_ascent_descent (struct font *font, int *ascent, int *descent)
+{
+#ifdef HAVE_WINDOW_SYSTEM
+ normal_char_ascent_descent (font, -1, ascent, descent);
+#else
+ *ascent = 1;
+ *descent = 0;
+#endif
+}
+
/***********************************************************************
Glyph Display
@@ -24536,6 +24580,55 @@ get_per_char_metric (struct font *font, XChar2b *char2b)
return &metrics;
}
+/* A subroutine that computes "normal" values of ASCENT and DESCENT
+ for FONT. Values are taken from font-global ones, except for fonts
+ that claim preposterously large values, but whose glyphs actually
+ have reasonable dimensions. C is the character to use for metrics
+ if the font-global values are too large; if C is negative, the
+ function selects a default character. */
+static void
+normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
+{
+ *ascent = FONT_BASE (font);
+ *descent = FONT_DESCENT (font);
+
+ if (FONT_TOO_HIGH (font))
+ {
+ XChar2b char2b;
+
+ /* Get metrics of C, defaulting to a reasonably sized ASCII
+ character. */
+ if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
+ {
+ struct font_metrics *pcm = get_per_char_metric (font, &char2b);
+
+ if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
+ {
+ /* We add 1 pixel to character dimensions as heuristics
+ that produces nicer display, e.g. when the face has
+ the box attribute. */
+ *ascent = pcm->ascent + 1;
+ *descent = pcm->descent + 1;
+ }
+ }
+ }
+}
+
+/* A subroutine that computes a reasonable "normal character height"
+ for fonts that claim preposterously large vertical dimensions, but
+ whose glyphs are actually reasonably sized. C is the charcater
+ whose metrics to use for those fonts, or -1 for default
+ character. */
+static int
+normal_char_height (struct font *font, int c)
+{
+ int ascent, descent;
+
+ normal_char_ascent_descent (font, c, &ascent, &descent);
+
+ return ascent + descent;
+}
+
/* EXPORT for RIF:
Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
frame F. Overhangs of glyphs other than type CHAR_GLYPH are
@@ -25835,6 +25928,8 @@ produce_stretch_glyph (struct it *it)
/* Compute height. */
if (FRAME_WINDOW_P (it->f))
{
+ int default_height = normal_char_height (font, ' ');
+
if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
&& calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
{
@@ -25843,9 +25938,9 @@ produce_stretch_glyph (struct it *it)
}
else if (prop = Fplist_get (plist, QCrelative_height),
NUMVAL (prop) > 0)
- height = FONT_HEIGHT (font) * NUMVAL (prop);
+ height = default_height * NUMVAL (prop);
else
- height = FONT_HEIGHT (font);
+ height = default_height;
if (height <= 0 && (height < 0 || !zero_height_ok_p))
height = 1;
@@ -26069,8 +26164,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
- ascent = FONT_BASE (font) + boff;
- descent = FONT_DESCENT (font) - boff;
+ normal_char_ascent_descent (font, -1, &ascent, &descent);
if (override)
{
@@ -26196,8 +26290,9 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
ASCII face. */
face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
font = face->font ? face->font : FRAME_FONT (it->f);
- it->ascent = FONT_BASE (font) + font->baseline_offset;
- it->descent = FONT_DESCENT (font) - font->baseline_offset;
+ normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
+ it->ascent += font->baseline_offset;
+ it->descent -= font->baseline_offset;
base_height = it->ascent + it->descent;
base_width = font->average_width;
@@ -26384,6 +26479,22 @@ x_produce_glyphs (struct it *it)
it->phys_ascent = pcm->ascent + boff;
it->phys_descent = pcm->descent - boff;
it->pixel_width = pcm->width;
+ /* Don't use font-global values for ascent and descent
+ if they result in an exceedingly large line height. */
+ if (it->override_ascent < 0)
+ {
+ if (FONT_TOO_HIGH (font))
+ {
+ it->ascent = it->phys_ascent;
+ it->descent = it->phys_descent;
+ /* These limitations are enforced by an
+ assertion near the end of this function. */
+ if (it->ascent < 0)
+ it->ascent = 0;
+ if (it->descent < 0)
+ it->descent = 0;
+ }
+ }
}
else
{
@@ -26511,8 +26622,18 @@ x_produce_glyphs (struct it *it)
}
else
{
- it->ascent = FONT_BASE (font) + boff;
- it->descent = FONT_DESCENT (font) - boff;
+ if (FONT_TOO_HIGH (font))
+ {
+ it->ascent = font->pixel_size + boff - 1;
+ it->descent = -boff + 1;
+ if (it->descent < 0)
+ it->descent = 0;
+ }
+ else
+ {
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ }
}
if (EQ (height, Qt))
@@ -26583,8 +26704,38 @@ x_produce_glyphs (struct it *it)
it->pixel_width = next_tab_x - x;
it->nglyphs = 1;
- it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
- it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+ if (FONT_TOO_HIGH (font))
+ {
+ if (get_char_glyph_code (' ', font, &char2b))
+ {
+ pcm = get_per_char_metric (font, &char2b);
+ if (pcm->width == 0
+ && pcm->rbearing == 0 && pcm->lbearing == 0)
+ pcm = NULL;
+ }
+
+ if (pcm)
+ {
+ it->ascent = pcm->ascent + boff;
+ it->descent = pcm->descent - boff;
+ }
+ else
+ {
+ it->ascent = font->pixel_size + boff - 1;
+ it->descent = -boff + 1;
+ }
+ if (it->ascent < 0)
+ it->ascent = 0;
+ if (it->descent < 0)
+ it->descent = 0;
+ }
+ else
+ {
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ }
+ it->phys_ascent = it->ascent;
+ it->phys_descent = it->descent;
if (it->glyph_row)
{
@@ -26598,6 +26749,22 @@ x_produce_glyphs (struct it *it)
it->nglyphs = 1;
}
}
+
+ if (FONT_TOO_HIGH (font))
+ {
+ int font_ascent, font_descent;
+
+ /* For very large fonts, where we ignore the declared font
+ dimensions, and go by per-character metrics instead,
+ don't let the row ascent and descent values (and the row
+ height computed from them) be smaller than the "normal"
+ character metrics. This avoids unpleasant effects
+ whereby lines on display would change their heigh
+ depending on which characters are shown. */
+ normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
+ it->max_ascent = max (it->max_ascent, font_ascent);
+ it->max_descent = max (it->max_descent, font_descent);
+ }
}
else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
{
@@ -26664,9 +26831,10 @@ x_produce_glyphs (struct it *it)
boff = font->baseline_offset;
if (font->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
- font_ascent = FONT_BASE (font) + boff;
- font_descent = FONT_DESCENT (font) - boff;
- font_height = FONT_HEIGHT (font);
+ normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
+ font_ascent += boff;
+ font_descent -= boff;
+ font_height = font_ascent + font_descent;
cmp->font = font;
diff --git a/src/xftfont.c b/src/xftfont.c
index 0e8b876f1d3..a1846e8d461 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -617,8 +617,26 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y,
XftDrawSetClip (xft_draw, NULL);
if (with_background)
- XftDrawRect (xft_draw, &bg,
- x, y - s->font->ascent, s->width, s->font->height);
+ {
+ int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font);
+
+ /* Font's global height and ascent values might be
+ preposterously large for some fonts. We fix here the case
+ when those fonts are used for display of glyphless
+ characters, because drawing background with font dimensions
+ in those cases makes the display illegible. There's only one
+ more call to the draw method with with_background set to
+ true, and that's in x_draw_glyph_string_foreground, when
+ drawing the cursor, where we have no such heuristics
+ available. FIXME. */
+ if (s->first_glyph->type == GLYPHLESS_GLYPH
+ && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE
+ || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM))
+ height = ascent =
+ s->first_glyph->slice.glyphless.lower_yoff
+ - s->first_glyph->slice.glyphless.upper_yoff;
+ XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height);
+ }
code = alloca (sizeof (FT_UInt) * len);
for (i = 0; i < len; i++)
code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
diff --git a/src/xterm.c b/src/xterm.c
index 691ede58b43..4d7945059fe 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1724,6 +1724,11 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
s->background_filled_p = true;
}
else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
+ font dimensions, since the actual glyphs might be
+ much smaller. So in that case we always clear the
+ rectangle with background color. */
+ || FONT_TOO_HIGH (s->font)
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| force_p)
@@ -9405,7 +9410,7 @@ Lisp_Object
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
- int unit;
+ int unit, font_ascent, font_descent;
if (fontset < 0)
fontset = fontset_from_font (font_object);
@@ -9418,7 +9423,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
+ get_font_ascent_descent (font, &font_ascent, &font_descent);
+ FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
#ifndef USE_X_TOOLKIT
FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);