void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); // Add one since vsnprintf excludes null terminator. int length = vsnprintf(NULL, 0, fmt, args) + 1; va_end(args); char *buf = malloc(length); if (buf == NULL) { sway_log(SWAY_ERROR, "Failed to allocate memory"); return; } va_start(args, fmt); vsnprintf(buf, length, fmt, args); va_end(args); PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); cairo_font_options_t *fo = cairo_font_options_create(); cairo_get_font_options(cairo, fo); pango_cairo_context_set_font_options(pango_layout_get_context(layout), fo); cairo_font_options_destroy(fo); pango_cairo_update_layout(cairo, layout); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); free(buf); }
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); // Add one since vsnprintf excludes null terminator. int length = vsnprintf(NULL, 0, fmt, args) + 1; va_end(args); char *buf = malloc(length); if (buf == NULL) { sway_log(SWAY_ERROR, "Failed to allocate memory"); return; } va_start(args, fmt); vsnprintf(buf, length, fmt, args); va_end(args); PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, width, height); if (baseline) { *baseline = pango_layout_get_baseline(layout) / PANGO_SCALE; } g_object_unref(layout); free(buf); }
void pango_printf(cairo_t *cairo, const char *font, int32_t scale, bool markup, const char *fmt, ...) { char *buf = malloc(2048); va_list args; va_start(args, fmt); if (vsnprintf(buf, 2048, fmt, args) >= 2048) { strcpy(buf, "[buffer overflow]"); } va_end(args); PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); pango_cairo_update_layout(cairo, layout); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); free(buf); }
static void gtk_numerable_icon_ensure_emblem (GtkNumerableIcon *self) { cairo_t *cr; cairo_surface_t *surface; PangoLayout *layout; GEmblem *emblem; gint width, height; gdouble scale; PangoAttrList *attr_list; PangoAttribute *attr; GdkPixbuf *pixbuf; /* don't draw anything if the count is zero */ if (self->priv->rendered_string == NULL) { g_emblemed_icon_clear_emblems (G_EMBLEMED_ICON (self)); return; } surface = get_image_surface (self); cr = cairo_create (surface); layout = get_pango_layout (self); pango_layout_get_pixel_size (layout, &width, &height); /* scale the layout to be 0.75 of the size still available for drawing */ scale = ((get_surface_size (surface) - 2 * get_border_size (self)) * 0.75) / (MAX (height, width)); attr_list = pango_attr_list_new (); attr = pango_attr_scale_new (scale); pango_attr_list_insert (attr_list, attr); attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); pango_attr_list_insert (attr_list, attr); pango_layout_set_attributes (layout, attr_list); /* update these values */ pango_layout_get_pixel_size (layout, &width, &height); /* move to the center */ cairo_move_to (cr, get_surface_size (surface) / 2. - (gdouble) width / 2., get_surface_size (surface) / 2. - (gdouble) height / 2.); gdk_cairo_set_source_rgba (cr, self->priv->foreground); pango_cairo_show_layout (cr, layout); cairo_destroy (cr); pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, get_surface_size (surface), get_surface_size (surface)); emblem = g_emblem_new (G_ICON (pixbuf)); g_emblemed_icon_clear_emblems (G_EMBLEMED_ICON (self)); g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (self), emblem); g_object_unref (layout); g_object_unref (emblem); g_object_unref (pixbuf); cairo_surface_destroy (surface); pango_attr_list_unref (attr_list); }
static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { uint32_t width = swaynag->width * swaynag->scale; int border = swaynag->type->details_border_thickness * swaynag->scale; int padding = swaynag->type->message_padding * swaynag->scale; int decor = padding + border; swaynag->details.x = decor; swaynag->details.y = y * swaynag->scale + decor; swaynag->details.width = width - decor * 2; PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, swaynag->details.message, swaynag->scale, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_single_paragraph_mode(layout, false); pango_cairo_update_layout(cairo, layout); swaynag->details.total_lines = pango_layout_get_line_count(layout); PangoLayoutLine *line; line = pango_layout_get_line_readonly(layout, swaynag->details.offset); gint offset = line->start_index; const char *text = pango_layout_get_text(layout); pango_layout_set_text(layout, text + offset, strlen(text) - offset); int text_width, text_height; pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); bool show_buttons = swaynag->details.offset > 0; int button_width = get_detailed_scroll_button_width(cairo, swaynag); if (show_buttons) { swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } uint32_t ideal_height; do { ideal_height = swaynag->details.y + text_height + decor + padding * 2; if (ideal_height > SWAYNAG_MAX_HEIGHT) { ideal_height = SWAYNAG_MAX_HEIGHT; if (!show_buttons) { show_buttons = true; swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } } swaynag->details.height = ideal_height - swaynag->details.y - decor; pango_layout_set_height(layout, (swaynag->details.height - padding * 2) * PANGO_SCALE); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); } while (text_height != (swaynag->details.height - padding * 2)); swaynag->details.visible_lines = pango_layout_get_line_count(layout); if (show_buttons) { swaynag->details.button_up.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_up.y = swaynag->details.y; swaynag->details.button_up.width = button_width; swaynag->details.button_up.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_up); swaynag->details.button_down.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_down.y = swaynag->details.button_up.y + swaynag->details.button_up.height; swaynag->details.button_down.width = button_width; swaynag->details.button_down.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_down); } cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, swaynag->details.x, swaynag->details.y, swaynag->details.width, swaynag->details.height); cairo_fill(cairo); cairo_move_to(cairo, swaynag->details.x + padding, swaynag->details.y + padding); cairo_set_source_u32(cairo, swaynag->type->text); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); return ideal_height / swaynag->scale; }