Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transparent blitter stacking #1317

Merged
merged 16 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: debian-unstable

steps:
- name: debian-build
image: dankamongmen/unstable_builder:2021-01-02a
image: dankamongmen/unstable_builder:2021-02-01a
commands:
- export LANG=en_US.UTF-8
- mkdir build
Expand Down Expand Up @@ -66,7 +66,7 @@ name: ubuntu-focal

steps:
- name: ubuntu-build
image: dankamongmen/hirsute:2021-01-02a
image: dankamongmen/hirsute:2021-02-01a
commands:
- export LANG=es_ES.UTF-8
- mkdir build
Expand Down
25 changes: 20 additions & 5 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1601,11 +1601,22 @@ manner.
// characters, followed by a NUL terminator.
//
// Multi-column characters can only have a single style/color throughout.
// Existence is suffering, and thus wcwidth() is not reliable. It's just
// quoting whether or not the EGC contains a "Wide Asian" double-width
// character. This is set for some things, like most emoji, and not set for
// other things, like cuneiform. True display width is a *function of the
// font and terminal*. Among the longest Unicode codepoints is
//
// U+FDFD ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM ﷽
//
// wcwidth() rather optimistically claims this most exalted glyph to occupy
// a single column. BiDi text is too complicated for me to even get into here.
// Be assured there are no easy answers; ours is indeed a disturbing Universe.
//
// Each nccell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
// Dynamic requirements can add up to 16MB to an ncplane, but such large pools
// are unlikely in common use.
// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
// such large pools are unlikely in common use.
//
// We implement some small alpha compositing. Foreground and background both
// have two bits of inverted alpha. The actual grapheme written to a cell is
Expand All @@ -1624,6 +1635,9 @@ manner.
// meaningfully set transparency, but it can be mixed into a cascading color.
// RGB is used if neither default terminal colors nor palette indexing are in
// play, and fully supports all transparency options.
//
// This structure is exposed only so that most functions can be inlined. Do not
// directly modify or access the fields of this structure; use the API.
typedef struct nccell {
// These 32 bits, together with the associated plane's associated egcpool,
// completely define this cell's EGC. Unless the EGC requires more than four
Expand Down Expand Up @@ -1665,12 +1679,13 @@ typedef struct nccell {
// can be determined by checking whether ->gcluster is zero.
uint8_t width; // 1B → 6B (8 bits of EGC column width)
uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes)
// (channels & 0x8000000000000000ull): reserved, must be 0
// (channels & 0x8000000000000000ull): blitted to upper-left quadrant
// (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0800000000000000ull): foreground uses palette index
// (channels & 0x0400000000000000ull): glyph is entirely foreground
// (channels & 0x0300000000000000ull): reserved, must be 0
// (channels & 0x0400000000000000ull): blitted to upper-right quadrant
// (channels & 0x0200000000000000ull): blitted to lower-left quadrant
// (channels & 0x0100000000000000ull): blitted to lower-right quadrant
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0000000080000000ull): reserved, must be 0
// (channels & 0x0000000040000000ull): background is *not* "default color"
Expand Down
1 change: 1 addition & 0 deletions doc/man/man3/notcurses_render.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,6 @@ purposes of color blending.
**notcurses_plane(3)**,
**notcurses_refresh(3)**,
**notcurses_stats(3)**,
**notcurses_visual(3)**,
**console_codes(4)**,
**utf-8(7)**
39 changes: 37 additions & 2 deletions doc/man/man3/notcurses_visual.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,39 @@ The different **ncblitter_e** values select from among available glyph sets:
* **NCBLIT_SIXEL**: Not yet implemented.

**NCBLIT_4x1** and **NCBLIT_8x1** are intended for use with plots, and are
not really applicable for general visuals.
not really applicable for general visuals. **NCBLIT_BRAILLE** doesn't tend
to work out very well for images, but (depending on the font) can be very
good for plots.

In the absence of scaling, for a given set of pixels, more rows and columns in
the blitter will result in a smaller output image. An image rendered with
**NCBLIT_1x1** will be twice as tall as the same image rendered with
**NCBLIT_2x1**, which will be twice as wide as the same image rendered with
**NCBLIT_2x2**. The same image rendered with **NCBLIT_3x2** will be one-third
as tall and one-half as wide as the original **NCBLIT_1x1** render (again, this
depends on **NCSCALE_NONE**). If the output size is held constant (using for
instance **NCSCALE_SCALE_HIRES** and a large image), more rows and columns will
result in more effective resolution.

Assuming a cell is twice as tall as it is wide, **NCBLIT_1x1** (and indeed
any NxN blitter) will stretch an image by a factor of 2 in the vertical
dimension. **NCBLIT_2x1** will not distort the image whatsoever, as it maps a
vector two pixels high and one pixel wide to a single cell. **NCBLIT_3x2** will
stretch an image by a factor of 1.5.

The cell's dimension in pixels is ideally evenly divisible by the blitter
geometry. If **NCBLIT_3x2** is used together with a cell 8 pixels wide and
14 pixels tall, two of the vertical segments will be 5 pixels tall, while one
will be 4 pixels tall. Such unequal distributions are more likely with larger
blitter geometries. Likewise, there are only ever two colors available to us in
a given cell. **NCBLIT_1x1** and **NCBLIT_2x2** can be perfectly represented
with two colors per cell. Blitters of higher geometry are increasingly likely
to require some degree of interpolation. Transparency is always honored with
complete fidelity.

Finally, rendering operates slightly differently when two planes have both been
blitted, and one lies atop the other. See **notcurses_render(3)** for more
information.

# RETURN VALUES

Expand Down Expand Up @@ -210,11 +242,14 @@ radians for **rads**, but this will change soon.
among terminals.

Bad font support can ruin **NCBLIT_2x2**, **NCBLIT_3x2**, **NCBLIT_4x1**,
**NCBLIT_BRAILLE**, and **NCBLIT_8x1**.
**NCBLIT_BRAILLE**, and **NCBLIT_8x1**. Braille glyphs ought ideally draw only
the raised dots, rather than drawing all eight dots with two different styles.
It's often best for the emulator to draw these glyphs itself.

# SEE ALSO

**notcurses(3)**,
**notcurses_capabilities(3)**,
**notcurses_plane(3)**,
**notcurses_render(3)**,
**utf-8(7)**
15 changes: 9 additions & 6 deletions include/notcurses/notcurses.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ API int notcurses_ucs32_to_utf8(const char32_t* ucs32, unsigned ucs32count,
#define CELL_ALPHA_BLEND 0x10000000ull
#define CELL_ALPHA_OPAQUE 0x00000000ull

#define CELL_NOBACKGROUND_MASK 0x0400000000000000ull
// if this bit is set, we are *not* using the default background color
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull
// if this bit is set, we are *not* using the default foreground color
Expand Down Expand Up @@ -548,6 +547,9 @@ channels_set_bg_default(uint64_t* channels){
// meaningfully set transparency, but it can be mixed into a cascading color.
// RGB is used if neither default terminal colors nor palette indexing are in
// play, and fully supports all transparency options.
//
// This structure is exposed only so that most functions can be inlined. Do not
// directly modify or access the fields of this structure; use the API.
typedef struct nccell {
// These 32 bits, together with the associated plane's associated egcpool,
// completely define this cell's EGC. Unless the EGC requires more than four
Expand Down Expand Up @@ -589,19 +591,20 @@ typedef struct nccell {
// can be determined by checking whether ->gcluster is zero.
uint8_t width; // 1B → 6B (8 bits of EGC column width)
uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes)
// (channels & 0x8000000000000000ull): reserved, must be 0
// (channels & 0x8000000000000000ull): blitted to upper-left quadrant
// (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0800000000000000ull): foreground uses palette index
// (channels & 0x0400000000000000ull): glyph is entirely foreground
// (channels & 0x0300000000000000ull): reserved, must be 0
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb)
// (channels & 0x0400000000000000ull): blitted to upper-right quadrant
// (channels & 0x0200000000000000ull): blitted to lower-left quadrant
// (channels & 0x0100000000000000ull): blitted to lower-right quadrant
// (channels & 0x00ffffff00000000ull): foreground in 3x8 RGB (rrggbb) / pindex
// (channels & 0x0000000080000000ull): reserved, must be 0
// (channels & 0x0000000040000000ull): background is *not* "default color"
// (channels & 0x0000000030000000ull): background alpha (2 bits)
// (channels & 0x0000000008000000ull): background uses palette index
// (channels & 0x0000000007000000ull): reserved, must be 0
// (channels & 0x0000000000ffffffull): background in 3x8 RGB (rrggbb)
// (channels & 0x0000000000ffffffull): background in 3x8 RGB (rrggbb) / pindex
// At render time, these 24-bit values are quantized down to terminal
// capabilities, if necessary. There's a clear path to 10-bit support should
// we one day need it, but keep things cagey for now. "default color" is
Expand Down
1 change: 0 additions & 1 deletion rust/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub use ffi::{
// CELL_FG_ALPHA_MASK,
// CELL_FG_PALETTE,
// CELL_FG_RGB_MASK,
// CELL_NOBACKGROUND_MASK,

#[doc(inline)]
pub use ffi::{
Expand Down
5 changes: 0 additions & 5 deletions rust/src/cells/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,6 @@ pub const NCCELL_FG_PALETTE: u64 = crate::bindings::ffi::CELL_FG_PALETTE;
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_RGB_MASK`];
pub const NCCELL_FG_RGB_MASK: u64 = crate::bindings::ffi::CELL_FG_RGB_MASK;

/// Indicates the glyph is entirely foreground
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::ffi::CELL_NOBACKGROUND_MASK;

// NcEgc
//
/// Extended Grapheme Cluster. A 32-bit [`char`]-like type
Expand Down
1 change: 0 additions & 1 deletion rust/src/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ pub type NcAlphaBits = u32;
/// - [`NCCELL_FG_ALPHA_MASK`][crate::NCCELL_FG_ALPHA_MASK]
/// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE]
/// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK]
/// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK]
///
pub type NcChannelPair = u64;

Expand Down
11 changes: 8 additions & 3 deletions src/demo/intro.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,16 @@ int intro(struct notcurses* nc){
}
}
ncplane_off_styles(ncp, NCSTYLE_BOLD);
const wchar_t wstr[] = L"▏▁ ▂ ▃ ▄ ▅ ▆ ▇ █ █ ▇ ▆ ▅ ▄ ▃ ▂ ▁▕";
if(ncplane_putwstr_aligned(ncp, rows / 2 - 6, NCALIGN_CENTER, wstr) < 0){
const wchar_t nwstr[] = L"▏▁ ▂ ▃ ▄ ▅ ▆ ▇ █ █ ▇ ▆ ▅ ▄ ▃ ▂ ▁▕";
if(ncplane_putwstr_aligned(ncp, rows / 2 - 6, NCALIGN_CENTER, nwstr) < 0){
return -1;
}
const wchar_t iwstr[] = L"▏█ ▇ ▆ ▅ ▄ ▃ ▂ ▁ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █▕";
const wchar_t* iwstr;
if(notcurses_cansextant(nc)){
iwstr = L"▏▔ 🮂 🮃 ▀ 🮄 🮅 🮆 █ █ 🮆 🮅 🮄 ▀ 🮃 🮂 ▔▕";
}else{
iwstr = L"▏█ ▇ ▆ ▅ ▄ ▃ ▂ ▁ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █▕";
}
if(ncplane_putwstr_aligned(ncp, rows / 2 + 1, NCALIGN_CENTER, iwstr) < 0){
return -1;
}
Expand Down