devela/media/image/sixel/output/mod.rs
1// devela::media::image::sixel::output
2//
3//! Defines private [`SixelNode`], [`SixelOutput`].
4//
5// TOC
6// - SixelNode
7// - SixelOutput
8// - impl SixelOutput
9//
10// TODO: NEED:
11
12use crate::{IoWrite, String, Vec};
13
14mod enums; // RETHINK relocate
15mod pixel_format; // PixelFormat
16mod tosixel;
17pub use enums::*;
18pub use pixel_format::*;
19
20/// Represents a single sixel tile with color and spatial properties.
21///
22/// Holds the palette index, x-coordinates, and a map of color data
23/// for efficient rendering of individual sixel tiles.
24///
25/// # Adaptation
26/// - Derived from `sixel_node` struct in the `libsixel` C library.
27#[derive(Debug, Default, PartialEq, Eq, Hash)]
28pub(crate) struct SixelNode {
29 /// Index of the color in the palette.
30 pub pal: i32,
31 /// Start x-coordinate of the tile.
32 pub sx: i32,
33 /// End x-coordinate of the tile.
34 pub mx: i32,
35 /// Color data map for the tile.
36 pub map: Vec<u8>,
37}
38impl SixelNode {
39 pub fn new(pal: i32, sx: i32, mx: i32, map: Vec<u8>) -> Self {
40 Self { pal, sx, mx, map }
41 }
42}
43
44/// Handles sixel data output to a specified writer destination.
45///
46/// Abstracts over writing sixel-encoded data,
47/// supporting various output targets such as files or terminal streams.
48///
49/// # Adaptation
50/// - Derived from `sixel_output` struct in the `libsixel` C library.
51#[derive(Debug, Default, PartialEq, Eq, Hash)]
52pub(crate) struct SixelOutput<W: IoWrite> {
53 /* public fields
54 */
55 /// Palette selection mode.
56 pub color_model: SixelColorModel,
57
58 /// Writer for output, managing data destination.
59 pub fn_write: W,
60
61 /// Last saved pixel value.
62 pub save_pixel: u8,
63 /// Count of consecutive saved pixels.
64 pub save_count: i32,
65 /// Currently active palette index.
66 pub active_palette: i32,
67
68 /// Collection of sixel nodes for dithering.
69 pub nodes: Vec<SixelNode>,
70
71 /// Flag to allow penetration of the multiplexer.
72 pub penetrate_multiplexer: bool,
73 /// Policy for encoding decisions.
74 pub encode_policy: SixelEncodePolicy,
75
76 /// Buffer for output data.
77 pub buffer: String,
78
79 /* private compatibility flags
80 */
81 /// Indicates 8-bit terminal support.
82 ///
83 /// `false` for 7-bit, `true` for 8-bit.
84 pub(crate) has_8bit_control: bool,
85
86 /// Sixel scrolling support flag.
87 ///
88 /// `false` if terminal supports scrolling, `true` if not.
89 pub(crate) has_sixel_scrolling: bool,
90
91 /// Argument limit for repeat introducer (DECGRI).
92 ///
93 /// `false` if limited to 255, `true` if unlimited.
94 pub(crate) has_gri_arg_limit: bool,
95
96 /// DECSDM (CSI ? 80 h) sixel scrolling glitch flag.
97 ///
98 /// `false` enables sixel scrolling, `true` disables it.
99 pub(crate) has_sdm_glitch: bool,
100
101 /// Flag to skip DCS envelope handling.
102 ///
103 /// `false` to process, `true` to skip.
104 pub(crate) skip_dcs_envelope: bool,
105}
106
107// general methods annd constants
108#[allow(dead_code, reason = "crate private struct")]
109impl<W: IoWrite> SixelOutput<W> {
110 /// Device Control String start and end sequences
111 pub(crate) const DCS_START_7BIT: &str = "\x1BP";
112 pub(crate) const DCS_START_8BIT: &str = "\u{220}";
113 pub(crate) const DCS_END_7BIT: &str = "\x1B\\";
114 pub(crate) const DCS_END_8BIT: &str = "\u{234}";
115
116 /// Used in `penetrate`.
117 pub(crate) const SCREEN_PACKET_SIZE: usize = 256;
118
119 /// Packet size limit.
120 /// Used in `advance`.
121 pub(crate) const PACKET_SIZE: usize = 16_384;
122
123 /// Used in `encode_high_color`.
124 pub(crate) const PALETTE_HIT: i32 = 1;
125 pub(crate) const PALETTE_CHANGE: i32 = 2;
126
127 /// Create new output context object
128 pub fn new(fn_write: W) -> Self {
129 Self {
130 has_8bit_control: false,
131 has_sdm_glitch: false,
132 has_gri_arg_limit: true,
133 skip_dcs_envelope: false,
134 color_model: SixelColorModel::Auto,
135 fn_write,
136 save_pixel: 0,
137 save_count: 0,
138 active_palette: -1,
139 nodes: Vec::new(),
140 penetrate_multiplexer: false,
141 encode_policy: SixelEncodePolicy::Auto,
142 has_sixel_scrolling: false,
143 buffer: String::new(),
144 }
145 }
146
147 /// Get 8bit output mode which indicates whether it uses C1 control characters.
148 #[must_use]
149 pub fn get_8bit_availability(&self) -> bool {
150 self.has_8bit_control
151 }
152 /// Set 8bit output mode state.
153 pub fn set_8bit_availability(&mut self, availability: bool) {
154 self.has_8bit_control = availability;
155 }
156
157 /// Set limit for repeat introducer (DECGRI).
158 ///
159 /// `false` if limited to 255, `true` if unlimited.
160 pub fn set_gri_arg_limit(&mut self, value: bool) {
161 self.has_gri_arg_limit = value;
162 }
163
164 /// Set GNU Screen penetration.
165 pub fn set_penetrate_multiplexer(&mut self, penetrate: bool) {
166 self.penetrate_multiplexer = penetrate;
167 }
168
169 /// Set whether we skip DCS envelope.
170 pub fn set_skip_dcs_envelope(&mut self, skip: bool) {
171 self.skip_dcs_envelope = skip;
172 }
173
174 /// Set the color model.
175 pub fn set_color_model(&mut self, color_model: SixelColorModel) {
176 self.color_model = color_model;
177 }
178
179 /// Set the encoding policy.
180 pub fn set_encode_policy(&mut self, encode_policy: SixelEncodePolicy) {
181 self.encode_policy = encode_policy;
182 }
183}