]> git.mdlowis.com Git - proto/labwc.git/commitdiff
common/font: add scaled_font_buffer_create_for_titlebar()
authorJohn Lindgren <john@jlindgren.net>
Thu, 29 May 2025 16:34:03 +0000 (12:34 -0400)
committerJohn Lindgren <john@jlindgren.net>
Wed, 18 Jun 2025 19:48:24 +0000 (15:48 -0400)
Co-authored-by: tokyo4j <hrak1529@gmail.com>
include/common/font.h
include/common/scaled-font-buffer.h
src/common/font.c
src/common/scaled-font-buffer.c

index 17d1181e437daf75acf2c8fafbfb2f0baa31c88c..a7a5ba556ef48b98d2198377e6f3810852d674d1 100644 (file)
@@ -1,6 +1,8 @@
 /* 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;
@@ -36,14 +38,15 @@ void font_get_buffer_size(int max_width, const char *text, struct font *font,
  * 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
index e3de0248b325658790a1114e09c8dca8913dc030..ddccbc82f56dd95a1ea3461d508285c53fa94cc5 100644 (file)
@@ -20,6 +20,16 @@ struct scaled_font_buffer {
        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 */
 };
 
 /**
@@ -33,6 +43,17 @@ struct scaled_font_buffer {
  */
 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.
  *
@@ -44,6 +65,9 @@ struct scaled_font_buffer *scaled_font_buffer_create(struct wlr_scene_tree *pare
  * - 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,
index d21734675fc5c82a218a2b0a7d1ef42f455425ad..9599c846e85cdbc3cf62c0cf43bd04353490573f 100644 (file)
@@ -86,15 +86,18 @@ font_get_buffer_size(int max_width, const char *text, struct font *font,
 
 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) {
@@ -114,18 +117,16 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
         * 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);
index e0d79a572ca6a2b31aef96cfa627e85ddb97f8db..64584b033eadcd5c4fc4d41b0f9d1a5821d949ae 100644 (file)
@@ -7,6 +7,7 @@
 #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"
@@ -17,15 +18,23 @@ _create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale)
 {
        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;
 }
 
@@ -37,6 +46,7 @@ _destroy(struct scaled_scene_buffer *scaled_buffer)
 
        zfree(self->text);
        zfree(self->font.name);
+       zfree_pattern(self->bg_pattern);
        free(self);
 }
 
@@ -54,7 +64,9 @@ _equal(struct scaled_scene_buffer *scaled_buffer_a,
                && 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 = {
@@ -82,6 +94,18 @@ scaled_font_buffer_create(struct wlr_scene_tree *parent)
        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,
@@ -109,8 +133,11 @@ scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
        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);
 }
@@ -120,8 +147,11 @@ scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
 {
        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);
 }