]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Add scaled_font_buffer implementation
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Mon, 13 Jun 2022 19:33:32 +0000 (21:33 +0200)
committerJohan Malm <johanmalm@users.noreply.github.com>
Tue, 14 Jun 2022 21:03:08 +0000 (22:03 +0100)
include/common/scaled_font_buffer.h [new file with mode: 0644]
src/common/meson.build
src/common/scaled_font_buffer.c [new file with mode: 0644]

diff --git a/include/common/scaled_font_buffer.h b/include/common/scaled_font_buffer.h
new file mode 100644 (file)
index 0000000..94debea
--- /dev/null
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __LAB_COMMON_SCALED_FONT_BUFFER_H
+#define __LAB_COMMON_SCALED_FONT_BUFFER_H
+
+struct font;
+struct wlr_scene_tree;
+struct wlr_scene_buffer;
+struct scaled_scene_buffere;
+
+struct scaled_font_buffer {
+       struct wlr_scene_buffer *scene_buffer;
+       int width;   /* unscaled, read only */
+       int height;  /* unscaled, read only */
+
+       /* Private */
+       char *text;
+       int max_width;
+       float color[4];
+       struct font font;
+       struct scaled_scene_buffer *scaled_buffer;
+};
+
+/**
+ * Create an auto scaling font buffer, providing a wlr_scene_buffer node for
+ * display. It gets destroyed automatically when the backing scaled_scene_buffer
+ * is being destoyed which in turn happens automatically when the backing
+ * wlr_scene_buffer (or one of its parents) is being destroyed.
+ *
+ * To actually show some text, scaled_font_buffer_update() has to be called.
+ *
+ */
+struct scaled_font_buffer *scaled_font_buffer_create(struct wlr_scene_tree *parent);
+
+/**
+ * Update an existing auto scaling font buffer.
+ *
+ * No steps are taken to detect if its actually required to render a new buffer.
+ * This should be done by the caller to prevent useless recreation of the same
+ * buffer in case nothing actually changed.
+ *
+ * Some basic checks could be something like
+ * - truncated = buffer->width == max_width
+ * - text_changed = strcmp(old_text, new_text)
+ * - font and color the same
+ */
+void scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
+       int max_width, struct font *font, float *color);
+
+#endif /* __LAB_COMMON_SCALED_FONT_BUFFER_H */
index 2e4407c8858396b000ab082a32bfb373dbdcc4a7..d04e9f63ca4cfb4317bbae600d57c79f82da42b3 100644 (file)
@@ -4,6 +4,7 @@ labwc_sources += files(
   'font.c',
   'grab-file.c',
   'nodename.c',
+  'scaled_font_buffer.c',
   'scaled_scene_buffer.c',
   'scene-helpers.c',
   'spawn.c',
diff --git a/src/common/scaled_font_buffer.c b/src/common/scaled_font_buffer.c
new file mode 100644 (file)
index 0000000..66375a7
--- /dev/null
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define _POSIX_C_SOURCE 200809L
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wayland-server-core.h>
+#include <wlr/util/log.h>
+#include "buffer.h"
+#include "common/font.h"
+#include "common/scaled_scene_buffer.h"
+#include "common/scaled_font_buffer.h"
+#include "common/zfree.h"
+
+static struct lab_data_buffer *
+_create_buffer(struct scaled_scene_buffer *scaled_buffer, double scale)
+{
+       struct lab_data_buffer *buffer;
+       struct scaled_font_buffer *self = scaled_buffer->data;
+
+       /* Buffer gets free'd automatically along the backing wlr_buffer */
+       font_buffer_create(&buffer, self->max_width, self->text,
+               &self->font, self->color, scale);
+
+       self->width = buffer ? buffer->unscaled_width : 0;
+       self->height = buffer ? buffer->unscaled_height : 0;
+       return buffer;
+}
+
+static void
+_destroy(struct scaled_scene_buffer *scaled_buffer)
+{
+       struct scaled_font_buffer *self = scaled_buffer->data;
+       if (self->text) {
+               zfree(self->text);
+       }
+       if (self->font.name) {
+               zfree(self->font.name);
+       }
+       zfree(scaled_buffer->data);
+}
+
+static const struct scaled_scene_buffer_impl impl = {
+       .create_buffer = _create_buffer,
+       .destroy = _destroy
+};
+
+/* Public API */
+struct scaled_font_buffer *
+scaled_font_buffer_create(struct wlr_scene_tree *parent)
+{
+       assert(parent);
+       struct scaled_font_buffer *self = calloc(1, sizeof(*self));
+       if (!self) {
+               return NULL;
+       }
+
+       struct scaled_scene_buffer *scaled_buffer
+               = scaled_scene_buffer_create(parent, &impl);
+       if (!scaled_buffer) {
+               free(self);
+               return NULL;
+       }
+
+       scaled_buffer->data = self;
+       self->scaled_buffer = scaled_buffer;
+       self->scene_buffer = scaled_buffer->scene_buffer;
+       return self;
+}
+
+void
+scaled_font_buffer_update(struct scaled_font_buffer *self,
+               const char *text, int max_width, struct font *font, float *color)
+{
+       assert(self);
+       assert(text);
+       assert(font);
+       assert(color);
+
+       /* Clean up old internal state */
+       if (self->text) {
+               zfree(self->text);
+       }
+       if (self->font.name) {
+               zfree(self->font.name);
+       }
+
+       /* Update internal state */
+       self->text = strdup(text);
+       self->max_width = max_width;
+       if (font->name) {
+               self->font.name = strdup(font->name);
+       }
+       self->font.size = font->size;
+       memcpy(self->color, color, sizeof(self->color));
+
+       /* Invalidate cache and force a new render */
+       scaled_scene_buffer_invalidate_cache(self->scaled_buffer);
+}