diff --git a/util/options.cc b/util/options.cc index 47a4e7104..ee09ac5d4 100644 --- a/util/options.cc +++ b/util/options.cc @@ -163,6 +163,28 @@ option_parser_t::parse (int *argc, char ***argv) } +static gboolean +parse_font_extents (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + view_options_t *view_opts = (view_options_t *) data; + view_options_t::font_extents_t &e = view_opts->font_extents; + switch (sscanf (arg, "%lf%*[ ,]%lf%*[ ,]%lf", &e.ascent, &e.descent, &e.line_gap)) { + case 1: HB_FALLTHROUGH; + case 2: HB_FALLTHROUGH; + case 3: + view_opts->have_font_extents = true; + return true; + default: + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "%s argument should be one to three space-separated numbers", + name); + return false; + } +} + static gboolean parse_margin (const char *name G_GNUC_UNUSED, const char *arg, @@ -399,6 +421,7 @@ view_options_t::add_options (option_parser_t *parser) {"background", 0, 0, G_OPTION_ARG_STRING, &this->back, "Set background color (default: " DEFAULT_BACK ")", "rrggbb/rrggbbaa"}, {"foreground", 0, 0, G_OPTION_ARG_STRING, &this->fore, "Set foreground color (default: " DEFAULT_FORE ")", "rrggbb/rrggbbaa"}, {"line-space", 0, 0, G_OPTION_ARG_DOUBLE, &this->line_space, "Set space between lines (default: 0)", "units"}, + {"font-extents", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_extents, "Set font ascent/descent/line-gap (default: auto)","one to three numbers"}, {"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"}, {nullptr} }; diff --git a/util/options.hh b/util/options.hh index 0fcc76e67..2c10578a9 100644 --- a/util/options.hh +++ b/util/options.hh @@ -125,6 +125,8 @@ struct view_options_t : option_group_t fore = nullptr; back = nullptr; line_space = 0; + have_font_extents = false; + font_extents.ascent = font_extents.descent = font_extents.line_gap = 0; margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN; add_options (parser); @@ -141,6 +143,10 @@ struct view_options_t : option_group_t char *fore; char *back; double line_space; + bool have_font_extents; + struct font_extents_t { + double ascent, descent, line_gap; + } font_extents; struct margin_t { double t, r, b, l; } margin; diff --git a/util/view-cairo.cc b/util/view-cairo.cc index e8e334beb..0db3306af 100644 --- a/util/view-cairo.cc +++ b/util/view-cairo.cc @@ -40,17 +40,25 @@ view_cairo_t::render (const font_options_t *font_opts) int y_sign = font_opts->font_size_y < 0 ? -1 : +1; hb_font_t *font = font_opts->get_font(); - hb_font_extents_t extents; - hb_font_get_extents_for_direction (font, direction, &extents); - double ascent = y_sign * scalbn ((double) extents.ascender, scale_bits); - double descent = y_sign * -scalbn ((double) extents.descender, scale_bits); - double font_height = y_sign * scalbn ((double) extents.ascender - extents.descender + extents.line_gap, scale_bits); - double leading = font_height + view_options.line_space; + view_options_t::font_extents_t extents = view_options.font_extents; + if (!view_options.have_font_extents) + { + hb_font_extents_t hb_extents; + hb_font_get_extents_for_direction (font, direction, &hb_extents); + extents.ascent = scalbn ((double) hb_extents.ascender, scale_bits); + extents.descent = -scalbn ((double) hb_extents.descender, scale_bits); + extents.line_gap = scalbn ((double) hb_extents.line_gap, scale_bits); + } + + double ascent = y_sign * extents.ascent; + double descent = y_sign * extents.descent; + double line_gap = y_sign * extents.line_gap + view_options.line_space; + double leading = ascent + descent + line_gap; /* Calculate surface size. */ double w = 0, h = 0; - (vertical ? w : h) = (int) lines->len * leading - view_options.line_space; + (vertical ? w : h) = (int) lines->len * leading - (extents.line_gap + view_options.line_space); (vertical ? h : w) = 0; for (unsigned int i = 0; i < lines->len; i++) { helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i); @@ -79,8 +87,7 @@ view_cairo_t::render (const font_options_t *font_opts) cairo_translate (cr, view_options.margin.l, view_options.margin.t); if (vertical) cairo_translate (cr, - w /* We stack lines right to left */ - -font_height * .5 /* "ascent" for vertical */, + w - ascent, /* We currently always stack lines right to left */ y_sign < 0 ? h : 0); else {