[util/hb-view] Add --font-extents

Fixes https://github.com/harfbuzz/harfbuzz/issues/2402
This commit is contained in:
Behdad Esfahbod 2020-05-14 18:58:53 -07:00
parent b2a965df5e
commit 069c5de9f8
3 changed files with 45 additions and 9 deletions

View File

@ -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 static gboolean
parse_margin (const char *name G_GNUC_UNUSED, parse_margin (const char *name G_GNUC_UNUSED,
const char *arg, 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"}, {"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"}, {"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"}, {"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"}, {"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"},
{nullptr} {nullptr}
}; };

View File

@ -125,6 +125,8 @@ struct view_options_t : option_group_t
fore = nullptr; fore = nullptr;
back = nullptr; back = nullptr;
line_space = 0; 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; margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN;
add_options (parser); add_options (parser);
@ -141,6 +143,10 @@ struct view_options_t : option_group_t
char *fore; char *fore;
char *back; char *back;
double line_space; double line_space;
bool have_font_extents;
struct font_extents_t {
double ascent, descent, line_gap;
} font_extents;
struct margin_t { struct margin_t {
double t, r, b, l; double t, r, b, l;
} margin; } margin;

View File

@ -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; int y_sign = font_opts->font_size_y < 0 ? -1 : +1;
hb_font_t *font = font_opts->get_font(); 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); view_options_t::font_extents_t extents = view_options.font_extents;
double descent = y_sign * -scalbn ((double) extents.descender, scale_bits); if (!view_options.have_font_extents)
double font_height = y_sign * scalbn ((double) extents.ascender - extents.descender + extents.line_gap, scale_bits); {
double leading = font_height + view_options.line_space; 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. */ /* Calculate surface size. */
double w = 0, h = 0; 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; (vertical ? h : w) = 0;
for (unsigned int i = 0; i < lines->len; i++) { for (unsigned int i = 0; i < lines->len; i++) {
helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, 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); cairo_translate (cr, view_options.margin.l, view_options.margin.t);
if (vertical) if (vertical)
cairo_translate (cr, cairo_translate (cr,
w /* We stack lines right to left */ w - ascent, /* We currently always stack lines right to left */
-font_height * .5 /* "ascent" for vertical */,
y_sign < 0 ? h : 0); y_sign < 0 ? h : 0);
else else
{ {