绘制 tag 标识
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user