aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Hugo Osvaldo Barrera <hugo@barrera.io>2022-06-29 21:38:24 +0200
committerLibravatar Simon Ser <contact@emersion.fr>2022-07-01 13:05:58 +0200
commit75605491a54f8647740fdba75dd2ad7bae9e0ca7 (patch)
treef1d7476fbc893517ea01ed0f92841219f8b4808a
parentAvoid unecessary string copy (diff)
downloadsway-75605491a54f8647740fdba75dd2ad7bae9e0ca7.tar.gz
sway-75605491a54f8647740fdba75dd2ad7bae9e0ca7.tar.zst
sway-75605491a54f8647740fdba75dd2ad7bae9e0ca7.zip
Reject font values that are invalid for pango
Use pango to parse font configuration early, and reject the command as invalid if the value is invalid for pango. Since we're already parsing the font into a `PangoFontDescription`, keep that instance around and avoid re-parsing the font each time we render text. Fixes: https://github.com/swaywm/sway/issues/6805
-rw-r--r--common/pango.c4
-rw-r--r--include/pango.h2
-rw-r--r--include/sway/config.h4
-rw-r--r--sway/commands/font.c23
-rw-r--r--sway/config.c3
5 files changed, 30 insertions, 6 deletions
diff --git a/common/pango.c b/common/pango.c
index abc18281..e8e2678d 100644
--- a/common/pango.c
+++ b/common/pango.c
@@ -109,10 +109,9 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
109 free(buf); 109 free(buf);
110} 110}
111 111
112void get_text_metrics(const char *font, int *height, int *baseline) { 112void get_text_metrics(const PangoFontDescription *description, int *height, int *baseline) {
113 cairo_t *cairo = cairo_create(NULL); 113 cairo_t *cairo = cairo_create(NULL);
114 PangoContext *pango = pango_cairo_create_context(cairo); 114 PangoContext *pango = pango_cairo_create_context(cairo);
115 PangoFontDescription *description = pango_font_description_from_string(font);
116 // When passing NULL as a language, pango uses the current locale. 115 // When passing NULL as a language, pango uses the current locale.
117 PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL); 116 PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL);
118 117
@@ -120,7 +119,6 @@ void get_text_metrics(const char *font, int *height, int *baseline) {
120 *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE; 119 *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
121 120
122 pango_font_metrics_unref(metrics); 121 pango_font_metrics_unref(metrics);
123 pango_font_description_free(description);
124 g_object_unref(pango); 122 g_object_unref(pango);
125 cairo_destroy(cairo); 123 cairo_destroy(cairo);
126} 124}
diff --git a/include/pango.h b/include/pango.h
index 93affc23..2f14d2bb 100644
--- a/include/pango.h
+++ b/include/pango.h
@@ -17,7 +17,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
17 const char *text, double scale, bool markup); 17 const char *text, double scale, bool markup);
18void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, 18void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
19 int *baseline, double scale, bool markup, const char *fmt, ...); 19 int *baseline, double scale, bool markup, const char *fmt, ...);
20void get_text_metrics(const char *font, int *height, int *baseline); 20void get_text_metrics(const PangoFontDescription *font, int *height, int *baseline);
21void render_text(cairo_t *cairo, const char *font, 21void render_text(cairo_t *cairo, const char *font,
22 double scale, bool markup, const char *fmt, ...); 22 double scale, bool markup, const char *fmt, ...);
23 23
diff --git a/include/sway/config.h b/include/sway/config.h
index 05678c33..8939af00 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -17,6 +17,7 @@
17#include "sway/input/tablet.h" 17#include "sway/input/tablet.h"
18#include "sway/tree/root.h" 18#include "sway/tree/root.h"
19#include "wlr-layer-shell-unstable-v1-protocol.h" 19#include "wlr-layer-shell-unstable-v1-protocol.h"
20#include <pango/pangocairo.h>
20 21
21// TODO: Refactor this shit 22// TODO: Refactor this shit
22 23
@@ -504,7 +505,8 @@ struct sway_config {
504 char *floating_scroll_right_cmd; 505 char *floating_scroll_right_cmd;
505 enum sway_container_layout default_orientation; 506 enum sway_container_layout default_orientation;
506 enum sway_container_layout default_layout; 507 enum sway_container_layout default_layout;
507 char *font; 508 char *font; // Use mostly for IPC.
509 PangoFontDescription *font_description; // Used internally for rendering and validating.
508 int font_height; 510 int font_height;
509 int font_baseline; 511 int font_baseline;
510 bool pango_markup; 512 bool pango_markup;
diff --git a/sway/commands/font.c b/sway/commands/font.c
index 3eda0a9c..74bb6b9f 100644
--- a/sway/commands/font.c
+++ b/sway/commands/font.c
@@ -4,6 +4,7 @@
4#include "sway/config.h" 4#include "sway/config.h"
5#include "log.h" 5#include "log.h"
6#include "stringop.h" 6#include "stringop.h"
7#include <pango/pangocairo.h>
7 8
8struct cmd_results *cmd_font(int argc, char **argv) { 9struct cmd_results *cmd_font(int argc, char **argv) {
9 struct cmd_results *error = NULL; 10 struct cmd_results *error = NULL;
@@ -22,6 +23,28 @@ struct cmd_results *cmd_font(int argc, char **argv) {
22 config->font = font; 23 config->font = font;
23 } 24 }
24 25
26 // Parse the font early so we can reject it if it's not valid for pango.
27 // Also avoids re-parsing each time we render text.
28 PangoFontDescription *font_description = pango_font_description_from_string(config->font);
29
30 const char *family = pango_font_description_get_family(font_description);
31 if (family == NULL) {
32 pango_font_description_free(font_description);
33 return cmd_results_new(CMD_FAILURE, "Invalid font family.");
34 }
35
36 const gint size = pango_font_description_get_size(font_description);
37 if (size == 0) {
38 pango_font_description_free(font_description);
39 return cmd_results_new(CMD_FAILURE, "Invalid font size.");
40 }
41
42 if (config->font_description != NULL) {
43 pango_font_description_free(config->font_description);
44 }
45
46 config->font_description = font_description;
25 config_update_font_height(); 47 config_update_font_height();
48
26 return cmd_results_new(CMD_SUCCESS, NULL); 49 return cmd_results_new(CMD_SUCCESS, NULL);
27} 50}
diff --git a/sway/config.c b/sway/config.c
index 8220ece0..b41dd871 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -243,6 +243,7 @@ static void config_defaults(struct sway_config *config) {
243 config->default_layout = L_NONE; 243 config->default_layout = L_NONE;
244 config->default_orientation = L_NONE; 244 config->default_orientation = L_NONE;
245 if (!(config->font = strdup("monospace 10"))) goto cleanup; 245 if (!(config->font = strdup("monospace 10"))) goto cleanup;
246 config->font_description = pango_font_description_from_string(config->font);
246 config->urgent_timeout = 500; 247 config->urgent_timeout = 500;
247 config->focus_on_window_activation = FOWA_URGENT; 248 config->focus_on_window_activation = FOWA_URGENT;
248 config->popup_during_fullscreen = POPUP_SMART; 249 config->popup_during_fullscreen = POPUP_SMART;
@@ -1006,7 +1007,7 @@ int workspace_output_cmp_workspace(const void *a, const void *b) {
1006void config_update_font_height(void) { 1007void config_update_font_height(void) {
1007 int prev_max_height = config->font_height; 1008 int prev_max_height = config->font_height;
1008 1009
1009 get_text_metrics(config->font, &config->font_height, &config->font_baseline); 1010 get_text_metrics(config->font_description, &config->font_height, &config->font_baseline);
1010 1011
1011 if (config->font_height != prev_max_height) { 1012 if (config->font_height != prev_max_height) {
1012 arrange_root(); 1013 arrange_root();