ssd: rework titlebar button rendering

- fix that icons for normal/hovered/rounded buttons are not placed
  exactly the same position
- fix blurry window button icons in scaled outputs

This commit introduces lab_img and scaled_img_buffer and uses them for
rendering icons in the window titlebar. Now the process of rendering
button icons are split into 2 phases: loading with lab_img_load() and
creating scene-nodes for them with scaled_img_buffer_create(). This
might incur some additional overhead since we no longer preload icon
textures, but the rendering of icon only happens for the first window
as backing buffers are shared and the overhead won't be noticeable.
This commit also simplifies the process of centering icon buffer in the
button, by creating icon buffers in a fixed geometry via
lab_img_render().
This commit is contained in:
tokyo4j 2024-11-28 19:21:18 +09:00 committed by Hiroaki Yamamoto
parent 9a3412324d
commit 16dbdc64e5
25 changed files with 647 additions and 391 deletions

View file

@ -61,18 +61,6 @@ struct lab_data_buffer *buffer_adopt_cairo_surface(cairo_surface_t *surface);
struct lab_data_buffer *buffer_create_cairo(uint32_t logical_width,
uint32_t logical_height, float scale);
/*
* Create a buffer from an image surface, for display as an icon.
*
* The surface is either adopted by the buffer (which takes ownership),
* or copied and then destroyed.
*
* This function allows non-ARGB32 source images and converts to
* CAIRO_FORMAT_ARGB32 if needed.
*/
struct lab_data_buffer *buffer_convert_cairo_surface_for_icon(
cairo_surface_t *surface, uint32_t icon_size, float scale);
/*
* Create a buffer which holds (and takes ownership of) raw pixel data
* in pre-multiplied ARGB32 format.

View file

@ -13,14 +13,13 @@ void box_union(struct wlr_box *box_dest, struct wlr_box *box_a,
struct wlr_box *box_b);
/*
* Fits and centers a content box (width & height) within a bounding box
* (max_width & max_height). The content box is downscaled if necessary
* (preserving aspect ratio) but not upscaled.
* Fits and centers a content box (width & height) within a bounding box.
* The content box is downscaled if necessary (preserving aspect ratio) but
* not upscaled.
*
* The returned x & y coordinates are the centered content position
* relative to the top-left corner of the bounding box.
*/
struct wlr_box box_fit_within(int width, int height, int max_width,
int max_height);
struct wlr_box box_fit_within(int width, int height, struct wlr_box *bounding_box);
#endif /* LABWC_BOX_H */

View file

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_SCALED_IMG_BUFFER_H
#define LABWC_SCALED_IMG_BUFFER_H
#include <stdbool.h>
struct wlr_scene_tree;
struct wlr_scene_node;
struct wlr_scene_buffer;
struct lab_img;
struct scaled_img_buffer {
struct scaled_scene_buffer *scaled_buffer;
struct wlr_scene_buffer *scene_buffer;
struct lab_img *img;
int width;
int height;
int padding;
};
/*
* Create an auto scaling image buffer, providing a wlr_scene_buffer node for
* display. It gets destroyed automatically when the backing scaled_scene_buffer
* is being destroyed which in turn happens automatically when the backing
* wlr_scene_buffer (or one of its parents) is being destroyed.
*/
struct scaled_img_buffer *scaled_img_buffer_create(struct wlr_scene_tree *parent,
struct lab_img *img, int width, int height, int padding);
/* Update image, width, height and padding of the scaled_img_buffer */
void scaled_img_buffer_update(struct scaled_img_buffer *self,
struct lab_img *img, int width, int height, int padding);
/* Obtain scaled_img_buffer from wlr_scene_node */
struct scaled_img_buffer *scaled_img_buffer_from_node(struct wlr_scene_node *node);
#endif /* LABWC_SCALED_IMG_BUFFER_H */

View file

@ -7,7 +7,7 @@ struct server;
void desktop_entry_init(struct server *server);
void desktop_entry_finish(struct server *server);
struct lab_data_buffer *desktop_entry_icon_lookup(struct server *server,
struct lab_img *desktop_entry_icon_lookup(struct server *server,
const char *app_id, int size, float scale);
/**

View file

@ -2,9 +2,6 @@
#ifndef LABWC_IMG_PNG_H
#define LABWC_IMG_PNG_H
struct lab_data_buffer;
void img_png_load(const char *filename, struct lab_data_buffer **buffer,
int size, float scale);
struct lab_data_buffer *img_png_load(const char *filename);
#endif /* LABWC_IMG_PNG_H */

View file

@ -2,9 +2,13 @@
#ifndef LABWC_IMG_SVG_H
#define LABWC_IMG_SVG_H
#include <librsvg/rsvg.h>
struct lab_data_buffer;
void img_svg_load(const char *filename, struct lab_data_buffer **buffer,
int size, float scale);
RsvgHandle *img_svg_load(const char *filename);
struct lab_data_buffer *img_svg_render(RsvgHandle *svg, int w, int h,
int padding, double scale);
#endif /* LABWC_IMG_SVG_H */

View file

@ -5,18 +5,15 @@
struct lab_data_buffer;
/**
* img_xbm_from_bitmap() - create button from monochrome bitmap
* img_xbm_load_from_bitmap() - create button from monochrome bitmap
* @bitmap: bitmap data array in hexadecimal xbm format
* @buffer: cairo-surface-buffer to create
* @rgba: color
*
* Example bitmap: char button[6] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
*/
void img_xbm_from_bitmap(const char *bitmap, struct lab_data_buffer **buffer,
float *rgba);
struct lab_data_buffer *img_xbm_load_from_bitmap(const char *bitmap, float *rgba);
/* img_xbm_load - Convert xbm file to buffer with cairo surface */
void img_xbm_load(const char *filename, struct lab_data_buffer **buffer,
float *rgba);
struct lab_data_buffer *img_xbm_load(const char *filename, float *rgba);
#endif /* LABWC_IMG_XBM_H */

View file

@ -4,7 +4,6 @@
struct lab_data_buffer;
void img_xpm_load(const char *filename, struct lab_data_buffer **buffer,
int size, float scale);
struct lab_data_buffer *img_xpm_load(const char *filename);
#endif /* LABWC_IMG_XPM_H */

78
include/img/img.h Normal file
View file

@ -0,0 +1,78 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_IMG_H
#define LABWC_IMG_H
#include <cairo.h>
#include <stdint.h>
#include <wayland-util.h>
struct lab_img_cache;
enum lab_img_type {
LAB_IMG_PNG,
LAB_IMG_SVG,
LAB_IMG_XBM,
LAB_IMG_XPM,
};
struct lab_img {
struct theme *theme; /* Used by modifier functions */
struct wl_array modifiers; /* lab_img_modifier_func_t */
struct lab_img_cache *cache;
};
struct lab_img *lab_img_load(enum lab_img_type type, const char *path,
float *xbm_color);
/**
* lab_img_load_from_bitmap() - create button from monochrome bitmap
* @bitmap: bitmap data array in hexadecimal xbm format
* @rgba: color
*
* Example bitmap: char button[6] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
*/
struct lab_img *lab_img_load_from_bitmap(const char *bitmap, float *rgba);
typedef void (*lab_img_modifier_func_t)(struct theme *theme, cairo_t *cairo,
int w, int h);
/**
* lab_img_copy() - Copy lab_img
* @img: source image
*
* This function duplicates lab_img, but its internal cache for the image is
* shared.
*/
struct lab_img *lab_img_copy(struct lab_img *img);
/**
* lab_img_add_modifier() - Add a modifier function to lab_img
* @img: source image
* @modifier: function that applies modifications to the image.
* @theme: pointer to theme passed to @modifier.
*
* "Modifiers" are functions that perform some additional drawing operation
* after the image is rendered on a buffer with lab_img_render(). For example,
* hover effects for window buttons can be drawn over the rendered image.
*/
void lab_img_add_modifier(struct lab_img *img, lab_img_modifier_func_t modifier,
struct theme *theme);
/**
* lab_img_render() - Render lab_img to a buffer
* @img: source image
* @width: width of the created buffer
* @height: height of the created buffer
* @padding: padding around the rendered image in the buffer
* @scale: scale of the created buffer
*/
struct lab_data_buffer *lab_img_render(struct lab_img *img,
int width, int height, int padding, double scale);
/**
* lab_img_destroy() - destroy lab_img
* @img: lab_img to destroy
*/
void lab_img_destroy(struct lab_img *img);
#endif /* LABWC_IMG_H */

View file

@ -79,6 +79,7 @@ struct ssd {
} title;
char *app_id;
struct lab_img *icon_img;
} state;
/* An invisible area around the view which allows resizing */
@ -146,10 +147,8 @@ struct ssd_part *add_scene_buffer(
struct wlr_scene_tree *parent, struct wlr_buffer *buffer, int x, int y);
struct ssd_part *add_scene_button(struct wl_list *part_list,
enum ssd_part_type type, struct wlr_scene_tree *parent,
struct lab_data_buffer *buffers[LAB_BS_ALL + 1], int x, int y,
struct lab_img *buffers[LAB_BS_ALL + 1], int x, int y,
struct view *view);
void update_window_icon_buffer(struct wlr_scene_node *button_node,
struct lab_data_buffer *buffer);
/* SSD internal helpers */
struct ssd_part *ssd_get_part(

View file

@ -12,6 +12,8 @@
#include <wlr/render/wlr_renderer.h>
#include "ssd.h"
struct lab_img;
enum lab_justification {
LAB_JUSTIFY_LEFT,
LAB_JUSTIFY_CENTER,
@ -82,7 +84,7 @@ struct theme {
*
* Elements in buttons[0] are all NULL since LAB_SSD_BUTTON_FIRST is 1.
*/
struct lab_data_buffer *buttons
struct lab_img *button_imgs
[LAB_SSD_BUTTON_LAST + 1][LAB_BS_ALL + 1];
struct lab_data_buffer *corner_top_left_normal;