aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Fenveireth <fenveireth@lhfblc.fr>2020-08-14 17:00:11 +0000
committerLibravatar Tudor Brindus <me@tbrindus.ca>2021-03-07 19:18:53 -0500
commit837605d68dc6112682bce0f133e3ba0b4dcfd440 (patch)
tree5e9702c36c57b08c3b64360cdb9fdb146dad70b5 /swaybar
parentcontainer: Limit tiled focus to container geometry (diff)
downloadsway-837605d68dc6112682bce0f133e3ba0b4dcfd440.tar.gz
sway-837605d68dc6112682bce0f133e3ba0b4dcfd440.tar.zst
sway-837605d68dc6112682bce0f133e3ba0b4dcfd440.zip
swaybar: use text subpixel antialias only where it would look good
Closes #5605 Text Subpixel antialiasing is : - FreeType makes glyph bitmaps containing coverage percentage for each subpixel, instead of pixel - Then draw by performing the blend for each subpixel, instead of pixel (e.g. dual-source blending in opengl) And there's only one Alpha channel, so this extra coverage data can't leave Cairo to reach the compositor through there. Therefore, it can't work as intended if output text alpha != bar background alpha. Disable it for those cases, enable it elsewhere As for color emojis, they are RGBA bitmaps. If drawn with text alpha=1.0 and background alpha=1.0 (should be completely opaque bar), then with 'CAIRO_OPERATOR_SOURCE' then texels with alpha < 1.0 result in a blend with whatever's behind the bar, instead of the bar background
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/render.c132
1 files changed, 97 insertions, 35 deletions
diff --git a/swaybar/render.c b/swaybar/render.c
index df066622..ebe127a5 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -23,8 +23,31 @@ static const int WS_HORIZONTAL_PADDING = 5;
23static const double WS_VERTICAL_PADDING = 1.5; 23static const double WS_VERTICAL_PADDING = 1.5;
24static const double BORDER_WIDTH = 1; 24static const double BORDER_WIDTH = 1;
25 25
26static uint32_t render_status_line_error(cairo_t *cairo, 26struct render_context {
27 struct swaybar_output *output, double *x) { 27 cairo_t *cairo;
28 struct swaybar_output *output;
29 cairo_font_options_t *textaa_sharp;
30 cairo_font_options_t *textaa_safe;
31 uint32_t background_color;
32};
33
34static void choose_text_aa_mode(struct render_context *ctx, uint32_t fontcolor) {
35 uint32_t salpha = fontcolor & 0xFF;
36 uint32_t balpha = ctx->background_color & 0xFF;
37
38 // Subpixel antialiasing requires blend be done in cairo, not compositor
39 cairo_font_options_t *fo = salpha == balpha ?
40 ctx->textaa_sharp : ctx->textaa_safe;
41 cairo_set_font_options(ctx->cairo, fo);
42
43 // Color emojis, being semitransparent bitmaps, are leaky with 'SOURCE'
44 cairo_operator_t op = salpha == 0xFF ?
45 CAIRO_OPERATOR_OVER : CAIRO_OPERATOR_SOURCE;
46 cairo_set_operator(ctx->cairo, op);
47}
48
49static uint32_t render_status_line_error(struct render_context *ctx, double *x) {
50 struct swaybar_output *output = ctx->output;
28 const char *error = output->bar->status->text; 51 const char *error = output->bar->status->text;
29 if (!error) { 52 if (!error) {
30 return 0; 53 return 0;
@@ -32,6 +55,7 @@ static uint32_t render_status_line_error(cairo_t *cairo,
32 55
33 uint32_t height = output->height * output->scale; 56 uint32_t height = output->height * output->scale;
34 57
58 cairo_t *cairo = ctx->cairo;
35 cairo_set_source_u32(cairo, 0xFF0000FF); 59 cairo_set_source_u32(cairo, 0xFF0000FF);
36 60
37 int margin = 3 * output->scale; 61 int margin = 3 * output->scale;
@@ -53,21 +77,24 @@ static uint32_t render_status_line_error(cairo_t *cairo,
53 77
54 double text_y = height / 2.0 - text_height / 2.0; 78 double text_y = height / 2.0 - text_height / 2.0;
55 cairo_move_to(cairo, *x, (int)floor(text_y)); 79 cairo_move_to(cairo, *x, (int)floor(text_y));
80 choose_text_aa_mode(ctx, 0xFF0000FF);
56 pango_printf(cairo, font, output->scale, false, "%s", error); 81 pango_printf(cairo, font, output->scale, false, "%s", error);
57 *x -= margin; 82 *x -= margin;
58 return output->height; 83 return output->height;
59} 84}
60 85
61static uint32_t render_status_line_text(cairo_t *cairo, 86static uint32_t render_status_line_text(struct render_context *ctx, double *x) {
62 struct swaybar_output *output, double *x) { 87 struct swaybar_output *output = ctx->output;
63 const char *text = output->bar->status->text; 88 const char *text = output->bar->status->text;
64 if (!text) { 89 if (!text) {
65 return 0; 90 return 0;
66 } 91 }
67 92
93 cairo_t *cairo = ctx->cairo;
68 struct swaybar_config *config = output->bar->config; 94 struct swaybar_config *config = output->bar->config;
69 cairo_set_source_u32(cairo, output->focused ? 95 uint32_t fontcolor = output->focused ?
70 config->colors.focused_statusline : config->colors.statusline); 96 config->colors.focused_statusline : config->colors.statusline;
97 cairo_set_source_u32(cairo, fontcolor);
71 98
72 int text_width, text_height; 99 int text_width, text_height;
73 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 100 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
@@ -87,6 +114,7 @@ static uint32_t render_status_line_text(cairo_t *cairo,
87 uint32_t height = output->height * output->scale; 114 uint32_t height = output->height * output->scale;
88 double text_y = height / 2.0 - text_height / 2.0; 115 double text_y = height / 2.0 - text_height / 2.0;
89 cairo_move_to(cairo, *x, (int)floor(text_y)); 116 cairo_move_to(cairo, *x, (int)floor(text_y));
117 choose_text_aa_mode(ctx, fontcolor);
90 pango_printf(cairo, config->font, output->scale, 118 pango_printf(cairo, config->font, output->scale,
91 config->pango_markup, "%s", text); 119 config->pango_markup, "%s", text);
92 *x -= margin; 120 *x -= margin;
@@ -96,6 +124,7 @@ static uint32_t render_status_line_text(cairo_t *cairo,
96static void render_sharp_rectangle(cairo_t *cairo, uint32_t color, 124static void render_sharp_rectangle(cairo_t *cairo, uint32_t color,
97 double x, double y, double width, double height) { 125 double x, double y, double width, double height) {
98 cairo_save(cairo); 126 cairo_save(cairo);
127 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
99 cairo_set_source_u32(cairo, color); 128 cairo_set_source_u32(cairo, color);
100 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); 129 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
101 cairo_rectangle(cairo, x, y, width, height); 130 cairo_rectangle(cairo, x, y, width, height);
@@ -109,6 +138,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color,
109 render_sharp_rectangle(cairo, color, x, y, width, height); 138 render_sharp_rectangle(cairo, color, x, y, width, height);
110 } else { 139 } else {
111 cairo_save(cairo); 140 cairo_save(cairo);
141 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
112 cairo_set_source_u32(cairo, color); 142 cairo_set_source_u32(cairo, color);
113 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); 143 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
114 if (width == 1) { 144 if (width == 1) {
@@ -146,9 +176,8 @@ static void i3bar_block_unref_callback(void *data) {
146 i3bar_block_unref(data); 176 i3bar_block_unref(data);
147} 177}
148 178
149static uint32_t render_status_block(cairo_t *cairo, 179static uint32_t render_status_block(struct render_context *ctx,
150 struct swaybar_output *output, struct i3bar_block *block, double *x, 180 struct i3bar_block *block, double *x, bool edge, bool use_short_text) {
151 bool edge, bool use_short_text) {
152 if (!block->full_text || !*block->full_text) { 181 if (!block->full_text || !*block->full_text) {
153 return 0; 182 return 0;
154 } 183 }
@@ -158,8 +187,9 @@ static uint32_t render_status_block(cairo_t *cairo,
158 text = block->short_text; 187 text = block->short_text;
159 } 188 }
160 189
190 cairo_t *cairo = ctx->cairo;
191 struct swaybar_output *output = ctx->output;
161 struct swaybar_config *config = output->bar->config; 192 struct swaybar_config *config = output->bar->config;
162
163 int text_width, text_height; 193 int text_width, text_height;
164 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 194 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
165 output->scale, block->markup, "%s", text); 195 output->scale, block->markup, "%s", text);
@@ -240,6 +270,7 @@ static uint32_t render_status_block(cairo_t *cairo,
240 if (bg_color) { 270 if (bg_color) {
241 render_sharp_rectangle(cairo, bg_color, x_pos, y_pos, 271 render_sharp_rectangle(cairo, bg_color, x_pos, y_pos,
242 block_width, render_height); 272 block_width, render_height);
273 ctx->background_color = bg_color;
243 } 274 }
244 275
245 uint32_t border_color = block->urgent 276 uint32_t border_color = block->urgent
@@ -274,6 +305,7 @@ static uint32_t render_status_block(cairo_t *cairo,
274 color = block->color_set ? block->color : color; 305 color = block->color_set ? block->color : color;
275 color = block->urgent ? config->colors.urgent_workspace.text : color; 306 color = block->urgent ? config->colors.urgent_workspace.text : color;
276 cairo_set_source_u32(cairo, color); 307 cairo_set_source_u32(cairo, color);
308 choose_text_aa_mode(ctx, color);
277 pango_printf(cairo, config->font, output->scale, 309 pango_printf(cairo, config->font, output->scale,
278 block->markup, "%s", text); 310 block->markup, "%s", text);
279 x_pos += width; 311 x_pos += width;
@@ -287,17 +319,20 @@ static uint32_t render_status_block(cairo_t *cairo,
287 319
288 if (!edge && block->separator) { 320 if (!edge && block->separator) {
289 if (output->focused) { 321 if (output->focused) {
290 cairo_set_source_u32(cairo, config->colors.focused_separator); 322 color = config->colors.focused_separator;
291 } else { 323 } else {
292 cairo_set_source_u32(cairo, config->colors.separator); 324 color = config->colors.separator;
293 } 325 }
326 cairo_set_source_u32(cairo, color);
294 if (config->sep_symbol) { 327 if (config->sep_symbol) {
295 offset = x_pos + (sep_block_width - sep_width) / 2; 328 offset = x_pos + (sep_block_width - sep_width) / 2;
296 double sep_y = height / 2.0 - sep_height / 2.0; 329 double sep_y = height / 2.0 - sep_height / 2.0;
297 cairo_move_to(cairo, offset, (int)floor(sep_y)); 330 cairo_move_to(cairo, offset, (int)floor(sep_y));
331 choose_text_aa_mode(ctx, color);
298 pango_printf(cairo, config->font, output->scale, false, 332 pango_printf(cairo, config->font, output->scale, false,
299 "%s", config->sep_symbol); 333 "%s", config->sep_symbol);
300 } else { 334 } else {
335 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
301 cairo_set_line_width(cairo, 1); 336 cairo_set_line_width(cairo, 1);
302 cairo_move_to(cairo, x_pos + sep_block_width / 2, margin); 337 cairo_move_to(cairo, x_pos + sep_block_width / 2, margin);
303 cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin); 338 cairo_line_to(cairo, x_pos + sep_block_width / 2, height - margin);
@@ -459,13 +494,14 @@ static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo,
459 return width; 494 return width;
460} 495}
461 496
462static uint32_t render_status_line_i3bar(cairo_t *cairo, 497static uint32_t render_status_line_i3bar(struct render_context *ctx, double *x) {
463 struct swaybar_output *output, double *x) { 498 struct swaybar_output *output = ctx->output;
464 uint32_t max_height = 0; 499 uint32_t max_height = 0;
465 bool edge = *x == output->width * output->scale; 500 bool edge = *x == output->width * output->scale;
466 struct i3bar_block *block; 501 struct i3bar_block *block;
467 bool use_short_text = false; 502 bool use_short_text = false;
468 503
504 cairo_t *cairo = ctx->cairo;
469 double reserved_width = 505 double reserved_width =
470 predict_workspace_buttons_length(cairo, output) + 506 predict_workspace_buttons_length(cairo, output) +
471 predict_binding_mode_indicator_length(cairo, output) + 507 predict_binding_mode_indicator_length(cairo, output) +
@@ -479,7 +515,7 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo,
479 } 515 }
480 516
481 wl_list_for_each(block, &output->bar->status->blocks, link) { 517 wl_list_for_each(block, &output->bar->status->blocks, link) {
482 uint32_t h = render_status_block(cairo, output, block, x, edge, 518 uint32_t h = render_status_block(ctx, block, x, edge,
483 use_short_text); 519 use_short_text);
484 max_height = h > max_height ? h : max_height; 520 max_height = h > max_height ? h : max_height;
485 edge = false; 521 edge = false;
@@ -487,29 +523,30 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo,
487 return max_height; 523 return max_height;
488} 524}
489 525
490static uint32_t render_status_line(cairo_t *cairo, 526static uint32_t render_status_line(struct render_context *ctx, double *x) {
491 struct swaybar_output *output, double *x) { 527 struct status_line *status = ctx->output->bar->status;
492 struct status_line *status = output->bar->status;
493 switch (status->protocol) { 528 switch (status->protocol) {
494 case PROTOCOL_ERROR: 529 case PROTOCOL_ERROR:
495 return render_status_line_error(cairo, output, x); 530 return render_status_line_error(ctx, x);
496 case PROTOCOL_TEXT: 531 case PROTOCOL_TEXT:
497 return render_status_line_text(cairo, output, x); 532 return render_status_line_text(ctx, x);
498 case PROTOCOL_I3BAR: 533 case PROTOCOL_I3BAR:
499 return render_status_line_i3bar(cairo, output, x); 534 return render_status_line_i3bar(ctx, x);
500 case PROTOCOL_UNDEF: 535 case PROTOCOL_UNDEF:
501 return 0; 536 return 0;
502 } 537 }
503 return 0; 538 return 0;
504} 539}
505 540
506static uint32_t render_binding_mode_indicator(cairo_t *cairo, 541static uint32_t render_binding_mode_indicator(struct render_context *ctx,
507 struct swaybar_output *output, double x) { 542 double x) {
543 struct swaybar_output *output = ctx->output;
508 const char *mode = output->bar->mode; 544 const char *mode = output->bar->mode;
509 if (!mode) { 545 if (!mode) {
510 return 0; 546 return 0;
511 } 547 }
512 548
549 cairo_t *cairo = ctx->cairo;
513 struct swaybar_config *config = output->bar->config; 550 struct swaybar_config *config = output->bar->config;
514 int text_width, text_height; 551 int text_width, text_height;
515 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 552 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
@@ -533,7 +570,9 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
533 } 570 }
534 571
535 uint32_t height = output->height * output->scale; 572 uint32_t height = output->height * output->scale;
573 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
536 cairo_set_source_u32(cairo, config->colors.binding_mode.background); 574 cairo_set_source_u32(cairo, config->colors.binding_mode.background);
575 ctx->background_color = config->colors.binding_mode.background;
537 cairo_rectangle(cairo, x, 0, width, height); 576 cairo_rectangle(cairo, x, 0, width, height);
538 cairo_fill(cairo); 577 cairo_fill(cairo);
539 578
@@ -550,6 +589,7 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
550 double text_y = height / 2.0 - text_height / 2.0; 589 double text_y = height / 2.0 - text_height / 2.0;
551 cairo_set_source_u32(cairo, config->colors.binding_mode.text); 590 cairo_set_source_u32(cairo, config->colors.binding_mode.text);
552 cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); 591 cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
592 choose_text_aa_mode(ctx, config->colors.binding_mode.text);
553 pango_printf(cairo, config->font, output->scale, 593 pango_printf(cairo, config->font, output->scale,
554 output->bar->mode_pango_markup, "%s", mode); 594 output->bar->mode_pango_markup, "%s", mode);
555 return output->height; 595 return output->height;
@@ -565,9 +605,9 @@ static enum hotspot_event_handling workspace_hotspot_callback(
565 return HOTSPOT_IGNORE; 605 return HOTSPOT_IGNORE;
566} 606}
567 607
568static uint32_t render_workspace_button(cairo_t *cairo, 608static uint32_t render_workspace_button(struct render_context *ctx,
569 struct swaybar_output *output,
570 struct swaybar_workspace *ws, double *x) { 609 struct swaybar_workspace *ws, double *x) {
610 struct swaybar_output *output = ctx->output;
571 struct swaybar_config *config = output->bar->config; 611 struct swaybar_config *config = output->bar->config;
572 struct box_colors box_colors; 612 struct box_colors box_colors;
573 if (ws->urgent) { 613 if (ws->urgent) {
@@ -582,6 +622,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
582 622
583 uint32_t height = output->height * output->scale; 623 uint32_t height = output->height * output->scale;
584 624
625 cairo_t *cairo = ctx->cairo;
585 int text_width, text_height; 626 int text_width, text_height;
586 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 627 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
587 output->scale, config->pango_markup, "%s", ws->label); 628 output->scale, config->pango_markup, "%s", ws->label);
@@ -603,7 +644,9 @@ static uint32_t render_workspace_button(cairo_t *cairo,
603 width = config->workspace_min_width * output->scale; 644 width = config->workspace_min_width * output->scale;
604 } 645 }
605 646
647 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
606 cairo_set_source_u32(cairo, box_colors.background); 648 cairo_set_source_u32(cairo, box_colors.background);
649 ctx->background_color = box_colors.background;
607 cairo_rectangle(cairo, *x, 0, width, height); 650 cairo_rectangle(cairo, *x, 0, width, height);
608 cairo_fill(cairo); 651 cairo_fill(cairo);
609 652
@@ -620,6 +663,7 @@ static uint32_t render_workspace_button(cairo_t *cairo,
620 double text_y = height / 2.0 - text_height / 2.0; 663 double text_y = height / 2.0 - text_height / 2.0;
621 cairo_set_source_u32(cairo, box_colors.text); 664 cairo_set_source_u32(cairo, box_colors.text);
622 cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); 665 cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y));
666 choose_text_aa_mode(ctx, box_colors.text);
623 pango_printf(cairo, config->font, output->scale, config->pango_markup, 667 pango_printf(cairo, config->font, output->scale, config->pango_markup,
624 "%s", ws->label); 668 "%s", ws->label);
625 669
@@ -637,15 +681,19 @@ static uint32_t render_workspace_button(cairo_t *cairo,
637 return output->height; 681 return output->height;
638} 682}
639 683
640static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { 684static uint32_t render_to_cairo(struct render_context *ctx) {
685 cairo_t *cairo = ctx->cairo;
686 struct swaybar_output *output = ctx->output;
641 struct swaybar *bar = output->bar; 687 struct swaybar *bar = output->bar;
642 struct swaybar_config *config = bar->config; 688 struct swaybar_config *config = bar->config;
643 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); 689 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
644 if (output->focused) { 690 if (output->focused) {
645 cairo_set_source_u32(cairo, config->colors.focused_background); 691 ctx->background_color = config->colors.focused_background;
646 } else { 692 } else {
647 cairo_set_source_u32(cairo, config->colors.background); 693 ctx->background_color = config->colors.background;
648 } 694 }
695
696 cairo_set_source_u32(cairo, ctx->background_color);
649 cairo_paint(cairo); 697 cairo_paint(cairo);
650 698
651 int th; 699 int th;
@@ -666,19 +714,19 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) {
666 } 714 }
667#endif 715#endif
668 if (bar->status) { 716 if (bar->status) {
669 uint32_t h = render_status_line(cairo, output, &x); 717 uint32_t h = render_status_line(ctx, &x);
670 max_height = h > max_height ? h : max_height; 718 max_height = h > max_height ? h : max_height;
671 } 719 }
672 x = 0; 720 x = 0;
673 if (config->workspace_buttons) { 721 if (config->workspace_buttons) {
674 struct swaybar_workspace *ws; 722 struct swaybar_workspace *ws;
675 wl_list_for_each(ws, &output->workspaces, link) { 723 wl_list_for_each(ws, &output->workspaces, link) {
676 uint32_t h = render_workspace_button(cairo, output, ws, &x); 724 uint32_t h = render_workspace_button(ctx, ws, &x);
677 max_height = h > max_height ? h : max_height; 725 max_height = h > max_height ? h : max_height;
678 } 726 }
679 } 727 }
680 if (config->binding_mode_indicator) { 728 if (config->binding_mode_indicator) {
681 uint32_t h = render_binding_mode_indicator(cairo, output, x); 729 uint32_t h = render_binding_mode_indicator(ctx, x);
682 max_height = h > max_height ? h : max_height; 730 max_height = h > max_height ? h : max_height;
683 } 731 }
684 732
@@ -708,26 +756,35 @@ void render_frame(struct swaybar_output *output) {
708 756
709 free_hotspots(&output->hotspots); 757 free_hotspots(&output->hotspots);
710 758
759 struct render_context ctx = { 0 };
760 ctx.output = output;
761
711 cairo_surface_t *recorder = cairo_recording_surface_create( 762 cairo_surface_t *recorder = cairo_recording_surface_create(
712 CAIRO_CONTENT_COLOR_ALPHA, NULL); 763 CAIRO_CONTENT_COLOR_ALPHA, NULL);
713 cairo_t *cairo = cairo_create(recorder); 764 cairo_t *cairo = cairo_create(recorder);
714 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); 765 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
766 ctx.cairo = cairo;
767
715 cairo_font_options_t *fo = cairo_font_options_create(); 768 cairo_font_options_t *fo = cairo_font_options_create();
716 cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); 769 cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
770 cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY);
771 ctx.textaa_safe = fo;
717 if (output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) { 772 if (output->subpixel == WL_OUTPUT_SUBPIXEL_NONE) {
718 cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_GRAY); 773 ctx.textaa_sharp = ctx.textaa_safe;
719 } else { 774 } else {
775 fo = cairo_font_options_create();
776 cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
720 cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); 777 cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
721 cairo_font_options_set_subpixel_order(fo, 778 cairo_font_options_set_subpixel_order(fo,
722 to_cairo_subpixel_order(output->subpixel)); 779 to_cairo_subpixel_order(output->subpixel));
780 ctx.textaa_sharp = fo;
723 } 781 }
724 cairo_set_font_options(cairo, fo); 782
725 cairo_font_options_destroy(fo);
726 cairo_save(cairo); 783 cairo_save(cairo);
727 cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); 784 cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
728 cairo_paint(cairo); 785 cairo_paint(cairo);
729 cairo_restore(cairo); 786 cairo_restore(cairo);
730 uint32_t height = render_to_cairo(cairo, output); 787 uint32_t height = render_to_cairo(&ctx);
731 int config_height = output->bar->config->height; 788 int config_height = output->bar->config->height;
732 if (config_height > 0) { 789 if (config_height > 0) {
733 height = config_height; 790 height = config_height;
@@ -779,6 +836,11 @@ void render_frame(struct swaybar_output *output) {
779 836
780 wl_surface_commit(output->surface); 837 wl_surface_commit(output->surface);
781 } 838 }
839
840 if (ctx.textaa_sharp != ctx.textaa_safe) {
841 cairo_font_options_destroy(ctx.textaa_sharp);
842 }
843 cairo_font_options_destroy(ctx.textaa_safe);
782 cairo_surface_destroy(recorder); 844 cairo_surface_destroy(recorder);
783 cairo_destroy(cairo); 845 cairo_destroy(cairo);
784} 846}