Skip to main content

agg_rust/
gsv_text.rs

1//! Geometric stroke vector text.
2//!
3//! Port of `agg_gsv_text.h` + `agg_gsv_text.cpp` — renders text using
4//! a built-in stroke font. Each glyph is defined as a series of stroked
5//! line segments (move_to / line_to), making it resolution-independent.
6
7use crate::basics::{VertexSource, PATH_CMD_LINE_TO, PATH_CMD_MOVE_TO, PATH_CMD_STOP};
8use crate::bounding_rect::bounding_rect_single;
9use crate::conv_stroke::ConvStroke;
10use crate::conv_transform::ConvTransform;
11use crate::math_stroke::{LineCap, LineJoin};
12use crate::trans_affine::TransAffine;
13
14// ============================================================================
15// Default font data (from agg_gsv_text.cpp)
16// ============================================================================
17
18/// Built-in stroke font — 3948 bytes of glyph data.
19///
20/// Format:
21/// - Bytes [0..2]: LE u16 offset to glyph index table
22/// - Bytes [4..6]: LE u16 base height
23/// - At index table offset: 257 × LE u16 glyph offsets
24/// - After index table: glyph stroke data as (dx: i8, dy_with_flag: u8) pairs
25///   where bit 7 of dy signals move_to vs line_to
26#[rustfmt::skip]
27static GSV_DEFAULT_FONT: &[u8] = &[
28    0x40,0x00,0x6c,0x0f,0x15,0x00,0x0e,0x00,0xf9,0xff,
29    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
30    0x0d,0x0a,0x0d,0x0a,0x46,0x6f,0x6e,0x74,0x20,0x28,
31    0x63,0x29,0x20,0x4d,0x69,0x63,0x72,0x6f,0x50,0x72,
32    0x6f,0x66,0x20,0x32,0x37,0x20,0x53,0x65,0x70,0x74,
33    0x65,0x6d,0x62,0x2e,0x31,0x39,0x38,0x39,0x00,0x0d,
34    0x0a,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
35    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
36    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
37    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
38    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
39    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
41    0x02,0x00,0x12,0x00,0x34,0x00,0x46,0x00,0x94,0x00,
42    0xd0,0x00,0x2e,0x01,0x3e,0x01,0x64,0x01,0x8a,0x01,
43    0x98,0x01,0xa2,0x01,0xb4,0x01,0xba,0x01,0xc6,0x01,
44    0xcc,0x01,0xf0,0x01,0xfa,0x01,0x18,0x02,0x38,0x02,
45    0x44,0x02,0x68,0x02,0x98,0x02,0xa2,0x02,0xde,0x02,
46    0x0e,0x03,0x24,0x03,0x40,0x03,0x48,0x03,0x52,0x03,
47    0x5a,0x03,0x82,0x03,0xec,0x03,0xfa,0x03,0x26,0x04,
48    0x4c,0x04,0x6a,0x04,0x7c,0x04,0x8a,0x04,0xb6,0x04,
49    0xc4,0x04,0xca,0x04,0xe0,0x04,0xee,0x04,0xf8,0x04,
50    0x0a,0x05,0x18,0x05,0x44,0x05,0x5e,0x05,0x8e,0x05,
51    0xac,0x05,0xd6,0x05,0xe0,0x05,0xf6,0x05,0x00,0x06,
52    0x12,0x06,0x1c,0x06,0x28,0x06,0x36,0x06,0x48,0x06,
53    0x4e,0x06,0x60,0x06,0x6e,0x06,0x74,0x06,0x84,0x06,
54    0xa6,0x06,0xc8,0x06,0xe6,0x06,0x08,0x07,0x2c,0x07,
55    0x3c,0x07,0x68,0x07,0x7c,0x07,0x8c,0x07,0xa2,0x07,
56    0xb0,0x07,0xb6,0x07,0xd8,0x07,0xec,0x07,0x10,0x08,
57    0x32,0x08,0x54,0x08,0x64,0x08,0x88,0x08,0x98,0x08,
58    0xac,0x08,0xb6,0x08,0xc8,0x08,0xd2,0x08,0xe4,0x08,
59    0xf2,0x08,0x3e,0x09,0x48,0x09,0x94,0x09,0xc2,0x09,
60    0xc4,0x09,0xd0,0x09,0xe2,0x09,0x04,0x0a,0x0e,0x0a,
61    0x26,0x0a,0x34,0x0a,0x4a,0x0a,0x66,0x0a,0x70,0x0a,
62    0x7e,0x0a,0x8e,0x0a,0x9a,0x0a,0xa6,0x0a,0xb4,0x0a,
63    0xd8,0x0a,0xe2,0x0a,0xf6,0x0a,0x18,0x0b,0x22,0x0b,
64    0x32,0x0b,0x56,0x0b,0x60,0x0b,0x6e,0x0b,0x7c,0x0b,
65    0x8a,0x0b,0x9c,0x0b,0x9e,0x0b,0xb2,0x0b,0xc2,0x0b,
66    0xd8,0x0b,0xf4,0x0b,0x08,0x0c,0x30,0x0c,0x56,0x0c,
67    0x72,0x0c,0x90,0x0c,0xb2,0x0c,0xce,0x0c,0xe2,0x0c,
68    0xfe,0x0c,0x10,0x0d,0x26,0x0d,0x36,0x0d,0x42,0x0d,
69    0x4e,0x0d,0x5c,0x0d,0x78,0x0d,0x8c,0x0d,0x8e,0x0d,
70    0x90,0x0d,0x92,0x0d,0x94,0x0d,0x96,0x0d,0x98,0x0d,
71    0x9a,0x0d,0x9c,0x0d,0x9e,0x0d,0xa0,0x0d,0xa2,0x0d,
72    0xa4,0x0d,0xa6,0x0d,0xa8,0x0d,0xaa,0x0d,0xac,0x0d,
73    0xae,0x0d,0xb0,0x0d,0xb2,0x0d,0xb4,0x0d,0xb6,0x0d,
74    0xb8,0x0d,0xba,0x0d,0xbc,0x0d,0xbe,0x0d,0xc0,0x0d,
75    0xc2,0x0d,0xc4,0x0d,0xc6,0x0d,0xc8,0x0d,0xca,0x0d,
76    0xcc,0x0d,0xce,0x0d,0xd0,0x0d,0xd2,0x0d,0xd4,0x0d,
77    0xd6,0x0d,0xd8,0x0d,0xda,0x0d,0xdc,0x0d,0xde,0x0d,
78    0xe0,0x0d,0xe2,0x0d,0xe4,0x0d,0xe6,0x0d,0xe8,0x0d,
79    0xea,0x0d,0xec,0x0d,0x0c,0x0e,0x26,0x0e,0x48,0x0e,
80    0x64,0x0e,0x88,0x0e,0x92,0x0e,0xa6,0x0e,0xb4,0x0e,
81    0xd0,0x0e,0xee,0x0e,0x02,0x0f,0x16,0x0f,0x26,0x0f,
82    0x3c,0x0f,0x58,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
83    0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
84    0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,
85    0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x10,0x80,
86    0x05,0x95,0x00,0x72,0x00,0xfb,0xff,0x7f,0x01,0x7f,
87    0x01,0x01,0xff,0x01,0x05,0xfe,0x05,0x95,0xff,0x7f,
88    0x00,0x7a,0x01,0x86,0xff,0x7a,0x01,0x87,0x01,0x7f,
89    0xfe,0x7a,0x0a,0x87,0xff,0x7f,0x00,0x7a,0x01,0x86,
90    0xff,0x7a,0x01,0x87,0x01,0x7f,0xfe,0x7a,0x05,0xf2,
91    0x0b,0x95,0xf9,0x64,0x0d,0x9c,0xf9,0x64,0xfa,0x91,
92    0x0e,0x00,0xf1,0xfa,0x0e,0x00,0x04,0xfc,0x08,0x99,
93    0x00,0x63,0x04,0x9d,0x00,0x63,0x04,0x96,0xff,0x7f,
94    0x01,0x7f,0x01,0x01,0x00,0x01,0xfe,0x02,0xfd,0x01,
95    0xfc,0x00,0xfd,0x7f,0xfe,0x7e,0x00,0x7e,0x01,0x7e,
96    0x01,0x7f,0x02,0x7f,0x06,0x7e,0x02,0x7f,0x02,0x7e,
97    0xf2,0x89,0x02,0x7e,0x02,0x7f,0x06,0x7e,0x02,0x7f,
98    0x01,0x7f,0x01,0x7e,0x00,0x7c,0xfe,0x7e,0xfd,0x7f,
99    0xfc,0x00,0xfd,0x01,0xfe,0x02,0x00,0x01,0x01,0x01,
100    0x01,0x7f,0xff,0x7f,0x10,0xfd,0x15,0x95,0xee,0x6b,
101    0x05,0x95,0x02,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7f,
102    0xfe,0x00,0xfe,0x02,0x00,0x02,0x01,0x02,0x02,0x01,
103    0x02,0x00,0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,
104    0x02,0x01,0xfc,0xf2,0xfe,0x7f,0xff,0x7e,0x00,0x7e,
105    0x02,0x7e,0x02,0x00,0x02,0x01,0x01,0x02,0x00,0x02,
106    0xfe,0x02,0xfe,0x00,0x07,0xf9,0x15,0x8d,0xff,0x7f,
107    0x01,0x7f,0x01,0x01,0x00,0x01,0xff,0x01,0xff,0x00,
108    0xff,0x7f,0xff,0x7e,0xfe,0x7b,0xfe,0x7d,0xfe,0x7e,
109    0xfe,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,0x00,0x03,
110    0x01,0x02,0x06,0x04,0x02,0x02,0x01,0x02,0x00,0x02,
111    0xff,0x02,0xfe,0x01,0xfe,0x7f,0xff,0x7e,0x00,0x7e,
112    0x01,0x7d,0x02,0x7d,0x05,0x79,0x02,0x7e,0x03,0x7f,
113    0x01,0x00,0x01,0x01,0x00,0x01,0xf1,0xfe,0xfe,0x01,
114    0xff,0x02,0x00,0x03,0x01,0x02,0x02,0x02,0x00,0x86,
115    0x01,0x7e,0x08,0x75,0x02,0x7e,0x02,0x7f,0x05,0x80,
116    0x05,0x93,0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,
117    0xff,0x7e,0xff,0x7f,0x06,0xf1,0x0b,0x99,0xfe,0x7e,
118    0xfe,0x7d,0xfe,0x7c,0xff,0x7b,0x00,0x7c,0x01,0x7b,
119    0x02,0x7c,0x02,0x7d,0x02,0x7e,0xfe,0x9e,0xfe,0x7c,
120    0xff,0x7d,0xff,0x7b,0x00,0x7c,0x01,0x7b,0x01,0x7d,
121    0x02,0x7c,0x05,0x85,0x03,0x99,0x02,0x7e,0x02,0x7d,
122    0x02,0x7c,0x01,0x7b,0x00,0x7c,0xff,0x7b,0xfe,0x7c,
123    0xfe,0x7d,0xfe,0x7e,0x02,0x9e,0x02,0x7c,0x01,0x7d,
124    0x01,0x7b,0x00,0x7c,0xff,0x7b,0xff,0x7d,0xfe,0x7c,
125    0x09,0x85,0x08,0x95,0x00,0x74,0xfb,0x89,0x0a,0x7a,
126    0x00,0x86,0xf6,0x7a,0x0d,0xf4,0x0d,0x92,0x00,0x6e,
127    0xf7,0x89,0x12,0x00,0x04,0xf7,0x06,0x81,0xff,0x7f,
128    0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,0xff,0x7e,
129    0xff,0x7f,0x06,0x84,0x04,0x89,0x12,0x00,0x04,0xf7,
130    0x05,0x82,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
131    0x05,0xfe,0x00,0xfd,0x0e,0x18,0x00,0xeb,0x09,0x95,
132    0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7d,0x01,0x7b,
133    0x02,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x03,
134    0x01,0x05,0x00,0x03,0xff,0x05,0xfe,0x03,0xfd,0x01,
135    0xfe,0x00,0x0b,0xeb,0x06,0x91,0x02,0x01,0x03,0x03,
136    0x00,0x6b,0x09,0x80,0x04,0x90,0x00,0x01,0x01,0x02,
137    0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7f,
138    0x01,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7d,0xf6,0x76,
139    0x0e,0x00,0x03,0x80,0x05,0x95,0x0b,0x00,0xfa,0x78,
140    0x03,0x00,0x02,0x7f,0x01,0x7f,0x01,0x7d,0x00,0x7e,
141    0xff,0x7d,0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,
142    0xff,0x01,0xff,0x02,0x11,0xfc,0x0d,0x95,0xf6,0x72,
143    0x0f,0x00,0xfb,0x8e,0x00,0x6b,0x07,0x80,0x0f,0x95,
144    0xf6,0x00,0xff,0x77,0x01,0x01,0x03,0x01,0x03,0x00,
145    0x03,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,0xff,0x7d,
146    0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x01,
147    0xff,0x02,0x11,0xfc,0x10,0x92,0xff,0x02,0xfd,0x01,
148    0xfe,0x00,0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7b,
149    0x01,0x7c,0x02,0x7e,0x03,0x7f,0x01,0x00,0x03,0x01,
150    0x02,0x02,0x01,0x03,0x00,0x01,0xff,0x03,0xfe,0x02,
151    0xfd,0x01,0xff,0x00,0xfd,0x7f,0xfe,0x7e,0xff,0x7d,
152    0x10,0xf9,0x11,0x95,0xf6,0x6b,0xfc,0x95,0x0e,0x00,
153    0x03,0xeb,0x08,0x95,0xfd,0x7f,0xff,0x7e,0x00,0x7e,
154    0x01,0x7e,0x02,0x7f,0x04,0x7f,0x03,0x7f,0x02,0x7e,
155    0x01,0x7e,0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,
156    0xfc,0x00,0xfd,0x01,0xff,0x01,0xff,0x02,0x00,0x03,
157    0x01,0x02,0x02,0x02,0x03,0x01,0x04,0x01,0x02,0x01,
158    0x01,0x02,0x00,0x02,0xff,0x02,0xfd,0x01,0xfc,0x00,
159    0x0c,0xeb,0x10,0x8e,0xff,0x7d,0xfe,0x7e,0xfd,0x7f,
160    0xff,0x00,0xfd,0x01,0xfe,0x02,0xff,0x03,0x00,0x01,
161    0x01,0x03,0x02,0x02,0x03,0x01,0x01,0x00,0x03,0x7f,
162    0x02,0x7e,0x01,0x7c,0x00,0x7b,0xff,0x7b,0xfe,0x7d,
163    0xfd,0x7f,0xfe,0x00,0xfd,0x01,0xff,0x02,0x10,0xfd,
164    0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
165    0x00,0xf4,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01,
166    0x05,0xfe,0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,
167    0xff,0x01,0x01,0xf3,0xff,0x7f,0xff,0x01,0x01,0x01,
168    0x01,0x7f,0x00,0x7e,0xff,0x7e,0xff,0x7f,0x06,0x84,
169    0x14,0x92,0xf0,0x77,0x10,0x77,0x04,0x80,0x04,0x8c,
170    0x12,0x00,0xee,0xfa,0x12,0x00,0x04,0xfa,0x04,0x92,
171    0x10,0x77,0xf0,0x77,0x14,0x80,0x03,0x90,0x00,0x01,
172    0x01,0x02,0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,
173    0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,
174    0xfc,0x7e,0x00,0x7d,0x00,0xfb,0xff,0x7f,0x01,0x7f,
175    0x01,0x01,0xff,0x01,0x09,0xfe,0x12,0x8d,0xff,0x02,
176    0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xff,0x7f,0xff,0x7d,
177    0x00,0x7d,0x01,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
178    0x01,0x02,0xfb,0x88,0xfe,0x7e,0xff,0x7d,0x00,0x7d,
179    0x01,0x7e,0x01,0x7f,0x07,0x8b,0xff,0x78,0x00,0x7e,
180    0x02,0x7f,0x02,0x00,0x02,0x02,0x01,0x03,0x00,0x02,
181    0xff,0x03,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfd,0x01,
182    0xfd,0x00,0xfd,0x7f,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
183    0xff,0x7d,0x00,0x7d,0x01,0x7d,0x01,0x7e,0x02,0x7e,
184    0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,0x02,0x01,
185    0x01,0x01,0xfe,0x8d,0xff,0x78,0x00,0x7e,0x01,0x7f,
186    0x08,0xfb,0x09,0x95,0xf8,0x6b,0x08,0x95,0x08,0x6b,
187    0xf3,0x87,0x0a,0x00,0x04,0xf9,0x04,0x95,0x00,0x6b,
188    0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,
189    0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x80,
190    0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d,
191    0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,0x11,0x80,
192    0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00,
193    0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b,
194    0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00,
195    0x02,0x01,0x02,0x02,0x01,0x02,0x03,0xfb,0x04,0x95,
196    0x00,0x6b,0x00,0x95,0x07,0x00,0x03,0x7f,0x02,0x7e,
197    0x01,0x7e,0x01,0x7d,0x00,0x7b,0xff,0x7d,0xff,0x7e,
198    0xfe,0x7e,0xfd,0x7f,0xf9,0x00,0x11,0x80,0x04,0x95,
199    0x00,0x6b,0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,
200    0xf8,0xf5,0x0d,0x00,0x02,0x80,0x04,0x95,0x00,0x6b,
201    0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,0x06,0xf5,
202    0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00,
203    0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b,
204    0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00,
205    0x02,0x01,0x02,0x02,0x01,0x02,0x00,0x03,0xfb,0x80,
206    0x05,0x00,0x03,0xf8,0x04,0x95,0x00,0x6b,0x0e,0x95,
207    0x00,0x6b,0xf2,0x8b,0x0e,0x00,0x04,0xf5,0x04,0x95,
208    0x00,0x6b,0x04,0x80,0x0c,0x95,0x00,0x70,0xff,0x7d,
209    0xff,0x7f,0xfe,0x7f,0xfe,0x00,0xfe,0x01,0xff,0x01,
210    0xff,0x03,0x00,0x02,0x0e,0xf9,0x04,0x95,0x00,0x6b,
211    0x0e,0x95,0xf2,0x72,0x05,0x85,0x09,0x74,0x03,0x80,
212    0x04,0x95,0x00,0x6b,0x00,0x80,0x0c,0x00,0x01,0x80,
213    0x04,0x95,0x00,0x6b,0x00,0x95,0x08,0x6b,0x08,0x95,
214    0xf8,0x6b,0x08,0x95,0x00,0x6b,0x04,0x80,0x04,0x95,
215    0x00,0x6b,0x00,0x95,0x0e,0x6b,0x00,0x95,0x00,0x6b,
216    0x04,0x80,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
217    0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e,
218    0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02,
219    0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02,
220    0xfe,0x01,0xfc,0x00,0x0d,0xeb,0x04,0x95,0x00,0x6b,
221    0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,
222    0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,
223    0x11,0xf6,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e,
224    0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e,
225    0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02,
226    0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02,
227    0xfe,0x01,0xfc,0x00,0x03,0xef,0x06,0x7a,0x04,0x82,
228    0x04,0x95,0x00,0x6b,0x00,0x95,0x09,0x00,0x03,0x7f,
229    0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,
230    0xfd,0x7f,0xf7,0x00,0x07,0x80,0x07,0x75,0x03,0x80,
231    0x11,0x92,0xfe,0x02,0xfd,0x01,0xfc,0x00,0xfd,0x7f,
232    0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x02,0x7f,
233    0x06,0x7e,0x02,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d,
234    0xfe,0x7e,0xfd,0x7f,0xfc,0x00,0xfd,0x01,0xfe,0x02,
235    0x11,0xfd,0x08,0x95,0x00,0x6b,0xf9,0x95,0x0e,0x00,
236    0x01,0xeb,0x04,0x95,0x00,0x71,0x01,0x7d,0x02,0x7e,
237    0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x02,0x01,0x03,
238    0x00,0x0f,0x04,0xeb,0x01,0x95,0x08,0x6b,0x08,0x95,
239    0xf8,0x6b,0x09,0x80,0x02,0x95,0x05,0x6b,0x05,0x95,
240    0xfb,0x6b,0x05,0x95,0x05,0x6b,0x05,0x95,0xfb,0x6b,
241    0x07,0x80,0x03,0x95,0x0e,0x6b,0x00,0x95,0xf2,0x6b,
242    0x11,0x80,0x01,0x95,0x08,0x76,0x00,0x75,0x08,0x95,
243    0xf8,0x76,0x09,0xf5,0x11,0x95,0xf2,0x6b,0x00,0x95,
244    0x0e,0x00,0xf2,0xeb,0x0e,0x00,0x03,0x80,0x03,0x93,
245    0x00,0x6c,0x01,0x94,0x00,0x6c,0xff,0x94,0x05,0x00,
246    0xfb,0xec,0x05,0x00,0x02,0x81,0x00,0x95,0x0e,0x68,
247    0x00,0x83,0x06,0x93,0x00,0x6c,0x01,0x94,0x00,0x6c,
248    0xfb,0x94,0x05,0x00,0xfb,0xec,0x05,0x00,0x03,0x81,
249    0x03,0x87,0x08,0x05,0x08,0x7b,0xf0,0x80,0x08,0x04,
250    0x08,0x7c,0x03,0xf9,0x01,0x80,0x10,0x00,0x01,0x80,
251    0x06,0x95,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7f,
252    0x01,0x01,0xff,0x01,0x05,0xef,0x0f,0x8e,0x00,0x72,
253    0x00,0x8b,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,
254    0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
255    0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,
256    0x04,0x95,0x00,0x6b,0x00,0x8b,0x02,0x02,0x02,0x01,
257    0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,
258    0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,0xfe,0x01,
259    0xfe,0x02,0x0f,0xfd,0x0f,0x8b,0xfe,0x02,0xfe,0x01,
260    0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
261    0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
262    0x02,0x02,0x03,0xfd,0x0f,0x95,0x00,0x6b,0x00,0x8b,
263    0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xfe,0x7e,
264    0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,0x02,0x7f,
265    0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,0x03,0x88,
266    0x0c,0x00,0x00,0x02,0xff,0x02,0xff,0x01,0xfe,0x01,
267    0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
268    0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
269    0x02,0x02,0x03,0xfd,0x0a,0x95,0xfe,0x00,0xfe,0x7f,
270    0xff,0x7d,0x00,0x6f,0xfd,0x8e,0x07,0x00,0x03,0xf2,
271    0x0f,0x8e,0x00,0x70,0xff,0x7d,0xff,0x7f,0xfe,0x7f,
272    0xfd,0x00,0xfe,0x01,0x09,0x91,0xfe,0x02,0xfe,0x01,
273    0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e,
274    0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01,
275    0x02,0x02,0x04,0xfd,0x04,0x95,0x00,0x6b,0x00,0x8a,
276    0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,
277    0x00,0x76,0x04,0x80,0x03,0x95,0x01,0x7f,0x01,0x01,
278    0xff,0x01,0xff,0x7f,0x01,0xf9,0x00,0x72,0x04,0x80,
279    0x05,0x95,0x01,0x7f,0x01,0x01,0xff,0x01,0xff,0x7f,
280    0x01,0xf9,0x00,0x6f,0xff,0x7d,0xfe,0x7f,0xfe,0x00,
281    0x09,0x87,0x04,0x95,0x00,0x6b,0x0a,0x8e,0xf6,0x76,
282    0x04,0x84,0x07,0x78,0x02,0x80,0x04,0x95,0x00,0x6b,
283    0x04,0x80,0x04,0x8e,0x00,0x72,0x00,0x8a,0x03,0x03,
284    0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,0x00,0x76,
285    0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,
286    0x01,0x7d,0x00,0x76,0x04,0x80,0x04,0x8e,0x00,0x72,
287    0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,
288    0x01,0x7d,0x00,0x76,0x04,0x80,0x08,0x8e,0xfe,0x7f,
289    0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
290    0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x01,0x03,
291    0x00,0x02,0xff,0x03,0xfe,0x02,0xfe,0x01,0xfd,0x00,
292    0x0b,0xf2,0x04,0x8e,0x00,0x6b,0x00,0x92,0x02,0x02,
293    0x02,0x01,0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,
294    0x00,0x7e,0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,
295    0xfe,0x01,0xfe,0x02,0x0f,0xfd,0x0f,0x8e,0x00,0x6b,
296    0x00,0x92,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,
297    0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,
298    0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,
299    0x04,0x8e,0x00,0x72,0x00,0x88,0x01,0x03,0x02,0x02,
300    0x02,0x01,0x03,0x00,0x01,0xf2,0x0e,0x8b,0xff,0x02,
301    0xfd,0x01,0xfd,0x00,0xfd,0x7f,0xff,0x7e,0x01,0x7e,
302    0x02,0x7f,0x05,0x7f,0x02,0x7f,0x01,0x7e,0x00,0x7f,
303    0xff,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,
304    0x0e,0xfd,0x05,0x95,0x00,0x6f,0x01,0x7d,0x02,0x7f,
305    0x02,0x00,0xf8,0x8e,0x07,0x00,0x03,0xf2,0x04,0x8e,
306    0x00,0x76,0x01,0x7d,0x02,0x7f,0x03,0x00,0x02,0x01,
307    0x03,0x03,0x00,0x8a,0x00,0x72,0x04,0x80,0x02,0x8e,
308    0x06,0x72,0x06,0x8e,0xfa,0x72,0x08,0x80,0x03,0x8e,
309    0x04,0x72,0x04,0x8e,0xfc,0x72,0x04,0x8e,0x04,0x72,
310    0x04,0x8e,0xfc,0x72,0x07,0x80,0x03,0x8e,0x0b,0x72,
311    0x00,0x8e,0xf5,0x72,0x0e,0x80,0x02,0x8e,0x06,0x72,
312    0x06,0x8e,0xfa,0x72,0xfe,0x7c,0xfe,0x7e,0xfe,0x7f,
313    0xff,0x00,0x0f,0x87,0x0e,0x8e,0xf5,0x72,0x00,0x8e,
314    0x0b,0x00,0xf5,0xf2,0x0b,0x00,0x03,0x80,0x09,0x99,
315    0xfe,0x7f,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,
316    0x01,0x7f,0x01,0x7e,0x00,0x7e,0xfe,0x7e,0x01,0x8e,
317    0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e,
318    0x00,0x7e,0xff,0x7e,0xfc,0x7e,0x04,0x7e,0x01,0x7e,
319    0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,
320    0x01,0x7e,0xff,0x8e,0x02,0x7e,0x00,0x7e,0xff,0x7e,
321    0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,
322    0x02,0x7f,0x05,0x87,0x04,0x95,0x00,0x77,0x00,0xfd,
323    0x00,0x77,0x04,0x80,0x05,0x99,0x02,0x7f,0x01,0x7f,
324    0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,
325    0x00,0x7e,0x02,0x7e,0xff,0x8e,0x01,0x7e,0x00,0x7e,
326    0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,
327    0x04,0x7e,0xfc,0x7e,0xff,0x7e,0x00,0x7e,0x01,0x7e,
328    0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0x01,0x8e,
329    0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e,
330    0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfe,0x7f,0x09,0x87,
331    0x03,0x86,0x00,0x02,0x01,0x03,0x02,0x01,0x02,0x00,
332    0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01,
333    0x01,0x02,0xee,0xfe,0x01,0x02,0x02,0x01,0x02,0x00,
334    0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01,
335    0x01,0x03,0x00,0x02,0x03,0xf4,0x10,0x80,0x03,0x80,
336    0x07,0x15,0x08,0x6b,0xfe,0x85,0xf5,0x00,0x10,0xfb,
337    0x0d,0x95,0xf6,0x00,0x00,0x6b,0x0a,0x00,0x02,0x02,
338    0x00,0x08,0xfe,0x02,0xf6,0x00,0x0e,0xf4,0x03,0x80,
339    0x00,0x15,0x0a,0x00,0x02,0x7e,0x00,0x7e,0x00,0x7d,
340    0x00,0x7e,0xfe,0x7f,0xf6,0x00,0x0a,0x80,0x02,0x7e,
341    0x01,0x7e,0x00,0x7d,0xff,0x7d,0xfe,0x7f,0xf6,0x00,
342    0x10,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,0xff,0x7e,
343    0x03,0xed,0x03,0xfd,0x00,0x03,0x02,0x00,0x00,0x12,
344    0x02,0x03,0x0a,0x00,0x00,0x6b,0x02,0x00,0x00,0x7d,
345    0xfe,0x83,0xf4,0x00,0x11,0x80,0x0f,0x80,0xf4,0x00,
346    0x00,0x15,0x0c,0x00,0xff,0xf6,0xf5,0x00,0x0f,0xf5,
347    0x04,0x95,0x07,0x76,0x00,0x0a,0x07,0x80,0xf9,0x76,
348    0x00,0x75,0xf8,0x80,0x07,0x0c,0x09,0xf4,0xf9,0x0c,
349    0x09,0xf4,0x03,0x92,0x02,0x03,0x07,0x00,0x03,0x7d,
350    0x00,0x7b,0xfc,0x7e,0x04,0x7d,0x00,0x7a,0xfd,0x7e,
351    0xf9,0x00,0xfe,0x02,0x06,0x89,0x02,0x00,0x06,0xf5,
352    0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0x02,0x80,
353    0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0xf8,0x96,
354    0x03,0x00,0x07,0xea,0x03,0x80,0x00,0x15,0x0c,0x80,
355    0xf7,0x76,0xfd,0x00,0x03,0x80,0x0a,0x75,0x03,0x80,
356    0x03,0x80,0x07,0x13,0x02,0x02,0x03,0x00,0x00,0x6b,
357    0x02,0x80,0x03,0x80,0x00,0x15,0x09,0x6b,0x09,0x15,
358    0x00,0x6b,0x03,0x80,0x03,0x80,0x00,0x15,0x00,0xf6,
359    0x0d,0x00,0x00,0x8a,0x00,0x6b,0x03,0x80,0x07,0x80,
360    0xfd,0x00,0xff,0x03,0x00,0x04,0x00,0x07,0x00,0x04,
361    0x01,0x02,0x03,0x01,0x06,0x00,0x03,0x7f,0x01,0x7e,
362    0x01,0x7c,0x00,0x79,0xff,0x7c,0xff,0x7d,0xfd,0x00,
363    0xfa,0x00,0x0e,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,
364    0x00,0x6b,0x02,0x80,0x03,0x80,0x00,0x15,0x0a,0x00,
365    0x02,0x7f,0x01,0x7d,0x00,0x7b,0xff,0x7e,0xfe,0x7f,
366    0xf6,0x00,0x10,0xf7,0x11,0x8f,0xff,0x03,0xff,0x02,
367    0xfe,0x01,0xfa,0x00,0xfd,0x7f,0xff,0x7e,0x00,0x7c,
368    0x00,0x79,0x00,0x7b,0x01,0x7e,0x03,0x00,0x06,0x00,
369    0x02,0x00,0x01,0x03,0x01,0x02,0x03,0xfb,0x03,0x95,
370    0x0c,0x00,0xfa,0x80,0x00,0x6b,0x09,0x80,0x03,0x95,
371    0x00,0x77,0x06,0x7a,0x06,0x06,0x00,0x09,0xfa,0xf1,
372    0xfa,0x7a,0x0e,0x80,0x03,0x87,0x00,0x0b,0x02,0x02,
373    0x03,0x00,0x02,0x7e,0x01,0x02,0x04,0x00,0x02,0x7e,
374    0x00,0x75,0xfe,0x7e,0xfc,0x00,0xff,0x01,0xfe,0x7f,
375    0xfd,0x00,0xfe,0x02,0x07,0x8e,0x00,0x6b,0x09,0x80,
376    0x03,0x80,0x0e,0x15,0xf2,0x80,0x0e,0x6b,0x03,0x80,
377    0x03,0x95,0x00,0x6b,0x0e,0x00,0x00,0x7d,0xfe,0x98,
378    0x00,0x6b,0x05,0x80,0x03,0x95,0x00,0x75,0x02,0x7d,
379    0x0a,0x00,0x00,0x8e,0x00,0x6b,0x02,0x80,0x03,0x95,
380    0x00,0x6b,0x10,0x00,0x00,0x15,0xf8,0x80,0x00,0x6b,
381    0x0a,0x80,0x03,0x95,0x00,0x6b,0x10,0x00,0x00,0x15,
382    0xf8,0x80,0x00,0x6b,0x0a,0x00,0x00,0x7d,0x02,0x83,
383    0x10,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02,
384    0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0x89,0x00,0x6b,
385    0x03,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02,
386    0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0xf4,0x03,0x92,
387    0x02,0x03,0x07,0x00,0x03,0x7d,0x00,0x70,0xfd,0x7e,
388    0xf9,0x00,0xfe,0x02,0x03,0x89,0x09,0x00,0x02,0xf5,
389    0x03,0x80,0x00,0x15,0x00,0xf5,0x07,0x00,0x00,0x08,
390    0x02,0x03,0x06,0x00,0x02,0x7d,0x00,0x70,0xfe,0x7e,
391    0xfa,0x00,0xfe,0x02,0x00,0x08,0x0c,0xf6,0x0f,0x80,
392    0x00,0x15,0xf6,0x00,0xfe,0x7d,0x00,0x79,0x02,0x7e,
393    0x0a,0x00,0xf4,0xf7,0x07,0x09,0x07,0xf7,0x03,0x8c,
394    0x01,0x02,0x01,0x01,0x05,0x00,0x02,0x7f,0x01,0x7e,
395    0x00,0x74,0x00,0x86,0xff,0x01,0xfe,0x01,0xfb,0x00,
396    0xff,0x7f,0xff,0x7f,0x00,0x7c,0x01,0x7e,0x01,0x00,
397    0x05,0x00,0x02,0x00,0x01,0x02,0x03,0xfe,0x04,0x8e,
398    0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7e,0x00,0x77,
399    0xff,0x7e,0xfe,0x7f,0xfc,0x00,0xfe,0x01,0xff,0x02,
400    0x00,0x09,0x01,0x02,0x02,0x02,0x03,0x01,0x02,0x01,
401    0x01,0x01,0x01,0x02,0x02,0xeb,0x03,0x80,0x00,0x15,
402    0x03,0x00,0x02,0x7e,0x00,0x7b,0xfe,0x7e,0xfd,0x00,
403    0x03,0x80,0x04,0x00,0x03,0x7e,0x00,0x78,0xfd,0x7e,
404    0xf9,0x00,0x0c,0x80,0x03,0x8c,0x02,0x02,0x02,0x01,
405    0x03,0x00,0x02,0x7f,0x01,0x7d,0xfe,0x7e,0xf9,0x7d,
406    0xff,0x7e,0x00,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,
407    0x02,0x01,0x02,0xfe,0x0d,0x8c,0xff,0x02,0xfe,0x01,
408    0xfc,0x00,0xfe,0x7f,0xff,0x7e,0x00,0x77,0x01,0x7e,
409    0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x02,0x00,0x0f,
410    0xff,0x02,0xfe,0x01,0xf9,0x00,0x0c,0xeb,0x03,0x88,
411    0x0a,0x00,0x00,0x02,0x00,0x03,0xfe,0x02,0xfa,0x00,
412    0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,0x01,0x7f,
413    0x06,0x00,0x02,0x02,0x03,0xfe,0x03,0x8f,0x06,0x77,
414    0x06,0x09,0xfa,0x80,0x00,0x71,0xff,0x87,0xfb,0x79,
415    0x07,0x87,0x05,0x79,0x02,0x80,0x03,0x8d,0x02,0x02,
416    0x06,0x00,0x02,0x7e,0x00,0x7d,0xfc,0x7d,0x04,0x7e,
417    0x00,0x7d,0xfe,0x7e,0xfa,0x00,0xfe,0x02,0x04,0x85,
418    0x02,0x00,0x06,0xf9,0x03,0x8f,0x00,0x73,0x01,0x7e,
419    0x07,0x00,0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,
420    0x03,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x07,0x00,
421    0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0xf8,0x90,
422    0x03,0x00,0x08,0xf0,0x03,0x80,0x00,0x15,0x00,0xf3,
423    0x02,0x00,0x06,0x07,0xfa,0xf9,0x07,0x78,0x03,0x80,
424    0x03,0x80,0x04,0x0c,0x02,0x03,0x04,0x00,0x00,0x71,
425    0x02,0x80,0x03,0x80,0x00,0x0f,0x06,0x77,0x06,0x09,
426    0x00,0x71,0x02,0x80,0x03,0x80,0x00,0x0f,0x0a,0xf1,
427    0x00,0x0f,0xf6,0xf8,0x0a,0x00,0x02,0xf9,0x05,0x80,
428    0xff,0x01,0xff,0x04,0x00,0x05,0x01,0x03,0x01,0x02,
429    0x06,0x00,0x02,0x7e,0x00,0x7d,0x00,0x7b,0x00,0x7c,
430    0xfe,0x7f,0xfa,0x00,0x0b,0x80,0x03,0x80,0x00,0x0f,
431    0x00,0xfb,0x01,0x03,0x01,0x02,0x05,0x00,0x02,0x7e,
432    0x01,0x7d,0x00,0x76,0x03,0x80,0x10,0x80,0x10,0x80,
433    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
434    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
435    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
436    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
437    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
438    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
439    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
440    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
441    0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,
442    0x10,0x80,0x0a,0x8f,0x02,0x7f,0x01,0x7e,0x00,0x76,
443    0xff,0x7f,0xfe,0x7f,0xfb,0x00,0xff,0x01,0xff,0x01,
444    0x00,0x0a,0x01,0x02,0x01,0x01,0x05,0x00,0xf9,0x80,
445    0x00,0x6b,0x0c,0x86,0x0d,0x8a,0xff,0x03,0xfe,0x02,
446    0xfb,0x00,0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,
447    0x01,0x7f,0x05,0x00,0x02,0x01,0x01,0x03,0x03,0xfc,
448    0x03,0x80,0x00,0x0f,0x00,0xfb,0x01,0x03,0x01,0x02,
449    0x04,0x00,0x01,0x7e,0x01,0x7d,0x00,0x76,0x00,0x8a,
450    0x01,0x03,0x02,0x02,0x03,0x00,0x02,0x7e,0x01,0x7d,
451    0x00,0x76,0x03,0x80,0x03,0x8f,0x00,0x74,0x01,0x7e,
452    0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x01,0x00,0x8d,
453    0x00,0x6e,0xff,0x7e,0xfe,0x7f,0xfb,0x00,0xfe,0x01,
454    0x0c,0x85,0x03,0x8d,0x01,0x02,0x03,0x00,0x02,0x7e,
455    0x01,0x02,0x03,0x00,0x02,0x7e,0x00,0x74,0xfe,0x7f,
456    0xfd,0x00,0xff,0x01,0xfe,0x7f,0xfd,0x00,0xff,0x01,
457    0x00,0x0c,0x06,0x82,0x00,0x6b,0x08,0x86,0x03,0x80,
458    0x0a,0x0f,0xf6,0x80,0x0a,0x71,0x03,0x80,0x03,0x8f,
459    0x00,0x73,0x01,0x7e,0x07,0x00,0x02,0x02,0x00,0x0d,
460    0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,0x03,0x8f,
461    0x00,0x79,0x02,0x7e,0x08,0x00,0x00,0x89,0x00,0x71,
462    0x02,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,
463    0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,
464    0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x80,
465    0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,0x02,0x02,
466    0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,0x02,0x02,
467    0x00,0x0d,0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,
468    0x03,0x8d,0x00,0x02,0x02,0x00,0x00,0x71,0x08,0x00,
469    0x02,0x02,0x00,0x06,0xfe,0x02,0xf8,0x00,0x0c,0xf6,
470    0x03,0x8f,0x00,0x71,0x07,0x00,0x02,0x02,0x00,0x06,
471    0xfe,0x02,0xf9,0x00,0x0c,0x85,0x00,0x71,0x02,0x80,
472    0x03,0x8f,0x00,0x71,0x07,0x00,0x03,0x02,0x00,0x06,
473    0xfd,0x02,0xf9,0x00,0x0c,0xf6,0x03,0x8d,0x02,0x02,
474    0x06,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfa,0x00,
475    0xfe,0x02,0x04,0x85,0x06,0x00,0x02,0xf9,0x03,0x80,
476    0x00,0x0f,0x00,0xf8,0x04,0x00,0x00,0x06,0x02,0x02,
477    0x04,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfc,0x00,
478    0xfe,0x02,0x00,0x05,0x0a,0xf9,0x0d,0x80,0x00,0x0f,
479    0xf7,0x00,0xff,0x7e,0x00,0x7b,0x01,0x7e,0x09,0x00,
480    0xf6,0xfa,0x04,0x06,0x08,0xfa,
481];
482
483// ============================================================================
484// GsvText — geometric stroke vector text
485// ============================================================================
486
487#[derive(Clone, Copy, PartialEq)]
488enum Status {
489    Initial,
490    NextChar,
491    StartGlyph,
492    Glyph,
493}
494
495/// Read a little-endian u16 from a byte slice at the given offset.
496#[inline]
497fn value_le(data: &[u8], offset: usize) -> u16 {
498    u16::from_le_bytes([data[offset], data[offset + 1]])
499}
500
501/// Geometric stroke vector text renderer.
502///
503/// Renders text using a built-in stroke-based font. Each character is
504/// described as a series of stroked line segments, making the output
505/// resolution-independent.
506///
507/// Port of C++ `gsv_text`.
508pub struct GsvText {
509    x: f64,
510    y: f64,
511    start_x: f64,
512    width: f64,
513    height: f64,
514    space: f64,
515    line_space: f64,
516    text: Vec<u8>,
517    cur_chr: usize,
518    font: &'static [u8],
519    loaded_font: Vec<u8>,
520    status: Status,
521    flip: bool,
522    // Offsets into the font data
523    indices: usize,
524    glyphs: usize,
525    bglyph: usize,
526    eglyph: usize,
527    // Computed scale factors
528    w: f64,
529    h: f64,
530}
531
532impl GsvText {
533    pub fn new() -> Self {
534        Self {
535            x: 0.0,
536            y: 0.0,
537            start_x: 0.0,
538            width: 10.0,
539            height: 0.0,
540            space: 0.0,
541            line_space: 0.0,
542            text: Vec::new(),
543            cur_chr: 0,
544            font: GSV_DEFAULT_FONT,
545            loaded_font: Vec::new(),
546            status: Status::Initial,
547            flip: false,
548            indices: 0,
549            glyphs: 0,
550            bglyph: 0,
551            eglyph: 0,
552            w: 0.0,
553            h: 0.0,
554        }
555    }
556
557    /// Set the font data. If `None`, uses the loaded font (if any).
558    pub fn set_font(&mut self, font: Option<&'static [u8]>) {
559        match font {
560            Some(f) => self.font = f,
561            None => {
562                if !self.loaded_font.is_empty() {
563                    // Can't assign loaded_font as &'static, so we keep using
564                    // the default font. C++ version uses a raw pointer here.
565                    // In Rust we handle this differently in load_font.
566                }
567            }
568        }
569    }
570
571    pub fn flip(&mut self, flip_y: bool) {
572        self.flip = flip_y;
573    }
574
575    pub fn size(&mut self, height: f64, width: f64) {
576        self.height = height;
577        self.width = width;
578    }
579
580    pub fn space(&mut self, space: f64) {
581        self.space = space;
582    }
583
584    pub fn line_space(&mut self, line_space: f64) {
585        self.line_space = line_space;
586    }
587
588    pub fn start_point(&mut self, x: f64, y: f64) {
589        self.x = x;
590        self.start_x = x;
591        self.y = y;
592    }
593
594    pub fn text(&mut self, text: &str) {
595        self.text = text.as_bytes().to_vec();
596    }
597
598    /// Load font data from a byte slice (replaces C++ file-based load_font).
599    pub fn load_font_data(&mut self, data: &[u8]) {
600        self.loaded_font = data.to_vec();
601    }
602
603    /// Get the active font data. Uses loaded_font if available, else default.
604    fn active_font(&self) -> &[u8] {
605        if !self.loaded_font.is_empty() {
606            &self.loaded_font
607        } else {
608            self.font
609        }
610    }
611
612    /// Compute the bounding width of the current text.
613    pub fn text_width(&mut self) -> f64 {
614        match bounding_rect_single(self, 0) {
615            Some(r) => r.x2 - r.x1,
616            None => 0.0,
617        }
618    }
619}
620
621impl Default for GsvText {
622    fn default() -> Self {
623        Self::new()
624    }
625}
626
627impl VertexSource for GsvText {
628    fn rewind(&mut self, _path_id: u32) {
629        self.status = Status::Initial;
630        let font = self.active_font();
631        if font.is_empty() {
632            return;
633        }
634
635        let base_height = value_le(font, 4) as f64;
636        let idx_offset = value_le(font, 0) as usize;
637        self.indices = idx_offset;
638        self.glyphs = idx_offset + 257 * 2;
639        self.h = self.height / base_height;
640        self.w = if self.width == 0.0 {
641            self.h
642        } else {
643            self.width / base_height
644        };
645        if self.flip {
646            self.h = -self.h;
647        }
648        self.cur_chr = 0;
649    }
650
651    fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
652        // C++ uses switch with fallthrough: initial → next_char → start_glyph → glyph.
653        // Font data is accessed via short-lived borrows to avoid conflicting
654        // with mutations of self.status, self.cur_chr, etc.
655        loop {
656            match self.status {
657                Status::Initial => {
658                    if self.active_font().is_empty() {
659                        return PATH_CMD_STOP;
660                    }
661                    self.status = Status::NextChar;
662                    continue;
663                }
664                Status::NextChar => {
665                    if self.cur_chr >= self.text.len() {
666                        return PATH_CMD_STOP;
667                    }
668                    let idx = self.text[self.cur_chr] as usize;
669                    self.cur_chr += 1;
670                    if idx == b'\n' as usize {
671                        self.x = self.start_x;
672                        self.y -= if self.flip {
673                            -self.height - self.line_space
674                        } else {
675                            self.height + self.line_space
676                        };
677                        continue;
678                    }
679                    let idx2 = idx << 1;
680                    // Read glyph offsets from font with short-lived borrow
681                    let bg = value_le(self.active_font(), self.indices + idx2) as usize;
682                    let eg = value_le(self.active_font(), self.indices + idx2 + 2) as usize;
683                    self.bglyph = self.glyphs + bg;
684                    self.eglyph = self.glyphs + eg;
685                    self.status = Status::StartGlyph;
686                    // fallthrough to StartGlyph
687                    continue;
688                }
689                Status::StartGlyph => {
690                    *x = self.x;
691                    *y = self.y;
692                    self.status = Status::Glyph;
693                    return PATH_CMD_MOVE_TO;
694                }
695                Status::Glyph => {
696                    if self.bglyph >= self.eglyph {
697                        self.status = Status::NextChar;
698                        self.x += self.space;
699                        continue;
700                    }
701                    // Read glyph bytes with short-lived borrow
702                    let (dx_byte, yc_raw) = {
703                        let f = self.active_font();
704                        (f[self.bglyph], f[self.bglyph + 1])
705                    };
706                    self.bglyph += 2;
707
708                    let dx = dx_byte as i8;
709                    let yf = yc_raw & 0x80;
710                    // Sign-extend the lower 7 bits: shift left 1 then
711                    // arithmetic shift right 1 (matching C++ `yc <<= 1; yc >>= 1`)
712                    let yc = ((yc_raw as i8) << 1) >> 1;
713                    let dy = yc as i32;
714
715                    self.x += dx as f64 * self.w;
716                    self.y += dy as f64 * self.h;
717                    *x = self.x;
718                    *y = self.y;
719                    return if yf != 0 {
720                        PATH_CMD_MOVE_TO
721                    } else {
722                        PATH_CMD_LINE_TO
723                    };
724                }
725            }
726        }
727    }
728}
729
730// ============================================================================
731// GsvTextOutline — stroked text with transformation
732// ============================================================================
733
734/// Stroked text outline with optional transformation.
735///
736/// Composes `ConvStroke<GsvText>` (for stroke width) with
737/// `ConvTransform<ConvStroke<GsvText>>` (for affine transform).
738///
739/// Port of C++ `gsv_text_outline<Transformer>`.
740pub struct GsvTextOutline {
741    polyline: ConvTransform<ConvStroke<GsvText>>,
742}
743
744impl GsvTextOutline {
745    pub fn new(text: GsvText, trans: TransAffine) -> Self {
746        let stroke = ConvStroke::new(text);
747        let ct = ConvTransform::new(stroke, trans);
748        Self { polyline: ct }
749    }
750
751    pub fn set_width(&mut self, w: f64) {
752        self.polyline.source_mut().set_width(w);
753    }
754
755    pub fn set_transform(&mut self, trans: TransAffine) {
756        self.polyline.set_transform(trans);
757    }
758
759    /// Access the inner GsvText for setting text, size, etc.
760    pub fn text_mut(&mut self) -> &mut GsvText {
761        self.polyline.source_mut().source_mut()
762    }
763}
764
765impl VertexSource for GsvTextOutline {
766    fn rewind(&mut self, path_id: u32) {
767        self.polyline.rewind(path_id);
768        // Set round join and cap like C++ does
769        self.polyline.source_mut().set_line_join(LineJoin::Round);
770        self.polyline.source_mut().set_line_cap(LineCap::Round);
771    }
772
773    fn vertex(&mut self, x: &mut f64, y: &mut f64) -> u32 {
774        self.polyline.vertex(x, y)
775    }
776}
777
778// ============================================================================
779// Tests
780// ============================================================================
781
782#[cfg(test)]
783mod tests {
784    use super::*;
785    use crate::basics::{is_move_to, is_stop, is_vertex};
786
787    #[test]
788    fn test_new_defaults() {
789        let t = GsvText::new();
790        assert_eq!(t.width, 10.0);
791        assert_eq!(t.height, 0.0);
792        assert_eq!(t.space, 0.0);
793        assert!(!t.flip);
794    }
795
796    #[test]
797    fn test_empty_text_produces_stop() {
798        let mut t = GsvText::new();
799        t.size(24.0, 0.0);
800        t.rewind(0);
801        let mut x = 0.0;
802        let mut y = 0.0;
803        let cmd = t.vertex(&mut x, &mut y);
804        assert!(is_stop(cmd));
805    }
806
807    #[test]
808    fn test_single_char_produces_vertices() {
809        let mut t = GsvText::new();
810        t.size(24.0, 0.0);
811        t.start_point(0.0, 0.0);
812        t.text("A");
813        t.rewind(0);
814
815        let mut x = 0.0;
816        let mut y = 0.0;
817        // First vertex should be a move_to
818        let cmd = t.vertex(&mut x, &mut y);
819        assert!(is_move_to(cmd));
820
821        // Should produce more vertices (the glyph strokes)
822        let mut count = 1;
823        loop {
824            let cmd = t.vertex(&mut x, &mut y);
825            if is_stop(cmd) {
826                break;
827            }
828            assert!(is_vertex(cmd) || is_move_to(cmd));
829            count += 1;
830        }
831        assert!(count > 3, "Expected multiple vertices for 'A', got {count}");
832    }
833
834    #[test]
835    fn test_start_point() {
836        let mut t = GsvText::new();
837        t.size(24.0, 0.0);
838        t.start_point(100.0, 200.0);
839        t.text("A");
840        t.rewind(0);
841
842        let mut x = 0.0;
843        let mut y = 0.0;
844        let cmd = t.vertex(&mut x, &mut y);
845        assert!(is_move_to(cmd));
846        // The first move_to position should reflect start_point + glyph origin offset
847        // (glyph 'A' starts with dx,dy offsets from origin)
848        // We just verify it's in the neighborhood of (100, 200)
849        assert!(x > 50.0 && x < 200.0);
850        assert!(y > 100.0 && y < 300.0);
851    }
852
853    #[test]
854    fn test_multi_char_text() {
855        let mut t = GsvText::new();
856        t.size(24.0, 0.0);
857        t.start_point(0.0, 0.0);
858        t.text("AB");
859        t.rewind(0);
860
861        let mut x = 0.0;
862        let mut y = 0.0;
863        let mut count = 0;
864        loop {
865            let cmd = t.vertex(&mut x, &mut y);
866            if is_stop(cmd) {
867                break;
868            }
869            count += 1;
870        }
871        // "AB" should produce more vertices than just "A"
872        let mut t2 = GsvText::new();
873        t2.size(24.0, 0.0);
874        t2.start_point(0.0, 0.0);
875        t2.text("A");
876        t2.rewind(0);
877        let mut count_a = 0;
878        loop {
879            let cmd = t2.vertex(&mut x, &mut y);
880            if is_stop(cmd) {
881                break;
882            }
883            count_a += 1;
884        }
885        assert!(count > count_a, "AB should produce more vertices than A");
886    }
887
888    #[test]
889    fn test_text_width() {
890        let mut t = GsvText::new();
891        t.size(24.0, 0.0);
892        t.start_point(0.0, 0.0);
893        t.text("Hello");
894        let w = t.text_width();
895        assert!(w > 0.0, "text_width should be positive for non-empty text");
896    }
897
898    #[test]
899    fn test_text_width_longer_is_wider() {
900        let mut t1 = GsvText::new();
901        t1.size(24.0, 0.0);
902        t1.start_point(0.0, 0.0);
903        t1.text("Hi");
904        let w1 = t1.text_width();
905
906        let mut t2 = GsvText::new();
907        t2.size(24.0, 0.0);
908        t2.start_point(0.0, 0.0);
909        t2.text("Hello World");
910        let w2 = t2.text_width();
911
912        assert!(w2 > w1, "Longer text should be wider: {w2} vs {w1}");
913    }
914
915    #[test]
916    fn test_size_affects_output() {
917        let mut t1 = GsvText::new();
918        t1.size(12.0, 0.0);
919        t1.start_point(0.0, 0.0);
920        t1.text("A");
921        let w1 = t1.text_width();
922
923        let mut t2 = GsvText::new();
924        t2.size(24.0, 0.0);
925        t2.start_point(0.0, 0.0);
926        t2.text("A");
927        let w2 = t2.text_width();
928
929        // Doubling height should approximately double width (proportional)
930        assert!(
931            (w2 / w1 - 2.0).abs() < 0.1,
932            "Double height should double width: w2/w1 = {}",
933            w2 / w1
934        );
935    }
936
937    #[test]
938    fn test_flip() {
939        let mut t = GsvText::new();
940        t.size(24.0, 0.0);
941        t.start_point(0.0, 100.0);
942        t.flip(true);
943        t.text("A");
944        t.rewind(0);
945
946        let mut x = 0.0;
947        let mut y = 0.0;
948        t.vertex(&mut x, &mut y);
949        // With flip, the y direction is inverted relative to non-flipped
950        // Just verify it produces vertices
951        let mut has_vertex = true;
952        let cmd = t.vertex(&mut x, &mut y);
953        if is_stop(cmd) {
954            has_vertex = false;
955        }
956        assert!(has_vertex);
957    }
958
959    #[test]
960    fn test_rewind_resets() {
961        let mut t = GsvText::new();
962        t.size(24.0, 0.0);
963        t.start_point(0.0, 0.0);
964        t.text("A");
965
966        // First pass
967        t.rewind(0);
968        let mut x1 = 0.0;
969        let mut y1 = 0.0;
970        t.vertex(&mut x1, &mut y1);
971
972        // Rewind and try again
973        t.rewind(0);
974        let mut x2 = 0.0;
975        let mut y2 = 0.0;
976        t.vertex(&mut x2, &mut y2);
977
978        assert_eq!(x1, x2);
979        assert_eq!(y1, y2);
980    }
981
982    #[test]
983    fn test_newline_resets_x() {
984        let mut t = GsvText::new();
985        t.size(24.0, 0.0);
986        t.start_point(100.0, 200.0);
987        t.text("A\nB");
988        t.rewind(0);
989
990        let mut x = 0.0;
991        let mut y = 0.0;
992
993        // Read through all vertices of 'A'
994        loop {
995            let cmd = t.vertex(&mut x, &mut y);
996            if is_stop(cmd) {
997                break;
998            }
999        }
1000        // After the newline, we should have read 'B' too
1001        // Re-verify by checking text produces valid output
1002        t.rewind(0);
1003        let mut count = 0;
1004        loop {
1005            let cmd = t.vertex(&mut x, &mut y);
1006            if is_stop(cmd) {
1007                break;
1008            }
1009            count += 1;
1010        }
1011        assert!(count > 0);
1012    }
1013
1014    #[test]
1015    fn test_gsv_text_outline_basic() {
1016        let mut text = GsvText::new();
1017        text.size(24.0, 0.0);
1018        text.start_point(0.0, 0.0);
1019        text.text("Hi");
1020
1021        let mut outline = GsvTextOutline::new(text, TransAffine::new());
1022        outline.set_width(1.0);
1023        outline.rewind(0);
1024
1025        let mut x = 0.0;
1026        let mut y = 0.0;
1027        let mut count = 0;
1028        loop {
1029            let cmd = outline.vertex(&mut x, &mut y);
1030            if is_stop(cmd) {
1031                break;
1032            }
1033            count += 1;
1034        }
1035        assert!(
1036            count > 10,
1037            "Stroked text outline should produce many vertices, got {count}"
1038        );
1039    }
1040
1041    #[test]
1042    fn test_font_data_valid() {
1043        // Verify the font data has a valid structure
1044        let font = GSV_DEFAULT_FONT;
1045        assert!(
1046            font.len() > 520,
1047            "Font should have index table + glyph data"
1048        );
1049        let idx_offset = value_le(font, 0) as usize;
1050        let base_height = value_le(font, 4);
1051        assert!(idx_offset > 0 && idx_offset < font.len());
1052        assert!(base_height > 0);
1053        // Index table should fit within font data
1054        assert!(idx_offset + 257 * 2 <= font.len());
1055    }
1056
1057    #[test]
1058    fn test_space_character_advances() {
1059        // Space character should advance position without drawing
1060        let mut t = GsvText::new();
1061        t.size(24.0, 0.0);
1062        t.start_point(0.0, 0.0);
1063        t.text("A B");
1064        let w_with_space = t.text_width();
1065
1066        let mut t2 = GsvText::new();
1067        t2.size(24.0, 0.0);
1068        t2.start_point(0.0, 0.0);
1069        t2.text("AB");
1070        let w_without_space = t2.text_width();
1071
1072        assert!(
1073            w_with_space > w_without_space,
1074            "Text with space should be wider"
1075        );
1076    }
1077}