console_engine icon indicating copy to clipboard operation
console_engine copied to clipboard

Bold pixels

Open jcornaz opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe.

I would like to add more depth to what is rendered, by using bold characters

Describe the solution you'd like

I would like to set some "pixel" to be rendered as bold. Maybe something like:

engine.set_pxl(1, 2, pixel::pxl_fg('Z', Color::Red).bold());

But I don't have much opinion on the API.

Describe alternatives you've considered

Aside using crosstem directly, I don't see how to achieve that via console_engine

Additional context

There might be other desirable styles such as italic, underline, etc.

jcornaz avatar Mar 11 '23 20:03 jcornaz

I have a quick-and-dirty proof-of-concept implementation in my fork. It has bold, italic, and underline working. WARNING: These changes break compatibility with existing code by changing or entirely replacing functions having to do with the struct Pixel, due to the new style data it holds.

ac-z avatar Dec 05 '23 04:12 ac-z

I won't mind a change with the Pixels because the design of this module is pretty bad imo, and the name is also quite not well suited for what it represents.

Such change could make into a 3.0 release, including deprecation notice in the current major version.
If the module name was changed, we can also create a mirror of the Pixel module using the new name and the new function so people migrating their code would just have to follow the deprecation notice and use the new struct before upgrading the major version.

EDIT: about your PoC implementation, is it possible to mix the styles ? (e.g. bold + underline)

VincentFoulon80 avatar Dec 05 '23 12:12 VincentFoulon80

EDIT: about your PoC implementation, is it possible to mix the styles ? (e.g. bold + underline)

Yes, of course. Each pixel contains a new Style struct, containing a Boolean for each attribute. In more recent commits I also implemented the optimization currently used for colors to detect whether the style needs to be changed from the previous pixel.

                    // we check if the last pixel is the same as the current one.
                    // if the color/attribute is the same, only print the character
                    // the less we write on the output the faster we'll get
                    // and additional characters for colors we already have set is
                    // time consuming
                    if current_bold != pixel.style.bold || first {
                        current_bold = pixel.style.bold;
                        if pixel.style.bold {
                            queue!(self.stdout, style::SetAttribute(style::Attribute::Bold)).unwrap(); 
                        } else {
                            // style::Attribute::NoBold is unreliable across terminals
                            // Use style::Attribute::Reset instead, process italics and underline
                            // afterwards to avoid resetting those attributes.
                            queue!(self.stdout, style::SetAttribute(style::Attribute::Reset)).unwrap();
                        }
                    }
                    if current_italic != pixel.style.italic || first {
                        current_italic = pixel.style.italic;
                        if pixel.style.italic {
                            queue!(self.stdout, style::SetAttribute(style::Attribute::Italic)).unwrap(); 
                        } else {
                            queue!(self.stdout, style::SetAttribute(style::Attribute::NoItalic)).unwrap();
                        }
                    }
                    if current_underline != pixel.style.underlined || first {
                        current_underline = pixel.style.underlined;
                        if pixel.style.underlined {
                            queue!(self.stdout, style::SetAttribute(style::Attribute::Underlined)).unwrap(); 
                        } else {
                            queue!(self.stdout, style::SetAttribute(style::Attribute::NoUnderline)).unwrap();
                        }
                    }
                    if current_colors != pixel.get_colors() || first {
                        current_colors = pixel.get_colors();
                        queue!(
                            self.stdout,
                            style::SetForegroundColor(pixel.fg),
                            style::SetBackgroundColor(pixel.bg),
                        ).unwrap();
                    }
                    first = false;
                    queue!(self.stdout, style::Print(pixel.chr)).unwrap();

Note that using Reset instead of NoBold is necessary for some terminals. At the current moment, I think there's a risk of accidentally clearing italics and underline for Pixels immediately after the last bold Pixel in a row.

ac-z avatar Dec 05 '23 16:12 ac-z