ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtfont.h
Revision: 1.43
Committed: Tue Jun 21 12:03:56 2016 UTC (7 years, 11 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: rxvt-unicode-rel-9_26, rxvt-unicode-rel-9_25
Changes since 1.42: +2 -2 lines
Log Message:
24-bit direct color support (patch by Fengguang Wu)

Support directly setting RGB fg/bg colors via ISO-8613-3 24-bit
ANSI color escapes:

  ESC[38;2;<r>;<g>;<b>m Select RGB foreground color
  ESC[48;2;<r>;<g>;<b>m Select RGB background color

The killer applications for me are vim in tmux. It'll not only modernize
their look and feeling, but also bring more eye friendly color schemes.
Very helpful for long time programmers.

To avoid memory overheads and keep the patch non-intrusive, it takes the
approach to adapt the nearest color in an hidden 6x6x4 (88-color mode)
or 7x7x5 (256-color mode) color cube to the new 24-bit RGB color.

The pros/cons are:

+) least memory footprint (close to 0)
   comparing to konsole, gnome-terminal etc. real 24-bit arrays

+) exact colors and excellent user feelings
   comparing to xterm, mlterm, etc. approximating to 256 palette

+) usable in both the existing 88/256-color modes

   Most vim GUI color schemes show up the same as gvim in rxvt-unicode's
   88-color mode, not to mention the 256-color mode. Typical applications
   only use one or two dozens of colors at the same time.

-) may not be able to show 2+ close 24-bit colors

   RGB colors close to each other will likely fall into the same slot in
   the 6x6x4 or 7x7x5 color cube. If necessary, it could be improved
   effectively by implementing some collision avoidance logic, trying to
   find empty/eldest slot in the +1/-1 r/g/b indices (ie. 3-8 neighbors).

The CPU overheads of map_rgb24_color() look ignorable: I feel no
perceptible slow down when doing vim operations in 24-bit color mode.

A micro benchmark running a test script from [1]:

% time (for i in {1..100}; do 24-bit-color.sh; done)

vanilla rxvt-unicode
====================
  2.42s user 1.88s system 31% cpu 13.555 total
  2.59s user 1.74s system 31% cpu 13.615 total
  2.46s user 1.85s system 31% cpu 13.631 total

THIS PATCH (adapt hidden color cube to 24-bit)
==============================================
  2.33s user 1.97s system 31% cpu 13.598 total
  2.46s user 1.89s system 31% cpu 13.613 total
  2.51s user 1.82s system 31% cpu 13.556 total

https://github.com/spudowiar/rxvt-unicode (real 24-bit array)
=============================================================
  2.61s user 1.75s system 31% cpu 13.721 total
  2.48s user 1.82s system 31% cpu 13.566 total
  2.60s user 1.76s system 31% cpu 13.631 total

USE_256_COLORS is defined in all the above rxvt-unicode builds.

References:

[1] True Colour (16 million colours) support in various terminal
    applications and terminals
    https://gist.github.com/XVilka/8346728

[2] https://en.wikipedia.org/wiki/ANSI_escape_code#Colors

File Contents

# Content
1 #ifndef DEFAULTFONT_H_
2 #define DEFAULTFONT_H_
3
4 #include <X11/Xlib.h>
5 #if XFT
6 # include <X11/Xft/Xft.h>
7 #endif
8
9 #include <inttypes.h>
10
11 #include "encoding.h"
12 #include "rxvtutil.h"
13 #include "rxvttoolkit.h"
14
15 struct rxvt_term;
16
17 struct rxvt_fontprop
18 {
19 enum {
20 unset = -1,
21 medium = 100, bold = 200,
22 roman = 0, italic = 100,
23 };
24 int width, height, ascent;
25 int weight, slant;
26 };
27
28 struct rxvt_font
29 {
30 // managed by the fontset
31 rxvt_term *term;
32 void set_term (rxvt_term *term) { this->term = term; }
33
34 char *name;
35 codeset cs;
36 bool loaded; // whether we tried loading it before (not whether it's loaded)
37
38 // managed by the font object
39 int ascent, descent,
40 width, height;
41
42 void set_name (char *name_);
43
44 rxvt_font ();
45 virtual ~rxvt_font () { free (name); };
46
47 virtual void clear () { };
48
49 void clear_rect (rxvt_drawable &d, int x, int y, int w, int h, int color) const;
50
51 virtual rxvt_fontprop properties () = 0;
52
53 virtual bool load (const rxvt_fontprop &morph, bool force_prop) = 0;
54 virtual bool has_char (uint32_t unicode, const rxvt_fontprop *prop, bool &careful) const = 0;
55
56 virtual void draw (rxvt_drawable &d,
57 int x, int y,
58 const text_t *text, int len,
59 int fg, int bg) = 0;
60
61 void unref ()
62 {
63 clear ();
64 delete this;
65 }
66 };
67
68 struct rxvt_fallback_font;
69
70 struct rxvt_fontset
71 {
72 char *fontdesc;
73
74 // must be power-of-two - 1, also has to match RS_fontMask in rxvt.h
75 #if USE_256_COLORS
76 enum { fontCount = 7 }; // 2 extra colors bits, 2 fewer fontcount bits
77 #else
78 enum { fontCount = 31 };
79 #endif
80
81 // index of first font in set
82 enum { firstFont = 2 };
83
84 rxvt_fontset (rxvt_term *term);
85 ~rxvt_fontset ();
86
87 bool populate (const char *desc);
88 void set_prop (const rxvt_fontprop &prop, bool force_prop) { this->prop = prop; this->force_prop = force_prop; }
89 int find_font_idx (uint32_t unicode);
90 int find_font (const char *name) const;
91 bool realize_font (int i);
92
93 rxvt_font *operator [] (int id) const
94 {
95 return fonts[id >> 1];
96 }
97
98 int
99 find_font (unicode_t unicode)
100 {
101 return min<int> ((fontCount << 1) | 1, find_font_idx (unicode));
102 }
103
104 private:
105 rxvt_term *term;
106 rxvt_fontprop prop;
107 bool force_prop;
108 simplevec<rxvt_font *> fonts;
109 const rxvt_fallback_font *fallback;
110
111 // this once was a "typedef xxx pagemap[256]
112 // but c++ arrays are not normal types, and cannot be
113 // put into containers, new doesn't work for them etc. etc.
114 // so we wrap out array into an object that acts like one. doh.
115 // example: C++ has no separate new and new [] forms,
116 // and if pagemap is char[256], new incorrectly assumes we want to
117 // allocate an array of chars instead of a single pagemap.
118 struct pagemap
119 {
120 unsigned char cppsucks[256];
121 unsigned char &operator [](int i) { return cppsucks [i]; };
122 };
123 vector<pagemap *> fmap;
124
125 void clear ();
126 rxvt_font *new_font (const char *name, codeset cs);
127 void prepare_font (rxvt_font *font, codeset cs);
128 void add_fonts (const char *desc);
129 void push_font (rxvt_font *font);
130 };
131
132 #endif /* _DEFAULTFONT_H_ */
133