diff options
| author | Po Lu | 2022-02-10 18:43:08 +0800 |
|---|---|---|
| committer | Po Lu | 2022-02-10 18:45:35 +0800 |
| commit | e16a78c44e05237b98207a7cee4b0666b7e1ac2a (patch) | |
| tree | 851dcf0a3fe04ef08560a57d75bff802ca3bd7a2 /src | |
| parent | 849895d0db9c8879dedd6658f66b28b1613358ff (diff) | |
| download | emacs-e16a78c44e05237b98207a7cee4b0666b7e1ac2a.tar.gz emacs-e16a78c44e05237b98207a7cee4b0666b7e1ac2a.zip | |
Correctly allocate colors in xftfont
* src/xftfont.c (struct xftface_info): New fields
`bg_allocated_p' and `fg_allocated_p'.
(xftfont_get_colors): Actually allocate colors and tell the
caller whether colors were allocated.
(xftfont_prepare_face): Set allocated fields.
(xftfont_done_face):
(xftfont_draw): Free colors that were allocated.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xftfont.c | 71 |
1 files changed, 64 insertions, 7 deletions
diff --git a/src/xftfont.c b/src/xftfont.c index 6a2b2086df8..e27c6cf3146 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -49,19 +49,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 49 | 49 | ||
| 50 | struct xftface_info | 50 | struct xftface_info |
| 51 | { | 51 | { |
| 52 | bool bg_allocated_p; | ||
| 53 | bool fg_allocated_p; | ||
| 52 | XftColor xft_fg; /* color for face->foreground */ | 54 | XftColor xft_fg; /* color for face->foreground */ |
| 53 | XftColor xft_bg; /* color for face->background */ | 55 | XftColor xft_bg; /* color for face->background */ |
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| 56 | /* Setup foreground and background colors of GC into FG and BG. If | 58 | /* Setup foreground and background colors of GC into FG and BG. If |
| 57 | XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG | 59 | XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG |
| 58 | may be NULL. */ | 60 | may be NULL. Return whether or not colors were allocated in |
| 61 | BG_ALLOCATED_P and FG_ALLOCATED_P. */ | ||
| 59 | 62 | ||
| 60 | static void | 63 | static void |
| 61 | xftfont_get_colors (struct frame *f, struct face *face, GC gc, | 64 | xftfont_get_colors (struct frame *f, struct face *face, GC gc, |
| 62 | struct xftface_info *xftface_info, | 65 | struct xftface_info *xftface_info, |
| 63 | XftColor *fg, XftColor *bg) | 66 | XftColor *fg, XftColor *bg, |
| 67 | bool *bg_allocated_p, bool *fg_allocated_p) | ||
| 64 | { | 68 | { |
| 69 | *bg_allocated_p = false; | ||
| 70 | *fg_allocated_p = false; | ||
| 71 | |||
| 65 | if (xftface_info && face->gc == gc) | 72 | if (xftface_info && face->gc == gc) |
| 66 | { | 73 | { |
| 67 | *fg = xftface_info->xft_fg; | 74 | *fg = xftface_info->xft_fg; |
| @@ -94,20 +101,39 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc, | |||
| 94 | { | 101 | { |
| 95 | XColor colors[2]; | 102 | XColor colors[2]; |
| 96 | 103 | ||
| 97 | colors[0].pixel = fg->pixel = xgcv.foreground; | 104 | colors[0].pixel = xgcv.foreground; |
| 98 | if (bg) | 105 | if (bg) |
| 99 | colors[1].pixel = bg->pixel = xgcv.background; | 106 | colors[1].pixel = xgcv.background; |
| 100 | x_query_colors (f, colors, bg ? 2 : 1); | 107 | x_query_colors (f, colors, bg ? 2 : 1); |
| 101 | fg->color.alpha = 0xFFFF; | 108 | fg->color.alpha = 0xFFFF; |
| 102 | fg->color.red = colors[0].red; | 109 | fg->color.red = colors[0].red; |
| 103 | fg->color.green = colors[0].green; | 110 | fg->color.green = colors[0].green; |
| 104 | fg->color.blue = colors[0].blue; | 111 | fg->color.blue = colors[0].blue; |
| 112 | |||
| 113 | if (!XftColorAllocValue (FRAME_X_DISPLAY (f), | ||
| 114 | FRAME_X_VISUAL (f), | ||
| 115 | FRAME_X_COLORMAP (f), | ||
| 116 | &fg->color, fg)) | ||
| 117 | /* This color should've been allocated when creating the | ||
| 118 | GC. */ | ||
| 119 | emacs_abort (); | ||
| 120 | else | ||
| 121 | *fg_allocated_p = true; | ||
| 122 | |||
| 105 | if (bg) | 123 | if (bg) |
| 106 | { | 124 | { |
| 107 | bg->color.alpha = 0xFFFF; | 125 | bg->color.alpha = 0xFFFF; |
| 108 | bg->color.red = colors[1].red; | 126 | bg->color.red = colors[1].red; |
| 109 | bg->color.green = colors[1].green; | 127 | bg->color.green = colors[1].green; |
| 110 | bg->color.blue = colors[1].blue; | 128 | bg->color.blue = colors[1].blue; |
| 129 | |||
| 130 | if (!XftColorAllocValue (FRAME_X_DISPLAY (f), | ||
| 131 | FRAME_X_VISUAL (f), | ||
| 132 | FRAME_X_COLORMAP (f), | ||
| 133 | &bg->color, bg)) | ||
| 134 | emacs_abort (); | ||
| 135 | else | ||
| 136 | *bg_allocated_p = true; | ||
| 111 | } | 137 | } |
| 112 | } | 138 | } |
| 113 | unblock_input (); | 139 | unblock_input (); |
| @@ -360,9 +386,12 @@ xftfont_prepare_face (struct frame *f, struct face *face) | |||
| 360 | } | 386 | } |
| 361 | #endif | 387 | #endif |
| 362 | 388 | ||
| 363 | xftface_info = xmalloc (sizeof *xftface_info); | 389 | xftface_info = xzalloc (sizeof *xftface_info); |
| 364 | xftfont_get_colors (f, face, face->gc, NULL, | 390 | xftfont_get_colors (f, face, face->gc, NULL, |
| 365 | &xftface_info->xft_fg, &xftface_info->xft_bg); | 391 | &xftface_info->xft_fg, |
| 392 | &xftface_info->xft_bg, | ||
| 393 | &xftface_info->bg_allocated_p, | ||
| 394 | &xftface_info->fg_allocated_p); | ||
| 366 | face->extra = xftface_info; | 395 | face->extra = xftface_info; |
| 367 | } | 396 | } |
| 368 | 397 | ||
| @@ -381,6 +410,18 @@ xftfont_done_face (struct frame *f, struct face *face) | |||
| 381 | xftface_info = (struct xftface_info *) face->extra; | 410 | xftface_info = (struct xftface_info *) face->extra; |
| 382 | if (xftface_info) | 411 | if (xftface_info) |
| 383 | { | 412 | { |
| 413 | if (xftface_info->fg_allocated_p) | ||
| 414 | XftColorFree (FRAME_X_DISPLAY (f), | ||
| 415 | FRAME_X_VISUAL (f), | ||
| 416 | FRAME_X_COLORMAP (f), | ||
| 417 | &xftface_info->xft_fg); | ||
| 418 | |||
| 419 | if (xftface_info->bg_allocated_p) | ||
| 420 | XftColorFree (FRAME_X_DISPLAY (f), | ||
| 421 | FRAME_X_VISUAL (f), | ||
| 422 | FRAME_X_COLORMAP (f), | ||
| 423 | &xftface_info->xft_bg); | ||
| 424 | |||
| 384 | xfree (xftface_info); | 425 | xfree (xftface_info); |
| 385 | face->extra = NULL; | 426 | face->extra = NULL; |
| 386 | } | 427 | } |
| @@ -469,13 +510,16 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 469 | XftDraw *xft_draw = xftfont_get_xft_draw (f); | 510 | XftDraw *xft_draw = xftfont_get_xft_draw (f); |
| 470 | FT_UInt *code; | 511 | FT_UInt *code; |
| 471 | XftColor fg, bg; | 512 | XftColor fg, bg; |
| 513 | bool bg_allocated_p, fg_allocated_p; | ||
| 472 | int len = to - from; | 514 | int len = to - from; |
| 473 | int i; | 515 | int i; |
| 474 | 516 | ||
| 475 | if (s->font == face->font) | 517 | if (s->font == face->font) |
| 476 | xftface_info = (struct xftface_info *) face->extra; | 518 | xftface_info = (struct xftface_info *) face->extra; |
| 477 | xftfont_get_colors (f, face, s->gc, xftface_info, | 519 | xftfont_get_colors (f, face, s->gc, xftface_info, |
| 478 | &fg, with_background ? &bg : NULL); | 520 | &fg, with_background ? &bg : NULL, |
| 521 | &bg_allocated_p, &fg_allocated_p); | ||
| 522 | |||
| 479 | if (s->num_clips > 0) | 523 | if (s->num_clips > 0) |
| 480 | XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); | 524 | XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); |
| 481 | else | 525 | else |
| @@ -550,6 +594,19 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, | |||
| 550 | FRAME_X_DRAWABLE in order to draw: we cached the drawable in the | 594 | FRAME_X_DRAWABLE in order to draw: we cached the drawable in the |
| 551 | XftDraw structure. */ | 595 | XftDraw structure. */ |
| 552 | x_mark_frame_dirty (f); | 596 | x_mark_frame_dirty (f); |
| 597 | |||
| 598 | if (bg_allocated_p) | ||
| 599 | XftColorFree (FRAME_X_DISPLAY (f), | ||
| 600 | FRAME_X_VISUAL (f), | ||
| 601 | FRAME_X_COLORMAP (f), | ||
| 602 | &bg); | ||
| 603 | |||
| 604 | if (fg_allocated_p) | ||
| 605 | XftColorFree (FRAME_X_DISPLAY (f), | ||
| 606 | FRAME_X_VISUAL (f), | ||
| 607 | FRAME_X_COLORMAP (f), | ||
| 608 | &fg); | ||
| 609 | |||
| 553 | unblock_input (); | 610 | unblock_input (); |
| 554 | return len; | 611 | return len; |
| 555 | } | 612 | } |