Correct color management for pango fonts
Corrects the cases where the colorpixel is not 0xRRGGBB : we have to
use the full color_t struct to describe font colors, as Pango expects
RGB values and not an XCB colorpixel value.
Alex Auvolat
8 years ago
478 | 478 | |
479 | 479 | if (current_step == STEP_WELCOME) { |
480 | 480 | /* restore font color */ |
481 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
481 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
482 | 482 | |
483 | 483 | txt(logical_px(10), 2, "You have not configured i3 yet."); |
484 | 484 | txt(logical_px(10), 3, "Do you want me to generate a config at"); |
492 | 492 | txt(logical_px(85), 8, "No, I will use the defaults"); |
493 | 493 | |
494 | 494 | /* green */ |
495 | set_font_colors(pixmap_gc, get_colorpixel("#00FF00"), get_colorpixel("#000000")); | |
495 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#00FF00"), draw_util_hex_to_color("#000000")); | |
496 | 496 | txt(logical_px(25), 6, "<Enter>"); |
497 | 497 | |
498 | 498 | /* red */ |
499 | set_font_colors(pixmap_gc, get_colorpixel("#FF0000"), get_colorpixel("#000000")); | |
499 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FF0000"), draw_util_hex_to_color("#000000")); | |
500 | 500 | txt(logical_px(31), 8, "<ESC>"); |
501 | 501 | } |
502 | 502 | |
503 | 503 | if (current_step == STEP_GENERATE) { |
504 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
504 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
505 | 505 | |
506 | 506 | txt(logical_px(10), 2, "Please choose either:"); |
507 | 507 | txt(logical_px(85), 4, "Win as default modifier"); |
518 | 518 | |
519 | 519 | /* the selected modifier */ |
520 | 520 | set_font(&bold_font); |
521 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
521 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
522 | 522 | if (modifier == MOD_Mod4) |
523 | 523 | txt(logical_px(10), 4, "-> <Win>"); |
524 | 524 | else |
526 | 526 | |
527 | 527 | /* green */ |
528 | 528 | set_font(&font); |
529 | set_font_colors(pixmap_gc, get_colorpixel("#00FF00"), get_colorpixel("#000000")); | |
529 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#00FF00"), draw_util_hex_to_color("#000000")); | |
530 | 530 | txt(logical_px(25), 9, "<Enter>"); |
531 | 531 | |
532 | 532 | /* red */ |
533 | set_font_colors(pixmap_gc, get_colorpixel("#FF0000"), get_colorpixel("#000000")); | |
533 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FF0000"), draw_util_hex_to_color("#000000")); | |
534 | 534 | txt(logical_px(31), 10, "<ESC>"); |
535 | 535 | } |
536 | 536 |
136 | 136 | xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner); |
137 | 137 | |
138 | 138 | /* restore font color */ |
139 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
139 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
140 | 140 | |
141 | 141 | /* draw the prompt … */ |
142 | 142 | if (prompt != NULL) { |
50 | 50 | static int buttoncnt; |
51 | 51 | |
52 | 52 | /* Result of get_colorpixel() for the various colors. */ |
53 | static uint32_t color_background; /* background of the bar */ | |
54 | static uint32_t color_button_background; /* background for buttons */ | |
55 | static uint32_t color_border; /* color of the button border */ | |
56 | static uint32_t color_border_bottom; /* color of the bottom border */ | |
57 | static uint32_t color_text; /* color of the text */ | |
53 | static color_t color_background; /* background of the bar */ | |
54 | static color_t color_button_background; /* background for buttons */ | |
55 | static color_t color_border; /* color of the button border */ | |
56 | static color_t color_border_bottom; /* color of the bottom border */ | |
57 | static color_t color_text; /* color of the text */ | |
58 | 58 | |
59 | 59 | xcb_window_t root; |
60 | 60 | xcb_connection_t *conn; |
190 | 190 | */ |
191 | 191 | static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { |
192 | 192 | /* re-draw the background */ |
193 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_background}); | |
193 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_background.colorpixel}); | |
194 | 194 | xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &rect); |
195 | 195 | |
196 | 196 | /* restore font color */ |
209 | 209 | w += logical_px(8); |
210 | 210 | int y = rect.width; |
211 | 211 | uint32_t values[3]; |
212 | values[0] = color_button_background; | |
212 | values[0] = color_button_background.colorpixel; | |
213 | 213 | values[1] = line_width; |
214 | 214 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); |
215 | 215 | |
216 | 216 | xcb_rectangle_t close = {y - w - (2 * line_width), 0, w + (2 * line_width), rect.height}; |
217 | 217 | xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); |
218 | 218 | |
219 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border}); | |
219 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border.colorpixel}); | |
220 | 220 | xcb_point_t points[] = { |
221 | 221 | {y - w - (2 * line_width), line_width / 2}, |
222 | 222 | {y - (line_width / 2), line_width / 2}, |
244 | 244 | /* account for left/right padding, which seems to be set to 12px (total) below */ |
245 | 245 | w += logical_px(12); |
246 | 246 | y -= logical_px(30); |
247 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_button_background}); | |
247 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_button_background.colorpixel}); | |
248 | 248 | close = (xcb_rectangle_t){y - w - (2 * line_width), logical_px(2), w + (2 * line_width), rect.height - logical_px(6)}; |
249 | 249 | xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &close); |
250 | 250 | |
251 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border}); | |
251 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND, (uint32_t[]){color_border.colorpixel}); | |
252 | 252 | buttons[c].x = y - w - (2 * line_width); |
253 | 253 | buttons[c].width = w; |
254 | 254 | xcb_point_t points2[] = { |
259 | 259 | {y - w - (2 * line_width), (line_width / 2) + logical_px(2)}}; |
260 | 260 | xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, pixmap, pixmap_gc, 5, points2); |
261 | 261 | |
262 | values[0] = color_text; | |
263 | values[1] = color_button_background; | |
262 | values[0] = color_text.colorpixel; | |
263 | values[1] = color_button_background.colorpixel; | |
264 | 264 | set_font_colors(pixmap_gc, color_text, color_button_background); |
265 | 265 | /* the x term seems to set left/right padding */ |
266 | 266 | draw_text(buttons[c].label, pixmap, pixmap_gc, NULL, |
273 | 273 | |
274 | 274 | /* border line at the bottom */ |
275 | 275 | line_width = logical_px(2); |
276 | values[0] = color_border_bottom; | |
276 | values[0] = color_border_bottom.colorpixel; | |
277 | 277 | values[1] = line_width; |
278 | 278 | xcb_change_gc(conn, pixmap_gc, XCB_GC_FOREGROUND | XCB_GC_LINE_WIDTH, values); |
279 | 279 | xcb_point_t bottom[] = { |
447 | 447 | |
448 | 448 | if (bar_type == TYPE_ERROR) { |
449 | 449 | /* Red theme for error messages */ |
450 | color_button_background = get_colorpixel("#680a0a"); | |
451 | color_background = get_colorpixel("#900000"); | |
452 | color_text = get_colorpixel("#ffffff"); | |
453 | color_border = get_colorpixel("#d92424"); | |
454 | color_border_bottom = get_colorpixel("#470909"); | |
450 | color_button_background = draw_util_hex_to_color("#680a0a"); | |
451 | color_background = draw_util_hex_to_color("#900000"); | |
452 | color_text = draw_util_hex_to_color("#ffffff"); | |
453 | color_border = draw_util_hex_to_color("#d92424"); | |
454 | color_border_bottom = draw_util_hex_to_color("#470909"); | |
455 | 455 | } else { |
456 | 456 | /* Yellowish theme for warnings */ |
457 | color_button_background = get_colorpixel("#ffc100"); | |
458 | color_background = get_colorpixel("#ffa8000"); | |
459 | color_text = get_colorpixel("#000000"); | |
460 | color_border = get_colorpixel("#ab7100"); | |
461 | color_border_bottom = get_colorpixel("#ab7100"); | |
457 | color_button_background = draw_util_hex_to_color("#ffc100"); | |
458 | color_background = draw_util_hex_to_color("#ffa8000"); | |
459 | color_text = draw_util_hex_to_color("#000000"); | |
460 | color_border = draw_util_hex_to_color("#ab7100"); | |
461 | color_border_bottom = draw_util_hex_to_color("#ab7100"); | |
462 | 462 | } |
463 | 463 | |
464 | 464 | font = load_font(pattern, true); |
391 | 391 | */ |
392 | 392 | xcb_char2b_t *convert_utf8_to_ucs2(char *input, size_t *real_strlen); |
393 | 393 | |
394 | /* Represents a color split by color channel. */ | |
395 | typedef struct color_t { | |
396 | double red; | |
397 | double green; | |
398 | double blue; | |
399 | double alpha; | |
400 | ||
401 | /* The colorpixel we use for direct XCB calls. */ | |
402 | uint32_t colorpixel; | |
403 | } color_t; | |
404 | ||
405 | #define COLOR_TRANSPARENT ((color_t){.red = 0.0, .green = 0.0, .blue = 0.0, .colorpixel = 0}) | |
406 | ||
394 | 407 | /** |
395 | 408 | * Defines the colors to be used for the forthcoming draw_text calls. |
396 | 409 | * |
397 | 410 | */ |
398 | void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background); | |
411 | void set_font_colors(xcb_gcontext_t gc, color_t foreground, color_t background); | |
399 | 412 | |
400 | 413 | /** |
401 | 414 | * Returns true if and only if the current font is a pango font. |
500 | 513 | } while (0) |
501 | 514 | #endif |
502 | 515 | |
503 | /* Represents a color split by color channel. */ | |
504 | typedef struct color_t { | |
505 | double red; | |
506 | double green; | |
507 | double blue; | |
508 | double alpha; | |
509 | ||
510 | /* The colorpixel we use for direct XCB calls. */ | |
511 | uint32_t colorpixel; | |
512 | } color_t; | |
513 | ||
514 | #define COLOR_TRANSPARENT ((color_t){.red = 0.0, .green = 0.0, .blue = 0.0, .colorpixel = 0}) | |
515 | ||
516 | 516 | /* A wrapper grouping an XCB drawable and both a graphics context |
517 | 517 | * and the corresponding cairo objects representing it. */ |
518 | 518 | typedef struct surface_t { |
143 | 143 | CAIRO_SURFACE_FLUSH(surface->surface); |
144 | 144 | #endif |
145 | 145 | |
146 | set_font_colors(surface->gc, fg_color.colorpixel, bg_color.colorpixel); | |
146 | set_font_colors(surface->gc, fg_color, bg_color); | |
147 | 147 | draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width); |
148 | 148 | |
149 | 149 | #ifdef CAIRO_SUPPORT |
309 | 309 | * Defines the colors to be used for the forthcoming draw_text calls. |
310 | 310 | * |
311 | 311 | */ |
312 | void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background) { | |
312 | void set_font_colors(xcb_gcontext_t gc, color_t foreground, color_t background) { | |
313 | 313 | assert(savedFont != NULL); |
314 | 314 | |
315 | 315 | switch (savedFont->type) { |
319 | 319 | case FONT_TYPE_XCB: { |
320 | 320 | /* Change the font and colors in the GC */ |
321 | 321 | uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; |
322 | uint32_t values[] = {foreground, background, savedFont->specific.xcb.id}; | |
322 | uint32_t values[] = {foreground.colorpixel, background.colorpixel, savedFont->specific.xcb.id}; | |
323 | 323 | xcb_change_gc(conn, gc, mask, values); |
324 | 324 | break; |
325 | 325 | } |
326 | 326 | #if PANGO_SUPPORT |
327 | 327 | case FONT_TYPE_PANGO: |
328 | 328 | /* Save the foreground font */ |
329 | pango_font_red = ((foreground >> 16) & 0xff) / 255.0; | |
330 | pango_font_green = ((foreground >> 8) & 0xff) / 255.0; | |
331 | pango_font_blue = (foreground & 0xff) / 255.0; | |
329 | pango_font_red = foreground.red; | |
330 | pango_font_green = foreground.green; | |
331 | pango_font_blue = foreground.blue; | |
332 | 332 | break; |
333 | 333 | #endif |
334 | 334 | default: |
132 | 132 | xcb_flush(restore_conn); |
133 | 133 | xcb_aux_sync(restore_conn); |
134 | 134 | |
135 | set_font_colors(state->gc, config.client.placeholder.text.colorpixel, config.client.placeholder.background.colorpixel); | |
135 | set_font_colors(state->gc, config.client.placeholder.text, config.client.placeholder.background); | |
136 | 136 | |
137 | 137 | Match *swallows; |
138 | 138 | int n = 0; |
140 | 140 | xcb_poly_fill_rectangle(conn, pixmap, pixmap_gc, 1, &inner); |
141 | 141 | |
142 | 142 | /* restore font color */ |
143 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
143 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
144 | 144 | |
145 | 145 | char *bt_colour = "#FFFFFF"; |
146 | 146 | if (backtrace_done < 0) |
151 | 151 | for (int i = 0; crash_text_i3strings[i] != NULL; ++i) { |
152 | 152 | /* fix the colour for the backtrace line when it finished */ |
153 | 153 | if (i == backtrace_string_index) |
154 | set_font_colors(pixmap_gc, get_colorpixel(bt_colour), get_colorpixel("#000000")); | |
154 | set_font_colors(pixmap_gc, draw_util_hex_to_color(bt_colour), draw_util_hex_to_color("#000000")); | |
155 | 155 | |
156 | 156 | draw_text(crash_text_i3strings[i], pixmap, pixmap_gc, NULL, |
157 | 157 | 8, 5 + i * font_height, width - 16); |
158 | 158 | |
159 | 159 | /* and reset the colour again for other lines */ |
160 | 160 | if (i == backtrace_string_index) |
161 | set_font_colors(pixmap_gc, get_colorpixel("#FFFFFF"), get_colorpixel("#000000")); | |
161 | set_font_colors(pixmap_gc, draw_util_hex_to_color("#FFFFFF"), draw_util_hex_to_color("#000000")); | |
162 | 162 | } |
163 | 163 | |
164 | 164 | /* Copy the contents of the pixmap to the real window */ |