libnotcurses_sys/cell/
mod.rs

1//! `NcCell`
2
3// functions already exported by bindgen : 5
4// -----------------------------------------
5// (W) wrap: 4
6// (#) test: 3
7// ------------------------------------------
8//W  nccell_extended_gcluster
9//W# nccell_load
10//W# nccell_duplicate
11//W# nccell_release
12//   ncstrwidth_valid
13//
14// functions manually reimplemented: 50
15// ------------------------------------------
16// (X) wont:  2
17// (+) done: 48
18// (W) wrap: 44
19// (#) test: 30
20// ------------------------------------------
21//W# nccell_bg_alpha
22//W# nccell_bg_default_p
23//W# nccell_bg_palindex
24//W# nccell_bg_palindex_p
25//W# nccell_bg_rgb
26// # nccell_bg_rgb8               // unneeded method
27//W+ nccell_channels
28//W+ nccell_cols
29//W+ nccell_double_wide_p
30//W# nccell_extract
31//W# nccell_fchannel
32//W# nccell_fg_alpha
33//W# nccell_fg_default_p
34//W# nccell_fg_palindex
35//W# nccell_fg_palindex_p
36//W# nccell_fg_rgb
37// # nccell_fg_rgb8               // unneeded method
38//W# nccell_init
39//W# nccell_load_char
40//W+ nccell_off_styles
41//W+ nccell_on_styles
42//W# nccell_prime
43//W# nccell_set_bchannel
44//W# nccell_set_bg_alpha
45//W# nccell_set_bg_default
46//W# nccell_set_bg_palindex
47//W# nccell_set_bg_rgb
48// # nccell_set_bg_rgb8           // unneeded method
49// X nccell_set_bg_rgb8_clipped   // unneeded
50//W+ nccell_set_channels
51//W# nccell_set_fchannel
52//W# nccell_set_fg_alpha
53//W# nccell_set_fg_default
54//W# nccell_set_fg_palindex
55//W# nccell_set_fg_rgb
56// # nccell_set_fg_rgb8           // unneeded method
57// X nccell_set_fg_rgb8_clipped   // unneeded
58//W+ nccell_set_styles
59//W+ nccell_strdup
60//W# nccell_styles
61//W+ nccell_wide_left_p
62//W+ nccell_wide_right_p
63//W+ nccellcmp
64//W+ nccells_ascii_box
65//W+ nccells_double_box
66//W+ nccells_rounded_box
67//W+ nccells_heavy_box
68//W+ nccells_light_box
69//W+ nccells_load_box
70// + ncstrwidth
71
72#[cfg(test)]
73mod test;
74
75mod methods;
76pub(crate) mod reimplemented;
77
78// NcCell
79/// A coordinate on an [`NcPlane`][crate::NcPlane] storing 128 bits of data.
80///
81/// # Methods & Associated Functions
82///
83/// - [Constructors & Destructors](#nccell-constructors-and-destructors)
84///
85/// - [bg|fg `NcChannel`s manipulation](#nccell-methods-bgfg-ncchannels-manipulation)
86/// - [Other components](#nccell-methods-other-components)
87/// - [Text](#nccell-methods-text)
88///
89/// # Description
90///
91/// An `NcCell` corresponds to a single character cell on some `NcPlane`,
92/// which can be occupied by a single `EGC` grapheme cluster (some root
93/// spacing glyph, along with possible combining characters, which might span
94/// multiple columns).
95///
96/// An `NcCell` is bounded to an `NcPlane`, but the cell doesn't store anything
97/// about the plane.
98///
99/// At any `NcCell`, we can have a theoretically arbitrarily long UTF-8 string,
100/// a foreground color, a background color, and an [`NcStyle`][crate::NcStyle] attribute set.
101///
102/// Valid grapheme cluster contents include:
103///
104/// - A NUL terminator,
105/// - A single [control character](https://en.wikipedia.org/wiki/Control_character),
106///   followed by a NUL terminator,
107/// - At most one [spacing
108/// character](https://en.wikipedia.org/wiki/Graphic_character#Spacing_character),
109///   followed by zero or more nonspacing characters, followed by a NUL terminator.
110///
111/// ## Diagram
112///
113/// ```txt
114/// `NcCell`: 128 bits structure comprised of the following 5 elements:
115///
116/// GCLUSTER|GCLUSTER|GCLUSTER|GCLUSTER  1. `EGC`
117/// 00000000║WWWWWWWW║11111111|11111111  2. backstop + 3. width + 4. `NcStyle`
118/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB  5. `NcChannels`
119/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB     "
120///
121/// 1. (32b) Extended Grapheme Cluster, presented either as:
122///
123///     1.1. An EGC of up to 4 bytes:
124///     UUUUUUUU|UUUUUUUU|UUUUUUUU|UUUUUUUU
125///
126///     1.2. A `0x01` in the first byte, plus 3 bytes with a 24b address to an egcpool:
127///     00000001|IIIIIIII|IIIIIIII|IIIIIIII
128///
129/// 2. (8b) backstop (zero)
130/// 00000000
131///
132/// 3. (8b) column width
133/// WWWWWWWW
134///
135/// 4. (16b) `NcStyle`
136/// 11111111 11111111
137///
138/// 5. (64b) `NcChannels`
139/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB║~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
140/// ```
141///
142/// `type in C: cell (struct)`
143///
144/// # More `NcCell` Information
145///
146/// ## Size
147///
148/// Multi-column characters can only have a single style/color throughout.
149/// [`wcwidth()`](https://www.man7.org/linux/man-pages/man3/wcwidth.3.html)
150/// is not reliable. It's just quoting whether or not the `EGC`
151/// contains a "Wide Asian" double-width character.
152/// This is set for some things, like most emoji, and not set for
153/// other things, like cuneiform.
154///
155/// Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
156/// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
157/// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
158/// such large pools are unlikely in common use.
159///
160/// ## Alpha Compositing
161///
162/// We implement some small alpha compositing. Foreground and background both
163/// have two bits of inverted alpha. The actual grapheme written to a cell is
164/// the topmost non-zero grapheme.
165///
166/// - If its alpha is 00
167///   ([`NcAlpha::OPAQUE`][crate::NcAlpha#associatedconstant.OPAQUE])
168///   its foreground color is used unchanged.
169///
170/// - If its alpha is 10
171///   ([`NcAlpha::TRANSPARENT`][crate::NcAlpha#associatedconstant.TRANSPARENT])
172///   its foreground color is derived
173///   entirely from cells underneath it.
174///
175/// - If its alpha is 01
176///   ([`NcAlpha::BLEND`][crate::NcAlpha#associatedconstant.BLEND])
177///   the result will be a composite.
178///
179/// Likewise for the background. If the bottom of a coordinate's zbuffer is
180/// reached with a cumulative alpha of zero, the default is used. In this way,
181/// a terminal configured with transparent background can be supported through
182/// multiple occluding ncplanes.
183///
184/// A foreground alpha of 11
185/// ([`NcAlpha::HIGHCONTRAST`][crate::NcAlpha#associatedconstant.HIGHCONTRAST])
186/// requests high-contrast text (relative to the computed background).
187/// A background alpha of 11 is currently forbidden.
188///
189/// ## Precedence
190///
191/// - Default color takes precedence over palette or RGB, and cannot be used with
192///   transparency.
193/// - Indexed palette takes precedence over RGB. It cannot meaningfully set
194///   transparency, but it can be mixed into a cascading color.
195/// - RGB is used if neither default terminal colors nor palette indexing are in
196///   play, and fully supports all transparency options.
197///
198/// ## Column width *(WIP)*
199///
200/// See [USAGE.md][0]
201///
202/// [0]: https://github.com/dankamongmen/notcurses/blob/master/USAGE.md#cells
203///
204/// We store the column width in this field. for a multicolumn EGC of N
205/// columns, there will be N nccells, and each has a width of N...for now.
206/// eventually, such an EGC will set more than one subsequent cell to
207/// WIDE_RIGHT, and this won't be necessary. it can then be used as a
208/// bytecount. see #1203. FIXME iff width >= 2, the cell is part of a
209/// multicolumn glyph. whether a cell is the left or right side of the glyph
210/// can be determined by checking whether ->gcluster is zero.
211///
212pub type NcCell = crate::c_api::ffi::nccell;
213
214// RETHINK:
215//
216// NcEgc
217//
218// /// Extended Grapheme Cluster. A unicode string of length 1.
219// ///
220// /// This 32 bit char, together with the associated plane's associated egcpool,
221// /// completely define this cell's `NcEgc`. Unless the `NcEgc` requires more than
222// /// four bytes to encode as UTF-8, it will be inlined here:
223// ///
224// /// ## Diagram 1
225// ///
226// /// ```txt
227// /// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
228// /// extended grapheme cluster <= 4bytes
229// /// ```
230// ///
231// /// `type in C: uint32_t`
232// ///
233// /// If more than four bytes are required, it will be spilled into the egcpool.
234// /// In either case, there's a NUL-terminated string available without copying,
235// /// because (1) the egcpool is all NUL-terminated sequences and (2) the fifth
236// /// byte of this struct (the backstop field) is guaranteed to be zero, as are
237// /// any unused bytes in gcluster.
238// ///
239// /// A spilled `NcEgc` is indicated by the value `0x01iiiiii`. This cannot alias a
240// /// true supra-ASCII NcEgc, because UTF-8 only encodes bytes <= 0x80 when they
241// /// are single-byte ASCII-derived values. The `iiiiii` is interpreted as a 24-bit
242// /// index into the egcpool (which may thus be up to 16MB):
243// ///
244// /// ## Diagram 2
245// ///
246// /// ```txt
247// /// 00000001 iiiiiiii iiiiiiii iiiiiiii
248// ///   sign     24bit index to egcpool
249// /// ```
250// /// `type in C: uint32_t`
251// ///
252// /// The cost of this scheme is that the character 0x01 (`SOH`) cannot be encoded
253// /// in a cell, and therefore it must not be allowed through the API.
254// ///
255// /// -----
256// /// Note that even if the `NcEgc` is <= 4 bytes and inlined, is still interpreted as
257// /// a NUL-terminated char * (technically, &cell->gcluster is treated as a char*).
258// /// If it is more than 4 bytes, cell->gcluster has a first byte of 0x01,
259// /// and the remaining 24 bits are an index into the plane's egcpool,
260// /// which is carved into NUL-terminated chunks of arbitrary length.
261// ///
262// /// ## Links
263// ///
264// /// - [Grapheme Cluster
265// /// Boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
266// ///
267// ///
268// FIXME: should be an utf-8 string len 1 of type &str.
269// pub type NcEgc = String;
270// pub type NcEgc<'a> = &'a str;