summaryrefslogtreecommitdiff
path: root/src/entry.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/entry.c')
-rw-r--r--src/entry.c201
1 files changed, 147 insertions, 54 deletions
diff --git a/src/entry.c b/src/entry.c
index 61b0211..e6338de 100644
--- a/src/entry.c
+++ b/src/entry.c
@@ -9,62 +9,109 @@
#include "log.h"
#include "nelem.h"
-static void calculate_font_extents(struct entry *entry);
+static void calculate_font_extents(struct entry *entry, uint32_t scale);
-void entry_init(struct entry *entry)
+void entry_init(struct entry *entry, uint32_t scale)
{
- calculate_font_extents(entry);
+ calculate_font_extents(entry, scale);
+ struct color color;
- /*
- * Cairo uses native 32 bit integers for pixels, so if this computer is
- * little endian we have to tell OpenGL to swizzle the texture.
+ /*
+ * Cairo uses native 32 bit integers for pixels, so if this processor
+ * is little endian we have to tell OpenGL to swizzle the texture.
*/
if (htonl(0xFFu) != 0xFFu) {
entry->image.swizzle = true;
}
+ /*
+ * Create the cairo surface and context we'll be using.
+ */
cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32,
entry->surface.width,
entry->surface.height
);
+ cairo_surface_set_device_scale(surface, scale, scale);
cairo_t *cr = cairo_create(surface);
- cairo_set_source_rgb(cr, 0.031, 0.031, 0);
+
+ /* Running size of current drawing area. */
+ int32_t width = entry->surface.width / scale;
+ int32_t height = entry->surface.height / scale;
+
+ /* Draw the outer outline */
+ color = entry->border.outline_color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
cairo_paint(cr);
- cairo_translate(cr, entry->border.outline_width, entry->border.outline_width);
- cairo_rectangle(cr,
- 0,
- 0,
- entry->surface.width - 2*entry->border.outline_width,
- entry->surface.height - 2*entry->border.outline_width
- );
+ /* Move and clip following draws to be within this outline */
+ cairo_translate(
+ cr,
+ entry->border.outline_width,
+ entry->border.outline_width);
+ width -= 2 * entry->border.outline_width;
+ height -= 2 * entry->border.outline_width;
+ cairo_rectangle(cr, 0, 0, width, height);
cairo_clip(cr);
- cairo_set_source_rgb(cr, 0.976, 0.149, 0.447);
+
+ /* Draw the border */
+ color = entry->border.color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
cairo_paint(cr);
+ /* Move and clip following draws to be within the border */
cairo_translate(cr, entry->border.width, entry->border.width);
- cairo_rectangle(cr,
- 0,
- 0,
- entry->surface.width - 2*(entry->border.outline_width + entry->border.width),
- entry->surface.height - 2*(entry->border.outline_width + entry->border.width)
- );
+ width -= 2 * entry->border.width;
+ height -= 2 * entry->border.width;
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_clip(cr);
+
+ /* Draw the inner outline */
+ color = entry->border.outline_color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
+ cairo_paint(cr);
+
+ /* Move and clip following draws to be within this outline */
+ cairo_translate(
+ cr,
+ entry->border.outline_width,
+ entry->border.outline_width);
+ width -= 2 * entry->border.outline_width;
+ height -= 2 * entry->border.outline_width;
+ cairo_rectangle(cr, 0, 0, width, height);
cairo_clip(cr);
- cairo_set_source_rgb(cr, 0.106, 0.114, 0.118);
+
+ /* Draw the entry background */
+ color = entry->background_color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
cairo_paint(cr);
- PangoLayout *layout = pango_cairo_create_layout(cr);
+ /* Move and clip following draws to be within the specified padding */
+ cairo_translate(cr, entry->padding, entry->padding);
+ width -= 2 * entry->padding;
+ height -= 2 * entry->padding;
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_clip(cr);
+
+ /*
+ * Move the cursor back up, so that Pango draws in the correct place if
+ * we're doing a tight layout.
+ */
+ 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);
- PangoFontDescription *font_description = pango_font_description_from_string("Rubik Bold 48");
+ 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);
- cairo_set_source_rgb(cr, 0.973, 0.973, 0.941);
- pango_cairo_update_layout(cr, layout);
- pango_cairo_show_layout(cr, layout);
-
entry->pangocairo.surface = surface;
entry->pangocairo.cr = cr;
entry->pangocairo.layout = layout;
@@ -77,49 +124,95 @@ void entry_update(struct entry *entry)
{
cairo_t *cr = entry->pangocairo.cr;
PangoLayout *layout = entry->pangocairo.layout;
- cairo_set_source_rgb(cr, 0.106, 0.114, 0.118);
+
+ /* 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);
- cairo_set_source_rgb(cr, 0.973, 0.973, 0.941);
+
+ /* Draw our text with Pango. */
+ color = entry->foreground_color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
//const wchar_t *src = entry->password;
//wcsrtombs(entry->password_mb, &src, N_ELEM(entry->password_mb), NULL);
+ size_t len = 0;
for (unsigned int i = 0; i < entry->password_length; i++) {
- entry->password_mb[2 * i] = '\xC2';
- entry->password_mb[2 * i + 1] = '\xB7';
+ len += wcrtomb(entry->password_mb + len, entry->password_character, NULL);
}
- entry->password_mb[2 * entry->password_length] = '\0';
+ entry->password_mb[len] = '\0';
fprintf(stderr, "%s\n", entry->password_mb);
pango_layout_set_text(layout, entry->password_mb, -1);
pango_cairo_update_layout(cr, layout);
pango_cairo_show_layout(cr, layout);
+
entry->image.redraw = true;
}
-void calculate_font_extents(struct entry *entry)
+void entry_set_scale(struct entry *entry, uint32_t scale)
{
+ cairo_surface_set_device_scale(entry->pangocairo.surface, scale, scale);
+}
+
+void calculate_font_extents(struct entry *entry, uint32_t scale)
+{
+ /*
+ * To calculate the size of the password box, we do the following:
+ * 1. Load the font we're going to use.
+ * 2. Create a string of the desired length using the specified
+ * password character, e.g. "·······".
+ * 3. Render the string with Pango in some abstract layout.
+ * 4. Measure the bounding box of the layout.
+ * 5. Add on the size of the border / outline.
+ */
PangoFontMap *font_map = pango_cairo_font_map_get_default();
PangoContext *context = pango_font_map_create_context(font_map);
PangoLayout *layout = pango_layout_new(context);
- {
- PangoFontDescription *font_description = pango_font_description_from_string("Rubik Bold 48");
- pango_layout_set_font_description(layout, font_description);
- PangoFont *font = pango_font_map_load_font(font_map, context, font_description);
- g_object_unref(font);
- pango_font_description_free(font_description);
-
- font_description = pango_context_get_font_description(context);
- log_info("Using family: %s\n", pango_font_description_get_family(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);
+ PangoFont *font =
+ pango_font_map_load_font(font_map, context, font_description);
+ pango_font_description_free(font_description);
+
+ font_description = pango_font_describe(font);
+ log_info("Using font: %s\n",
+ pango_font_description_to_string(font_description));
+ g_object_unref(font);
+
+ char *buf = calloc(MAX_PASSWORD_LENGTH, 4);
+ size_t len = 0;
+ for (unsigned int i = 0; i < entry->num_characters; i++) {
+ len += wcrtomb(buf + len, entry->password_character, NULL);
+ }
+ buf[len] = '\0';
+ pango_layout_set_text(layout,buf, -1);
+ free(buf);
+
+ PangoRectangle rect;
+ if (entry->tight_layout) {
+ pango_layout_get_pixel_extents(layout, &rect, NULL);
+ } else {
+ pango_layout_get_pixel_extents(layout, NULL, &rect);
}
- pango_layout_set_text(layout, "············", -1);
-
- int width;
- int height;
- pango_layout_get_pixel_size(layout, &width, &height);
- fprintf(stderr, "%d x %d\n", width, height);
- fprintf(stderr, "%d, %d\n", entry->border.width, entry->border.outline_width);
- width += 2 * (entry->border.width + entry->border.outline_width);
- height += 2 * (entry->border.width + entry->border.outline_width);
- entry->surface.width = width;
- entry->surface.height = height;
+ 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);