绘制 tag 标识

This commit is contained in:
2025-08-16 04:43:00 +08:00
parent 8472fda46a
commit e87607f817
7 changed files with 145 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
#include <cairo.h>
#include <glib-object.h>
#include <glib.h>
#include <pango/pango-attributes.h>
#include <pango/pango-context.h>
#include <pango/pango-font.h>
@@ -6,12 +8,16 @@
#include <pango/pango-layout.h>
#include <pango/pango-types.h>
#include <pango/pangocairo.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "renderer.h"
#include "types.h"
static PangoContext *context = NULL;
static PangoAttrList *attr_list = NULL;
static PangoLayout *layout = NULL;
uint32_t get_font_height(const char *font_family, const uint32_t font_size,
const uint32_t dpi) {
@@ -22,14 +28,13 @@ uint32_t get_font_height(const char *font_family, const uint32_t font_size,
pango_cairo_context_set_resolution(context, dpi);
PangoLanguage *lang = pango_context_get_language(context);
PangoAttrList *attr_list = pango_attr_list_new();
attr_list = pango_attr_list_new();
PangoFontDescription *desc = pango_font_description_from_string(font_family);
pango_font_description_set_size(desc, font_size * PANGO_SCALE);
PangoAttribute *attr = pango_attr_font_desc_new(desc);
pango_attr_list_insert(attr_list, attr);
pango_attr_list_unref(attr_list);
PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, lang);
int ascent = pango_font_metrics_get_ascent(metrics);
@@ -43,9 +48,108 @@ uint32_t get_font_height(const char *font_family, const uint32_t font_size,
return font_height;
}
static void draw_background(cairo_t *cr, color_t *color, int32_t x, int32_t y,
uint32_t width, uint32_t height) {
cairo_move_to(cr, x, y);
cairo_set_source_rgba(cr, color->red, color->green, color->blue,
color->alpha);
cairo_rectangle(cr, x, y, width, height);
cairo_fill(cr);
}
static void prepare_layout(bool align_center) {
if (!layout) {
layout = pango_layout_new(context);
pango_layout_set_attributes(layout, attr_list);
pango_layout_set_wrap(layout, PANGO_WRAP_NONE);
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
}
PangoAlignment align = align_center ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT;
pango_layout_set_alignment(layout, align);
}
static void get_layout_size(PangoLayout *layout, int *width, int *height) {
PangoRectangle ink_rect, logical_rect;
pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect);
int w = MAX(ink_rect.width, logical_rect.width);
int h = MAX(ink_rect.height, logical_rect.height);
if (width) *width = w;
if (height) *height = h;
}
static uint32_t get_text_width(const char *text) {
prepare_layout(false);
pango_layout_set_width(layout, -1);
pango_layout_set_text(layout, text, -1);
int w;
get_layout_size(layout, &w, NULL);
return (uint32_t)w;
}
static void draw_text(cairo_t *cr, const char *text, color_t *color, int32_t x,
uint32_t y, uint32_t width, uint32_t height,
bool align_center) {
prepare_layout(align_center);
pango_layout_set_width(layout, width * PANGO_SCALE);
pango_layout_set_text(layout, text, -1);
cairo_set_source_rgba(cr, color->red, color->green, color->blue,
color->alpha);
int h = 0;
get_layout_size(layout, NULL, &h);
double ty = ((double)height - h) / 2;
pango_cairo_update_layout(cr, layout);
cairo_move_to(cr, x, y + ty);
pango_cairo_show_layout(cr, layout);
}
static void clean_cairo_context(cairo_t *cr) {
cairo_save(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_restore(cr);
}
void draw_bar(monitor_t *monitor, bool is_current_monitor,
color_set_t *color_set, uint32_t height, uint32_t tag_x_padding) {
cairo_t *cr = monitor->cr;
int32_t x = 0;
uint32_t width = 0;
const char *text;
color_t *color;
clean_cairo_context(cr);
draw_background(cr, &color_set->bar_bg, 0, 0, monitor->monitor_width, height);
/* 绘制 tags */
for (int i = 0; i < g_strv_length(monitor->tags); i++) {
bool selected = (monitor->selected_tag >> i) & 0x1;
text = monitor->tags[i];
width = get_text_width(text) + tag_x_padding * 2;
color = selected ? &color_set->active_tag_bg : &color_set->tag_bg;
if (color->rgba != color_set->bar_bg.rgba) {
draw_background(cr, color, x, 0, width, height);
}
color = selected ? &color_set->active_tag_color : &color_set->tag_color;
draw_text(cr, text, color, x, 0, width, height, true);
x += width;
}
}
void clean_pango_context(void) {
if (!context) return;
g_object_unref(context);
context = NULL;
if (layout) {
g_object_unref(layout);
layout = NULL;
}
if (attr_list) {
pango_attr_list_unref(attr_list);
attr_list = NULL;
}
if (context) {
g_object_unref(context);
context = NULL;
}
}