From b9eb02c46f1a53d28cbd7a858c9cc7c1db057b3f Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Sun, 9 Sep 2012 23:08:35 +0200 Subject: [PATCH] editor: Extract text handling into text_layout Create a text_layout struct and functions for handling simple text layouts. Signed-off-by: Jan Arne Petersen --- clients/editor.c | 99 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/clients/editor.c b/clients/editor.c index 346f3635..03abab26 100644 --- a/clients/editor.c +++ b/clients/editor.c @@ -32,12 +32,25 @@ #include "window.h" #include "text-client-protocol.h" +static const char *font_name = "sans-serif"; +static int font_size = 14; + +struct text_layout { + cairo_glyph_t *glyphs; + int num_glyphs; + cairo_text_cluster_t *clusters; + int num_clusters; + cairo_text_cluster_flags_t cluster_flags; + cairo_scaled_font_t *font; +}; + struct text_entry { struct widget *widget; struct window *window; char *text; int active; struct text_model *model; + struct text_layout *layout; }; struct editor { @@ -49,6 +62,81 @@ struct editor { struct text_entry *editor; }; +static struct text_layout * +text_layout_create(void) +{ + struct text_layout *layout; + cairo_surface_t *surface; + cairo_t *cr; + + layout = malloc(sizeof *layout); + if (!layout) + return NULL; + + layout->glyphs = NULL; + layout->num_glyphs = 0; + + layout->clusters = NULL; + layout->num_clusters = 0; + + surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + cr = cairo_create(surface); + cairo_set_font_size(cr, font_size); + cairo_select_font_face(cr, font_name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + layout->font = cairo_get_scaled_font(cr); + cairo_scaled_font_reference(layout->font); + + cairo_destroy(cr); + cairo_surface_destroy(surface); + + return layout; +} + +static void +text_layout_destroy(struct text_layout *layout) +{ + if (layout->glyphs) + cairo_glyph_free(layout->glyphs); + + if (layout->clusters) + cairo_text_cluster_free(layout->clusters); + + cairo_scaled_font_destroy(layout->font); + + free(layout); +} + +static void +text_layout_set_text(struct text_layout *layout, + const char *text) +{ + if (layout->glyphs) + cairo_glyph_free(layout->glyphs); + + if (layout->clusters) + cairo_text_cluster_free(layout->clusters); + + layout->glyphs = NULL; + layout->num_glyphs = 0; + layout->clusters = NULL; + layout->num_clusters = 0; + + cairo_scaled_font_text_to_glyphs(layout->font, 0, 0, text, -1, + &layout->glyphs, &layout->num_glyphs, + &layout->clusters, &layout->num_clusters, + &layout->cluster_flags); +} + +static void +text_layout_draw(struct text_layout *layout, cairo_t *cr) +{ + cairo_save(cr); + cairo_set_scaled_font(cr, layout->font); + cairo_show_glyphs(cr, layout->glyphs, layout->num_glyphs); + cairo_restore(cr); +} + + static void text_entry_redraw_handler(struct widget *widget, void *data); static void text_entry_button_handler(struct widget *widget, struct input *input, uint32_t time, @@ -60,6 +148,7 @@ text_entry_append(struct text_entry *entry, const char *text) { entry->text = realloc(entry->text, strlen(entry->text) + strlen(text) + 1); strcat(entry->text, text); + text_layout_set_text(entry->layout, entry->text); } @@ -162,6 +251,9 @@ text_entry_create(struct editor *editor, const char *text) entry->model = text_model_factory_create_text_model(editor->text_model_factory); text_model_add_listener(entry->model, &text_model_listener, entry); + entry->layout = text_layout_create(); + text_layout_set_text(entry->layout, entry->text); + widget_set_redraw_handler(entry->widget, text_entry_redraw_handler); widget_set_button_handler(entry->widget, text_entry_button_handler); @@ -173,6 +265,7 @@ text_entry_destroy(struct text_entry *entry) { widget_destroy(entry->widget); text_model_destroy(entry->model); + text_layout_destroy(entry->layout); free(entry->text); free(entry); } @@ -285,13 +378,9 @@ text_entry_redraw_handler(struct widget *widget, void *data) } cairo_set_source_rgba(cr, 0, 0, 0, 1); - cairo_select_font_face(cr, "sans", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_BOLD); - cairo_set_font_size(cr, 14); cairo_translate(cr, 10, allocation.height / 2); - cairo_show_text(cr, entry->text); + text_layout_draw(entry->layout, cr); cairo_pop_group_to_source(cr); cairo_paint(cr);