diff options
author | Phil Jones <philj56@gmail.com> | 2021-11-03 01:22:20 +0000 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2021-11-03 01:22:20 +0000 |
commit | fb0e358feccc45c7cd642e346d07f4f7f21b484b (patch) | |
tree | ecac26391504b5b9e1e24978877fc446cd6e7c27 /src | |
parent | c7eaec357376533a77195d355cc4711d46177121 (diff) |
Don't use Pango by default.
Initialising Pango makes up a large portion of the startup time, and we
can achieve neater rendering with pure Cairo if we're just drawing
circles anyway. Therefore, this commit avoids loading Pango if no
options which require it are specified (such as --font-name or
--password-character). This reduces startup time with no background
image to ~40ms on my machine (2015 MacBook Pro).
Diffstat (limited to 'src')
-rw-r--r-- | src/entry.c | 118 | ||||
-rw-r--r-- | src/entry.h | 6 | ||||
-rw-r--r-- | src/main.c | 3 |
3 files changed, 86 insertions, 41 deletions
diff --git a/src/entry.c b/src/entry.c index fe2953c..95ab308 100644 --- a/src/entry.c +++ b/src/entry.c @@ -9,12 +9,34 @@ #include "log.h" #include "nelem.h" +#ifndef TWO_PI +#define TWO_PI 6.283185307179586f +#endif + static void calculate_font_extents(struct entry *entry, uint32_t scale); +static void draw_circles(struct entry *entry); void entry_init(struct entry *entry, uint32_t scale) { + entry->dot_radius = entry->font_size >> 3; + /* Calculate the size of the entry from our font and various widths. */ calculate_font_extents(entry, scale); - struct color color; + + entry->surface.width = entry->text_bounds.width; + entry->surface.height = entry->text_bounds.height; + entry->surface.width += 2 * ( + entry->border.width + + 2 * entry->border.outline_width + + entry->padding + ); + entry->surface.height += 2 * ( + entry->border.width + + 2 * entry->border.outline_width + + entry->padding + ); + entry->surface.width *= scale; + entry->surface.height *= scale; + /* * Cairo uses native 32 bit integers for pixels, so if this processor @@ -40,7 +62,7 @@ void entry_init(struct entry *entry, uint32_t scale) int32_t height = entry->surface.height / scale; /* Draw the outer outline */ - color = entry->border.outline_color; + struct color color = entry->border.outline_color; cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); cairo_paint(cr); @@ -100,22 +122,25 @@ void entry_init(struct entry *entry, uint32_t scale) cairo_translate(cr, -entry->text_bounds.x, -entry->text_bounds.y); /* Setup Pango. */ - PangoContext *context = pango_cairo_create_context(cr); - PangoLayout *layout = pango_layout_new(context); - pango_layout_set_text(layout, "", -1); + if (entry->use_pango) { + PangoContext *context = pango_cairo_create_context(cr); + PangoLayout *layout = pango_layout_new(context); + pango_layout_set_text(layout, "", -1); - PangoFontDescription *font_description = - pango_font_description_from_string(entry->font_name); - pango_font_description_set_size( - font_description, - entry->font_size * PANGO_SCALE); - pango_layout_set_font_description(layout, font_description); - pango_font_description_free(font_description); + PangoFontDescription *font_description = + pango_font_description_from_string(entry->font_name); + pango_font_description_set_size( + font_description, + entry->font_size * PANGO_SCALE); + pango_layout_set_font_description(layout, font_description); + pango_font_description_free(font_description); + + entry->pango.context = context; + entry->pango.layout = layout; + } + entry->cairo.surface = surface; + entry->cairo.cr = cr; - entry->pangocairo.surface = surface; - entry->pangocairo.cr = cr; - entry->pangocairo.context = context; - entry->pangocairo.layout = layout; entry->image.width = entry->surface.width; entry->image.height = entry->surface.height; entry->image.buffer = cairo_image_surface_get_data(surface); @@ -123,25 +148,34 @@ void entry_init(struct entry *entry, uint32_t scale) void entry_destroy(struct entry *entry) { - g_object_unref(entry->pangocairo.layout); - g_object_unref(entry->pangocairo.context); - cairo_destroy(entry->pangocairo.cr); - cairo_surface_destroy(entry->pangocairo.surface); + if (entry->use_pango) { + g_object_unref(entry->pango.layout); + g_object_unref(entry->pango.context); + } + cairo_destroy(entry->cairo.cr); + cairo_surface_destroy(entry->cairo.surface); } void entry_update(struct entry *entry) { - cairo_t *cr = entry->pangocairo.cr; - PangoLayout *layout = entry->pangocairo.layout; + cairo_t *cr = entry->cairo.cr; + PangoLayout *layout = entry->pango.layout; + + entry->image.redraw = true; /* Redraw the background. */ struct color color = entry->background_color; cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); cairo_paint(cr); - /* Draw our text with Pango. */ + /* Draw our text. */ color = entry->foreground_color; cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); + + if (!entry->use_pango) { + draw_circles(entry); + return; + } size_t len = 0; for (unsigned int i = 0; i < entry->password_length; i++) { len += wcrtomb(entry->password_mb_print + len, entry->password_character, NULL); @@ -150,17 +184,21 @@ void entry_update(struct entry *entry) pango_layout_set_text(layout, entry->password_mb_print, -1); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); - - entry->image.redraw = true; } void entry_set_scale(struct entry *entry, uint32_t scale) { - cairo_surface_set_device_scale(entry->pangocairo.surface, scale, scale); + cairo_surface_set_device_scale(entry->cairo.surface, scale, scale); } void calculate_font_extents(struct entry *entry, uint32_t scale) { + if (!entry->use_pango) { + /* If we're not using pango, just do a simple calculation. */ + entry->text_bounds.height = 2 * entry->dot_radius; + entry->text_bounds.width = 3 * entry->num_characters * entry->dot_radius; + return; + } /* * To calculate the size of the password box, we do the following: * 1. Load the font we're going to use. @@ -219,22 +257,22 @@ void calculate_font_extents(struct entry *entry, uint32_t scale) rect.x -= 1; rect.y -= 1; - int width = rect.width; - int height = rect.height; - width += 2 * ( - entry->border.width - + 2 * entry->border.outline_width - + entry->padding - ); - height += 2 * ( - entry->border.width - + 2 * entry->border.outline_width - + entry->padding - ); - entry->surface.width = width * scale; - entry->surface.height = height * scale; entry->text_bounds = rect; g_object_unref(layout); g_object_unref(context); } + +void draw_circles(struct entry *entry) +{ + cairo_t *cr = entry->cairo.cr; + uint32_t radius = entry->dot_radius; + cairo_save(cr); + cairo_translate(cr, radius, radius); + for (uint32_t i = 0; i < entry->password_length && i < entry->num_characters; i++) { + /* Draw circles with a one-radius gap between them. */ + cairo_arc(cr, 3 * i * radius, 0, radius, 0, TWO_PI); + } + cairo_fill(cr); + cairo_restore(cr); +} diff --git a/src/entry.h b/src/entry.h index 05c459b..b0e9542 100644 --- a/src/entry.h +++ b/src/entry.h @@ -15,9 +15,11 @@ struct entry { struct { PangoContext *context; PangoLayout *layout; + } pango; + struct { cairo_surface_t *surface; cairo_t *cr; - } pangocairo; + } cairo; PangoRectangle text_bounds; wchar_t password[MAX_PASSWORD_LENGTH]; @@ -28,6 +30,8 @@ struct entry { bool password_visible; /* Options */ + bool use_pango; + uint32_t dot_radius; uint32_t font_size; const char *font_name; uint32_t padding; @@ -701,6 +701,7 @@ int main(int argc, char *argv[]) break; case 'f': state.window.entry.font_name = optarg; + state.window.entry.use_pango = true; break; case 'F': state.window.entry.font_size = @@ -712,6 +713,7 @@ int main(int argc, char *argv[]) optarg, 4, NULL); + state.window.entry.use_pango = true; break; case 'c': state.command = optarg; @@ -725,6 +727,7 @@ int main(int argc, char *argv[]) break; case 'w': state.window.entry.tight_layout = false; + state.window.entry.use_pango = true; break; case 'H': state.hide_cursor = true; |