From fb0e358feccc45c7cd642e346d07f4f7f21b484b Mon Sep 17 00:00:00 2001 From: Phil Jones Date: Wed, 3 Nov 2021 01:22:20 +0000 Subject: 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). --- doc/greetd-mini-wl-greeter.1.scd | 7 ++- src/entry.c | 118 ++++++++++++++++++++++++++------------- src/entry.h | 6 +- src/main.c | 3 + 4 files changed, 92 insertions(+), 42 deletions(-) diff --git a/doc/greetd-mini-wl-greeter.1.scd b/doc/greetd-mini-wl-greeter.1.scd index 7beab36..988c2db 100644 --- a/doc/greetd-mini-wl-greeter.1.scd +++ b/doc/greetd-mini-wl-greeter.1.scd @@ -6,7 +6,7 @@ greetd-mini-wl-greeter - An extremely simple raw Wayland greeter for greetd # SYNOPSIS -*greetd-mini-wl-greeter* -u user -c command [options] +*greetd-mini-wl-greeter* -u user -c command [-bBCeEfFhHnoOrRw] # DESCRIPTION @@ -73,6 +73,11 @@ All options which take a color expect a 3- or 6-digit hex code, e.g. F9A733. # EXAMPLES +greetd-mini-wl-greeter aims to be as fast and simple as possible by default. If +none of the *-f*, *-C* or *-w* options are given, a simple circle will be used +for the password character, avoiding the need to use Pango, thus lowering +startup time. This is only likely noticeable on very slow machines however. + When using sway as the compositor for greetd-mini-greeter, something like the following sway config lines produce a nice look: 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; diff --git a/src/main.c b/src/main.c index 64e5975..4f20bd7 100644 --- a/src/main.c +++ b/src/main.c @@ -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; -- cgit v1.2.3