1use super::cluster::{Glyph, GlyphInfo};
2use super::feature::*;
3use crate::text::{
4 cluster::{Char, CharCluster, ClusterInfo, ShapeClass, SourceRange, MAX_CLUSTER_SIZE},
5 JoiningType,
6};
7
8use alloc::vec::Vec;
9use core::ops::Range;
10
11pub const SUBSTITUTED: u16 = 1;
13pub const LIGATED: u16 = 2;
14pub const COMPONENT: u16 = 4;
15pub const MARK_ATTACH: u16 = 8;
16pub const CURSIVE_ATTACH: u16 = 16;
17pub const IGNORABLE: u16 = 64;
18
19#[derive(Copy, Clone, Default, Debug)]
21pub struct GlyphData {
22 pub id: u16,
23 pub flags: u16,
24 pub class: u8,
25 pub char_class: ShapeClass,
26 pub mark_type: u8,
27 pub joining_type: u8,
28 pub mask: u8,
29 pub skip: bool,
30 pub component: u8,
31 pub cluster: u32,
32 pub data: u32,
33}
34
35impl GlyphData {
36 pub fn is_component(&self) -> bool {
37 self.flags & COMPONENT != 0
38 }
39}
40
41#[derive(Copy, Clone, Default, Debug)]
43pub struct PositionData {
44 pub base: u8,
45 pub flags: u16,
46 pub x: f32,
47 pub y: f32,
48 pub advance: f32,
49}
50
51impl Glyph {
52 pub(super) fn new(g: &GlyphData, p: &PositionData) -> Self {
53 Self {
54 id: g.id,
55 info: GlyphInfo(p.flags),
56 x: p.x,
57 y: p.y,
58 advance: p.advance,
59 data: g.data,
60 }
61 }
62}
63
64#[derive(Clone, Default)]
65pub struct Buffer {
66 pub glyphs: Vec<GlyphData>,
67 pub positions: Vec<PositionData>,
68 pub infos: Vec<(ClusterInfo, bool, u32)>,
69 pub ranges: Vec<SourceRange>,
70 pub shaped_glyphs: Vec<Glyph>,
71 pub is_rtl: bool,
72 pub dotted_circle: Option<u16>,
73 pub has_cursive: bool,
74 pub has_marks: bool,
75 pub reversed: bool,
76 pub next_cluster: u32,
77 pub skip_state: SkipState,
78 pub sub_args: Vec<u16>,
79 pub pos_args: Vec<u16>,
80}
81
82#[derive(Copy, Clone, PartialEq, Eq, Default)]
83pub struct SkipState {
84 pub flags: u8,
85 pub mask: u8,
86 pub mark_check: u8,
87 pub mark_class: u8,
88 pub mark_set: u32,
89}
90
91impl Buffer {
92 pub fn new() -> Self {
93 Self::default()
94 }
95
96 pub fn len(&self) -> usize {
97 self.glyphs.len()
98 }
99
100 pub fn push(&mut self, cluster: &CharCluster) -> Range<usize> {
101 let start = self.glyphs.len();
102 let chars = cluster.mapped_chars();
103 if cluster.info().is_broken() {
104 if let Some(id) = self.dotted_circle {
105 let first = &chars[0];
106 self.push_char(&Char {
107 ch: '\u{25cc}',
108 shape_class: ShapeClass::Base,
109 joining_type: JoiningType::U,
110 ignorable: false,
111 contributes_to_shaping: true,
112 glyph_id: id,
113 offset: first.offset,
114 data: first.data,
115 });
116 }
117 }
118 for ch in chars {
119 self.push_char(ch);
120 }
121 self.next_cluster += 1;
122 self.push_cluster(cluster);
123 start..self.glyphs.len()
124 }
125
126 pub fn push_order(&mut self, cluster: &CharCluster, order: &[usize]) -> Range<usize> {
127 let start = self.glyphs.len();
128 let chars = cluster.mapped_chars();
129 if cluster.info().is_broken() {
130 if let Some(id) = self.dotted_circle {
131 let first = &chars[order[0]];
132 self.push_char(&Char {
133 ch: '\u{25cc}',
134 shape_class: ShapeClass::Base,
135 joining_type: JoiningType::U,
136 ignorable: false,
137 contributes_to_shaping: true,
138 glyph_id: id,
139 offset: first.offset,
140 data: first.data,
141 });
142 }
143 }
144 for ch in order[..chars.len()].iter().map(|i| &chars[*i]) {
145 self.push_char(ch);
146 }
147 self.next_cluster += 1;
148 self.push_cluster(cluster);
149 start..self.glyphs.len()
150 }
151
152 pub fn _push_hangul(&mut self, cluster: &CharCluster) -> Range<usize> {
153 let start = self.glyphs.len();
154 let chars = cluster.mapped_chars();
155 if cluster.info().is_broken() {
156 if let Some(id) = self.dotted_circle {
157 let first = &chars[0];
158 self.push_char(&Char {
159 ch: '\u{25cc}',
160 shape_class: ShapeClass::Base,
161 joining_type: JoiningType::U,
162 ignorable: false,
163 contributes_to_shaping: true,
164 glyph_id: id,
165 offset: first.offset,
166 data: first.data,
167 });
168 }
169 }
170 for ch in chars {
171 self._push_hangul_char(ch);
172 }
173 self.next_cluster += 1;
174 self.push_cluster(cluster);
175 start..self.glyphs.len()
176 }
177
178 #[inline(always)]
179 fn push_char(&mut self, ch: &Char) {
180 let cluster = self.next_cluster;
181 self.glyphs.push(GlyphData {
182 id: ch.glyph_id,
183 flags: (ch.ignorable as u16) << 6,
184 class: 0,
185 char_class: ch.shape_class,
186 joining_type: ch.joining_type as u8,
187 mark_type: 0,
188 mask: 0,
189 skip: false,
190 component: !0,
191 cluster,
192 data: ch.data,
193 });
194 }
195
196 fn _push_hangul_char(&mut self, ch: &Char) {
197 let cluster = self.next_cluster;
198 let c = ch.ch as u32;
199 let mask = if (0x1100..=0x115F).contains(&c) || (0xA960..=0xA97C).contains(&c) {
200 1
201 } else if (0x1160..=0x11A7).contains(&c) || (0xD7B0..=0xD7C6).contains(&c) {
202 2
203 } else if (0x11A8..=0x11FF).contains(&c) || (0xD7CB..=0xD7FB).contains(&c) {
204 4
205 } else {
206 1 | 2 | 4
207 };
208 self.glyphs.push(GlyphData {
209 id: ch.glyph_id,
210 flags: (ch.ignorable as u16) << 6,
211 class: 0,
212 char_class: ch.shape_class,
213 joining_type: ch.joining_type as u8,
214 mark_type: 0,
215 mask,
216 skip: false,
217 component: !0,
218 cluster,
219 data: ch.data,
220 });
221 }
222
223 fn push_cluster(&mut self, cluster: &CharCluster) {
224 self.infos
225 .push((cluster.info(), false, cluster.user_data()));
226 self.ranges.push(cluster.range());
227 }
228
229 pub fn clear(&mut self) {
230 self.glyphs.clear();
231 self.positions.clear();
232 self.infos.clear();
233 self.ranges.clear();
234 self.is_rtl = false;
235 self.reversed = false;
236 self.has_cursive = false;
237 self.has_marks = false;
238 self.dotted_circle = None;
239 self.next_cluster = 0;
240 self.skip_state = SkipState::default();
241 }
242
243 pub fn ensure_order(&mut self, reversed: bool) {
244 if reversed != self.reversed {
245 self.glyphs.reverse();
246 if !self.positions.is_empty() {
247 self.positions.reverse();
248 }
249 self.reversed = reversed;
250 }
251 }
252
253 pub fn clear_flags(&mut self, flags: u16, range: Option<Range<usize>>) {
254 if let Some(range) = range {
255 for g in &mut self.glyphs[range] {
256 g.flags &= !flags;
257 }
258 } else {
259 for g in &mut self.glyphs {
260 g.flags &= !flags;
261 }
262 }
263 }
264
265 pub fn setup_positions(&mut self, was_morx: bool) {
266 if was_morx {
267 self.glyphs
268 .retain(|g| g.flags & COMPONENT == 0 && g.id != 0xFFFF);
269 } else {
270 self.glyphs.retain(|g| g.flags & COMPONENT == 0);
271 }
272 self.positions.clear();
273 self.positions
274 .resize(self.glyphs.len(), PositionData::default());
275 }
276
277 pub fn substitute(&mut self, index: usize, id: u16) {
278 let g = &mut self.glyphs[index];
279 g.id = id;
283 g.flags |= SUBSTITUTED;
284 }
285
286 pub fn substitute_ligature(&mut self, index: usize, id: u16, components: &[usize]) {
287 if components.is_empty() {
295 return;
296 }
297 let g = &mut self.glyphs[index];
298 g.id = id;
299 g.flags |= SUBSTITUTED | LIGATED;
300 let cluster = g.cluster;
301 let mut last_index = index;
302 for (i, &index) in components.iter().enumerate() {
303 let g = &mut self.glyphs[index];
304 self.infos[g.cluster as usize].1 = true;
305 g.id = 0xFFFF;
306 g.flags |= COMPONENT;
307 g.class = 5;
308 g.cluster = cluster;
309 g.skip = true;
310 if (index - last_index) > 1 {
311 let component = i as u8;
312 for g in &mut self.glyphs[last_index + 1..index] {
313 if g.mark_type != 0 || g.class == 3 {
314 g.component = component;
315 g.cluster = cluster;
316 }
317 }
318 }
319 last_index = index;
320 }
321 if (last_index + 1) < self.glyphs.len() {
322 let last_component = components.len() as u8;
323 for g in &mut self.glyphs[last_index + 1..] {
324 if g.mark_type != 0 || g.class == 3 {
325 g.component = last_component;
326 g.cluster = cluster;
327 } else {
328 break;
329 }
330 }
331 }
332 }
333
334 pub fn substitute_multiple(&mut self, index: usize, ids: &[u16]) {
335 let count = ids.len();
336 if count == 0 {
337 self.glyphs.remove(index);
338 return;
339 } else if count == 1 {
340 self.substitute(index, ids[0]);
341 return;
342 }
343 let g = self.glyphs[index];
347 self.glyphs
348 .splice(index..index + 1, SubstIter { ids, g, cur: 0 });
349 }
350
351 pub fn multiply(&mut self, index: usize, count: usize) {
352 let g = self
353 .glyphs
354 .get(index)
355 .copied()
356 .unwrap_or_else(GlyphData::default);
357 self.glyphs.splice(index..index, (0..count).map(|_| g));
358 }
359
360 pub fn position(&mut self, index: usize, x: f32, y: f32, xadvance: f32, _yadvance: f32) {
361 let p = &mut self.positions[index];
362 p.x += x;
363 p.y += y;
364 p.advance += xadvance;
365 }
366
367 pub fn position_cursive(&mut self, index: usize, next: usize, x: f32, y: f32) {
368 let p = &mut self.positions[index];
369 self.has_cursive = true;
370 p.flags = CURSIVE_ATTACH;
371 if true {
372 p.y = y;
374 } else {
376 p.x = x;
377 }
378 p.base = (next - index) as u8;
379 }
380
381 pub fn position_mark(&mut self, index: usize, base: usize, dx: f32, dy: f32) {
382 let p = &mut self.positions[index];
383 self.has_marks = true;
384 p.flags = MARK_ATTACH;
385 p.base = (index - base) as u8;
386 p.x = dx;
387 p.y = dy;
388 }
389
390 pub fn set_join_masks(&mut self) {
391 let mut prev: Option<usize> = None;
392 let mut state = 0;
393 let glyphs = &mut self.glyphs;
394 let len = glyphs.len();
395 const JOIN_T: u8 = 6;
397 for i in 0..len {
398 let ty = glyphs[i].joining_type;
399 if ty == JOIN_T {
400 continue;
401 }
402 let entry = JOIN_STATES[state][ty as usize];
403 if let Some(j) = prev {
404 if entry.0 != NONE_MASK {
405 glyphs[j].mask = entry.0;
406 }
407 }
408 glyphs[i].mask = entry.1;
409 prev = Some(i);
410 state = entry.2 as usize;
411 }
412 }
413}
414
415struct SubstIter<'a> {
416 ids: &'a [u16],
417 g: GlyphData,
418 cur: usize,
419}
420
421impl<'a> Iterator for SubstIter<'a> {
422 type Item = GlyphData;
423
424 fn size_hint(&self) -> (usize, Option<usize>) {
425 let remaining = self.ids.len() - self.cur;
426 (remaining, Some(remaining))
427 }
428
429 fn next(&mut self) -> Option<Self::Item> {
430 if self.cur >= self.ids.len() {
431 return None;
432 }
433 let g = GlyphData {
434 id: self.ids[self.cur],
435 flags: SUBSTITUTED,
436 ..self.g
437 };
438 self.cur += 1;
439 Some(g)
440 }
441}
442
443pub fn reorder_myanmar(chars: &[Char], order: &mut Vec<usize>) {
444 use ShapeClass::*;
445 let mut ignored = [false; MAX_CLUSTER_SIZE];
446 let mut base = None;
447 let mut kinzi: Option<Range<usize>> = None;
448 let mut medial_ra = None;
449 let mut vpre: Option<Range<usize>> = None;
450 let mut vblw: Option<usize> = None;
451 let mut anus: Option<Range<usize>> = None;
452 let mut i = 0;
453 let mut last_vblw = false;
454 let len = chars.len();
455 if len == 0 {
456 return;
457 }
458 if order.len() < len {
459 order.resize(chars.len(), 0);
460 }
461 if chars[0].shape_class == Kinzi {
462 kinzi = Some(0..3);
463 ignored[0] = true;
464 ignored[1] = true;
465 ignored[2] = true;
466 i = 3;
467 }
468 while i < len {
469 let ch = chars[i];
470 let k = ch.shape_class;
471 if last_vblw && k == Anusvara {
472 anus = match anus {
473 Some(r) => Some(r.start..i - r.start + 1),
474 None => Some(i..i + 1),
475 };
476 ignored[i] = true;
477 i += 1;
478 continue;
479 }
480 last_vblw = false;
481 if k == VBlw {
482 if vblw.is_none() {
483 vblw = Some(i);
484 }
485 last_vblw = true;
486 }
487 if k == Base && base.is_none() {
488 base = Some(i);
489 ignored[i] = true;
490 } else if k == MedialRa {
491 medial_ra = Some(i);
492 ignored[i] = true;
493 } else if k == VPre {
494 vpre = match vpre {
495 Some(r) => Some(r.start..i - r.start + 1),
496 None => Some(i..i + 1),
497 };
498 ignored[i] = true;
499 }
500 i += 1;
501 }
502 i = 0;
503 if let Some(r) = vpre {
504 for j in r {
505 order[i] = j;
506 i += 1;
507 }
508 }
509 if let Some(j) = medial_ra {
510 order[i] = j;
511 i += 1;
512 }
513 if let Some(j) = base {
514 order[i] = j;
515 i += 1;
516 }
517 if let Some(r) = kinzi {
518 for j in r {
519 order[i] = j;
520 i += 1;
521 }
522 }
523 let mut j = 0;
524 while j < len {
525 if ignored[j] {
526 j += 1;
527 continue;
528 }
529 if Some(j) == vblw && anus.is_some() {
530 for k in anus.take().unwrap() {
531 order[i] = k;
532 i += 1;
533 }
534 }
535 order[i] = j;
536 i += 1;
537 j += 1;
538 }
539}
540
541#[allow(clippy::needless_range_loop)]
542pub fn reorder_complex(glyphs: &mut [GlyphData], buf: &mut Vec<GlyphData>, order: &mut Vec<usize>) {
543 use ShapeClass::*;
544 let mut first_base = None;
545 let mut last_base = None;
546 let mut last_halant = None;
547 let mut reph = None;
548 let mut pref = None;
549 let mut vpre: Option<Range<usize>> = None;
550 let mut vmpre: Option<Range<usize>> = None;
551 let mut ignored = [false; 64];
552 let len = glyphs.len();
553 if buf.len() < glyphs.len() {
554 buf.resize(len, GlyphData::default());
555 }
556 let buf = &mut buf[..len];
557 if order.len() < len {
558 order.resize(len, 0);
559 }
560 let order = &mut order[..len];
561 for (i, g) in glyphs.iter().enumerate() {
562 if g.is_component() {
563 continue;
564 }
565 match g.char_class {
566 Base => {
567 if first_base.is_none() {
568 first_base = Some(i);
569 ignored[i] = true;
570 }
571 if last_halant.is_none() {
572 last_base = Some(i);
573 }
574 }
575 Halant => {
576 last_halant = Some(i);
577 }
578 Reph => {
579 if reph.is_none() {
580 reph = Some(i);
581 ignored[i] = true;
582 }
583 }
584 Pref => {
585 if pref.is_none() {
586 pref = Some(i);
587 ignored[i] = true;
588 }
589 }
590 VPre => {
591 vpre = match vpre {
592 Some(r) => Some(r.start..i - r.start + 1),
593 None => Some(i..i + 1),
594 };
595 ignored[i] = true;
596 }
597 VMPre => {
598 vmpre = match vmpre {
599 Some(r) => Some(r.start..i - r.start + 1),
600 None => Some(i..i + 1),
601 };
602 ignored[i] = true;
603 }
604 _ => {}
605 }
606 }
607 let mut j = 0;
608 if last_halant.is_none() {
610 if let Some(r) = vmpre.clone() {
611 for i in r {
612 order[j] = i;
613 j += 1;
614 }
615 }
616 if let Some(r) = vpre.clone() {
617 for i in r {
618 order[j] = i;
619 j += 1;
620 }
621 }
622 if let Some(i) = pref {
623 order[j] = i;
624 j += 1;
625 }
626 }
627 if let Some(i) = first_base {
629 order[j] = i;
630 j += 1;
631 }
632 if last_base.is_none() {
633 if let Some(i) = reph {
635 order[j] = i;
636 j += 1;
637 }
638 }
639 let len = glyphs.len();
641 for i in 0..len {
642 if ignored[i] {
643 continue;
644 }
645 order[j] = i;
649 j += 1;
650 if Some(i) == last_base {
652 if let Some(i) = reph {
653 order[j] = i;
654 j += 1;
655 }
656 }
657 if Some(i) == last_halant {
659 if let Some(r) = vmpre.clone() {
660 for i in r {
661 order[j] = i;
662 j += 1;
663 }
664 }
665 if let Some(r) = vpre.clone() {
666 for i in r {
667 order[j] = i;
668 j += 1;
669 }
670 }
671 if let Some(i) = pref {
672 order[j] = i;
673 j += 1;
674 }
675 }
676 }
677 buf.copy_from_slice(glyphs);
679 for (i, j) in order.iter().enumerate() {
680 glyphs[i] = buf[*j];
681 }
682 }
689
690#[rustfmt::skip]
692const JOIN_STATES: [[(u8, u8, u8); 6]; 7] = [
693 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,ISOL_MASK,1), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,ISOL_MASK,1), (NONE_MASK,ISOL_MASK,6), ],
696 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,ISOL_MASK,1), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,FIN2_MASK,5), (NONE_MASK,ISOL_MASK,6), ],
698 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (INIT_MASK,FINA_MASK,1), (INIT_MASK,FINA_MASK,3), (INIT_MASK,FINA_MASK,4), (INIT_MASK,FINA_MASK,6), ],
700 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (MEDI_MASK,FINA_MASK,1), (MEDI_MASK,FINA_MASK,3), (MEDI_MASK,FINA_MASK,4), (MEDI_MASK,FINA_MASK,6), ],
702 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (MED2_MASK,ISOL_MASK,1), (MED2_MASK,ISOL_MASK,2), (MED2_MASK,FIN2_MASK,5), (MED2_MASK,ISOL_MASK,6), ],
704 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (ISOL_MASK,ISOL_MASK,1), (ISOL_MASK,ISOL_MASK,2), (ISOL_MASK,FIN2_MASK,5), (ISOL_MASK,ISOL_MASK,6), ],
706 [ (NONE_MASK,NONE_MASK,0), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,ISOL_MASK,1), (NONE_MASK,ISOL_MASK,2), (NONE_MASK,FIN3_MASK,5), (NONE_MASK,ISOL_MASK,6), ]
708];