diff --git a/util/hb-ot-shape-closure.cc b/util/hb-ot-shape-closure.cc index 03de7e668..859f9a606 100644 --- a/util/hb-ot-shape-closure.cc +++ b/util/hb-ot-shape-closure.cc @@ -110,6 +110,6 @@ struct shape_closure_consumer_t : option_group_t int main (int argc, char **argv) { - main_font_text_t driver; + main_font_text_t driver; return driver.main (argc, argv); } diff --git a/util/hb-shape.cc b/util/hb-shape.cc index 01081ead9..f38f38791 100644 --- a/util/hb-shape.cc +++ b/util/hb-shape.cc @@ -126,6 +126,6 @@ struct output_buffer_t int main (int argc, char **argv) { - main_font_text_t > driver; + main_font_text_t, FONT_SIZE_UPEM, 0> driver; return driver.main (argc, argv); } diff --git a/util/hb-view.cc b/util/hb-view.cc index 26fad6641..ef75e6da7 100644 --- a/util/hb-view.cc +++ b/util/hb-view.cc @@ -29,9 +29,12 @@ #include "shape-consumer.hh" #include "view-cairo.hh" +#define DEFAULT_FONT_SIZE 256 +#define SUBPIXEL_BITS 8 + int main (int argc, char **argv) { - main_font_text_t > driver; + main_font_text_t, DEFAULT_FONT_SIZE, SUBPIXEL_BITS> driver; return driver.main (argc, argv); } diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc index ee940aeb0..d576c3fba 100644 --- a/util/helper-cairo.cc +++ b/util/helper-cairo.cc @@ -70,8 +70,7 @@ void free_ft_library (void) } cairo_scaled_font_t * -helper_cairo_create_scaled_font (const font_options_t *font_opts, - double font_size) +helper_cairo_create_scaled_font (const font_options_t *font_opts) { hb_font_t *font = hb_font_reference (font_opts->get_font ()); @@ -105,7 +104,8 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts, cairo_matrix_init_identity (&ctm); cairo_matrix_init_scale (&font_matrix, - font_size, font_size); + font_opts->font_size_x, + font_opts->font_size_y); font_options = cairo_font_options_create (); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); @@ -423,7 +423,7 @@ helper_cairo_line_from_buffer (helper_cairo_line_t *l, hb_buffer_t *buffer, const char *text, unsigned int text_len, - double scale, + int scale_bits, hb_bool_t utf8_clusters) { memset (l, 0, sizeof (*l)); @@ -456,16 +456,16 @@ helper_cairo_line_from_buffer (helper_cairo_line_t *l, for (i = 0; i < (int) l->num_glyphs; i++) { l->glyphs[i].index = hb_glyph[i].codepoint; - l->glyphs[i].x = ( hb_position->x_offset + x) * scale; - l->glyphs[i].y = (-hb_position->y_offset + y) * scale; + l->glyphs[i].x = scalbn ( hb_position->x_offset + x, scale_bits); + l->glyphs[i].y = scalbn (-hb_position->y_offset + y, scale_bits); x += hb_position->x_advance; y += -hb_position->y_advance; hb_position++; } l->glyphs[i].index = -1; - l->glyphs[i].x = x * scale; - l->glyphs[i].y = y * scale; + l->glyphs[i].x = scalbn (x, scale_bits); + l->glyphs[i].y = scalbn (y, scale_bits); if (l->num_clusters) { memset ((void *) l->clusters, 0, l->num_clusters * sizeof (l->clusters[0])); diff --git a/util/helper-cairo.hh b/util/helper-cairo.hh index 567777e11..ed55a452d 100644 --- a/util/helper-cairo.hh +++ b/util/helper-cairo.hh @@ -33,8 +33,7 @@ cairo_scaled_font_t * -helper_cairo_create_scaled_font (const font_options_t *font_opts, - double font_size); +helper_cairo_create_scaled_font (const font_options_t *font_opts); extern const char *helper_cairo_supported_formats[]; @@ -76,7 +75,7 @@ helper_cairo_line_from_buffer (helper_cairo_line_t *l, hb_buffer_t *buffer, const char *text, unsigned int text_len, - double scale, + int scale_bits, hb_bool_t utf8_clusters); #endif diff --git a/util/main-font-text.hh b/util/main-font-text.hh index ac51b2db0..628cdf967 100644 --- a/util/main-font-text.hh +++ b/util/main-font-text.hh @@ -31,12 +31,12 @@ /* main() body for utilities taking font and processing text.*/ -template +template struct main_font_text_t { main_font_text_t (void) : options ("[FONT-FILE] [TEXT]"), - font_opts (&options), + font_opts (&options, default_font_size, subpixel_bits), input (&options), consumer (&options) {} diff --git a/util/options.cc b/util/options.cc index 44b11c8d8..7387a5616 100644 --- a/util/options.cc +++ b/util/options.cc @@ -265,7 +265,6 @@ view_options_t::add_options (option_parser_t *parser) {"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"}, {"margin", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_margin, "Margin around output (default: " G_STRINGIFY(DEFAULT_MARGIN) ")","one to four numbers"}, - {"font-size", 0, 0, G_OPTION_ARG_DOUBLE, &this->font_size, "Font size (default: " G_STRINGIFY(DEFAULT_FONT_SIZE) ")","size"}, {NULL} }; parser->add_group (entries, @@ -350,6 +349,28 @@ shape_options_t::add_options (option_parser_t *parser) this); } +static gboolean +parse_font_size (const char *name G_GNUC_UNUSED, + const char *arg, + gpointer data, + GError **error G_GNUC_UNUSED) +{ + font_options_t *font_opts = (font_options_t *) data; + if (0 == strcmp (arg, "upem")) + { + font_opts->font_size_y = font_opts->font_size_x = FONT_SIZE_UPEM; + return true; + } + switch (sscanf (arg, "%lf %lf", &font_opts->font_size_x, &font_opts->font_size_y)) { + case 1: font_opts->font_size_y = font_opts->font_size_x; + case 2: return true; + default: + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "%s argument should be one to four space-separated numbers", + name); + return false; + } +} void font_options_t::add_options (option_parser_t *parser) { @@ -370,10 +391,21 @@ font_options_t::add_options (option_parser_t *parser) parser->free_later (text); } + char *font_size_text; + if (default_font_size == FONT_SIZE_UPEM) + font_size_text = (char *) "Font size (default: upem)"; + else + { + font_size_text = g_strdup_printf ("Font size (default: %d)", default_font_size); + parser->free_later (font_size_text); + } + GOptionEntry entries[] = { {"font-file", 0, 0, G_OPTION_ARG_STRING, &this->font_file, "Set font file-name", "filename"}, {"face-index", 0, 0, G_OPTION_ARG_INT, &this->face_index, "Set face index (default: 0)", "index"}, + {"font-size", 0, default_font_size ? 0 : G_OPTION_FLAG_HIDDEN, + G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_size, font_size_text, "1/2 numbers or 'upem'"}, {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, {NULL} }; @@ -515,8 +547,14 @@ font_options_t::get_font (void) const font = hb_font_create (face); - unsigned int upem = hb_face_get_upem (face); - hb_font_set_scale (font, upem, upem); + if (font_size_x == FONT_SIZE_UPEM) + font_size_x = hb_face_get_upem (face); + if (font_size_y == FONT_SIZE_UPEM) + font_size_y = hb_face_get_upem (face); + + int scale_x = (int) scalbnf (font_size_x, subpixel_bits); + int scale_y = (int) scalbnf (font_size_y, subpixel_bits); + hb_font_set_scale (font, scale_x, scale_y); hb_face_destroy (face); void (*set_font_funcs) (hb_font_t *) = NULL; diff --git a/util/options.hh b/util/options.hh index 223778d61..8b9b10ef0 100644 --- a/util/options.hh +++ b/util/options.hh @@ -143,7 +143,8 @@ struct option_parser_t #define DEFAULT_MARGIN 16 #define DEFAULT_FORE "#000000" #define DEFAULT_BACK "#FFFFFF" -#define DEFAULT_FONT_SIZE 256 +#define FONT_SIZE_UPEM 0x7FFFFFFF +#define FONT_SIZE_NONE 0 struct view_options_t : option_group_t { @@ -153,7 +154,6 @@ struct view_options_t : option_group_t back = DEFAULT_BACK; line_space = 0; margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN; - font_size = DEFAULT_FONT_SIZE; add_options (parser); } @@ -167,7 +167,6 @@ struct view_options_t : option_group_t struct margin_t { double t, r, b, l; } margin; - double font_size; }; @@ -273,9 +272,14 @@ struct shape_options_t : option_group_t struct font_options_t : option_group_t { - font_options_t (option_parser_t *parser) { + font_options_t (option_parser_t *parser, + int default_font_size_, + unsigned int subpixel_bits_) { + default_font_size = default_font_size_; + subpixel_bits = subpixel_bits_; font_file = NULL; face_index = 0; + font_size_x = font_size_y = default_font_size; font_funcs = NULL; font = NULL; @@ -292,6 +296,10 @@ struct font_options_t : option_group_t const char *font_file; int face_index; + int default_font_size; + unsigned int subpixel_bits; + mutable double font_size_x; + mutable double font_size_y; const char *font_funcs; private: diff --git a/util/view-cairo.cc b/util/view-cairo.cc index 666013ec1..160250e2d 100644 --- a/util/view-cairo.cc +++ b/util/view-cairo.cc @@ -54,7 +54,7 @@ view_cairo_t::get_surface_size (cairo_scaled_font_t *scaled_font, void view_cairo_t::render (const font_options_t *font_opts) { - cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts, view_options.font_size); + cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts); double w, h; get_surface_size (scaled_font, &w, &h); cairo_t *cr = helper_cairo_create_context (w, h, &view_options, &output_options); diff --git a/util/view-cairo.hh b/util/view-cairo.hh index 9dea06e96..cb523737a 100644 --- a/util/view-cairo.hh +++ b/util/view-cairo.hh @@ -37,7 +37,7 @@ struct view_cairo_t : output_options (parser, helper_cairo_supported_formats), view_options (parser), direction (HB_DIRECTION_INVALID), - lines (0), scale (1.0) {} + lines (0), scale_bits (0) {} ~view_cairo_t (void) { if (debug) cairo_debug_reset_static_data (); @@ -46,7 +46,7 @@ struct view_cairo_t void init (const font_options_t *font_opts) { lines = g_array_new (false, false, sizeof (helper_cairo_line_t)); - scale = double (view_options.font_size) / hb_face_get_upem (hb_font_get_face (font_opts->get_font ())); + scale_bits = -font_opts->subpixel_bits; } void new_line (void) { @@ -71,7 +71,7 @@ struct view_cairo_t { direction = hb_buffer_get_direction (buffer); helper_cairo_line_t l; - helper_cairo_line_from_buffer (&l, buffer, text, text_len, scale, utf8_clusters); + helper_cairo_line_from_buffer (&l, buffer, text, text_len, scale_bits, utf8_clusters); g_array_append_val (lines, l); } void finish (const font_options_t *font_opts) @@ -100,7 +100,7 @@ struct view_cairo_t hb_direction_t direction; // Remove this, make segment_properties accessible GArray *lines; - double scale; + int scale_bits; }; #endif