/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_FONT_H
#define LABWC_FONT_H
+
+#include <cairo.h>
#include <pango/pango-font.h>
struct lab_data_buffer;
* font_buffer_create - Create ARGB8888 lab_data_buffer using pango
* @buffer: buffer pointer
* @max_width: max allowable width; will be ellipsized if longer
+ * @height: buffer height or -1 to compute from font
* @text: text to be generated as texture
* @font: font description
* @color: foreground color in rgba format
- * @bg_color: background color in rgba format
+ * @bg_pattern: background pattern
*/
void font_buffer_create(struct lab_data_buffer **buffer, int max_width,
- const char *text, struct font *font, const float *color,
- const float *bg_color, double scale);
+ int height, const char *text, struct font *font, const float *color,
+ cairo_pattern_t *bg_pattern, double scale);
/**
* font_finish - free some font related resources
float bg_color[4];
struct font font;
struct scaled_scene_buffer *scaled_buffer;
+
+ /*
+ * The following fields are used only for the titlebar, where
+ * the font buffer can be rendered with a pattern background to
+ * support gradients. In this case, the font buffer is also
+ * padded to a fixed height (with the text centered vertically)
+ * in order to align the pattern with the rest of the titlebar.
+ */
+ int fixed_height;
+ cairo_pattern_t *bg_pattern; /* overrides bg_color if set */
};
/**
*/
struct scaled_font_buffer *scaled_font_buffer_create(struct wlr_scene_tree *parent);
+/**
+ * Create an auto scaling font buffer for titlebar text.
+ * The font buffer takes a new reference to bg_pattern.
+ *
+ * @param fixed_height Fixed height for the buffer (logical pixels)
+ * @param bg_pattern Background pattern (solid color or gradient)
+ */
+struct scaled_font_buffer *
+scaled_font_buffer_create_for_titlebar(struct wlr_scene_tree *parent,
+ int fixed_height, cairo_pattern_t *bg_pattern);
+
/**
* Update an existing auto scaling font buffer.
*
* - truncated = buffer->width == max_width
* - text_changed = strcmp(old_text, new_text)
* - font and color the same
+ *
+ * bg_color is ignored for font buffers created with
+ * scaled_font_buffer_create_for_titlebar().
*/
void scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
int max_width, struct font *font, const float *color,
void
font_buffer_create(struct lab_data_buffer **buffer, int max_width,
- const char *text, struct font *font, const float *color,
- const float *bg_color, double scale)
+ int height, const char *text, struct font *font, const float *color,
+ cairo_pattern_t *bg_pattern, double scale)
{
if (string_null_or_empty(text)) {
return;
}
- int width, height;
- font_get_buffer_size(max_width, text, font, &width, &height);
+ int width, computed_height;
+ font_get_buffer_size(max_width, text, font, &width, &computed_height);
+ if (height <= 0) {
+ height = computed_height;
+ }
*buffer = buffer_create_cairo(width, height, scale);
if (!*buffer) {
* buffer unfilled (completely transparent) since the background
* is already rendered by the scene element underneath. In this
* case we have to disable subpixel rendering.
- *
- * Note: the 0.999 cutoff was chosen to be greater than 254/255
- * (about 0.996) but leave some margin for rounding errors.
*/
- bool opaque_bg = (bg_color[3] > 0.999f);
+ bool opaque_bg = is_pattern_opaque(bg_pattern);
if (opaque_bg) {
- set_cairo_color(cairo, bg_color);
+ cairo_set_source(cairo, bg_pattern);
cairo_paint(cairo);
}
set_cairo_color(cairo, color);
- cairo_move_to(cairo, 0, 0);
+ /* center vertically if height was explicitly specified */
+ cairo_move_to(cairo, 0, (height - computed_height) / 2);
PangoLayout *layout = pango_cairo_create_layout(cairo);
pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
#include <wlr/util/log.h>
#include "buffer.h"
#include "common/font.h"
+#include "common/graphic-helpers.h"
#include "common/mem.h"
#include "common/scaled-scene-buffer.h"
#include "common/scaled-font-buffer.h"
{
struct lab_data_buffer *buffer = NULL;
struct scaled_font_buffer *self = scaled_buffer->data;
+ cairo_pattern_t *bg_pattern = self->bg_pattern;
+ cairo_pattern_t *solid_bg_pattern = NULL;
+
+ if (!bg_pattern) {
+ solid_bg_pattern = color_to_pattern(self->bg_color);
+ bg_pattern = solid_bg_pattern;
+ }
/* Buffer gets free'd automatically along the backing wlr_buffer */
- font_buffer_create(&buffer, self->max_width, self->text,
- &self->font, self->color, self->bg_color, scale);
+ font_buffer_create(&buffer, self->max_width, self->height, self->text,
+ &self->font, self->color, bg_pattern, scale);
if (!buffer) {
wlr_log(WLR_ERROR, "font_buffer_create() failed");
}
+ zfree_pattern(solid_bg_pattern);
return buffer;
}
zfree(self->text);
zfree(self->font.name);
+ zfree_pattern(self->bg_pattern);
free(self);
}
&& a->font.slant == b->font.slant
&& a->font.weight == b->font.weight
&& !memcmp(a->color, b->color, sizeof(a->color))
- && !memcmp(a->bg_color, b->bg_color, sizeof(a->bg_color));
+ && !memcmp(a->bg_color, b->bg_color, sizeof(a->bg_color))
+ && a->fixed_height == b->fixed_height
+ && a->bg_pattern == b->bg_pattern;
}
static const struct scaled_scene_buffer_impl impl = {
return self;
}
+struct scaled_font_buffer *
+scaled_font_buffer_create_for_titlebar(struct wlr_scene_tree *parent,
+ int fixed_height, cairo_pattern_t *bg_pattern)
+{
+ struct scaled_font_buffer *self = scaled_font_buffer_create(parent);
+ if (self) {
+ self->fixed_height = fixed_height;
+ self->bg_pattern = cairo_pattern_reference(bg_pattern);
+ }
+ return self;
+}
+
void
scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
int max_width, struct font *font, const float *color,
memcpy(self->bg_color, bg_color, sizeof(self->bg_color));
/* Calculate the size of font buffer and request re-rendering */
+ int computed_height;
font_get_buffer_size(self->max_width, self->text, &self->font,
- &self->width, &self->height);
+ &self->width, &computed_height);
+ self->height = (self->fixed_height > 0) ?
+ self->fixed_height : computed_height;
scaled_scene_buffer_request_update(self->scaled_buffer,
self->width, self->height);
}
{
self->max_width = max_width;
+ int computed_height;
font_get_buffer_size(self->max_width, self->text, &self->font,
- &self->width, &self->height);
+ &self->width, &computed_height);
+ self->height = (self->fixed_height > 0) ?
+ self->fixed_height : computed_height;
scaled_scene_buffer_request_update(self->scaled_buffer,
self->width, self->height);
}