1use makepad_font::{Font, Glyph, HorizontalMetrics, Outline, OutlinePoint};
2use makepad_geometry::{
3 AffineTransformation, LinearTransformation, Point, Rectangle, Transform, Vector,
4};
5use makepad_internal_iter::ExtendFromInternalIterator;
6use std::{mem, result};
7
8#[derive(Clone, Debug)]
9pub struct GlyphsParser<'a> {
10 glyphs: Vec<Option<Glyph>>,
11 advance_width_count: usize,
12 hmtx_table_bytes: &'a [u8],
13 index_to_loc_format: IndexToLocFormat,
14 loca_table_bytes: &'a [u8],
15 glyf_table_bytes: &'a [u8],
16}
17
18impl<'a> GlyphsParser<'a> {
19 fn new(
20 glyphs_count: usize,
21 advance_width_count: usize,
22 hmtx_table_bytes: &'a [u8],
23 index_to_loc_format: IndexToLocFormat,
24 loca_table_bytes: &'a [u8],
25 glyf_table_bytes: &'a [u8],
26 ) -> GlyphsParser<'a> {
27 GlyphsParser {
28 glyphs: vec![None; glyphs_count],
29 advance_width_count,
30 hmtx_table_bytes,
31 index_to_loc_format,
32 loca_table_bytes,
33 glyf_table_bytes,
34 }
35 }
36
37 fn parse_glyphs(mut self) -> Result<Vec<Glyph>> {
38 for index in 0..self.glyphs.len() {
39 self.get_or_parse_glyph(index)?;
40 }
41 Ok(self
42 .glyphs
43 .into_iter()
44 .map(|glyph| glyph.unwrap())
45 .collect())
46 }
47
48 fn get_or_parse_glyph(&mut self, index: usize) -> Result<&Glyph> {
49 if !self
50 .glyphs
51 .get(index)
52 .map_or(false, |glyphs| glyphs.is_some())
53 {
54 self.glyphs.resize(index + 1, None);
55 self.glyphs[index] = Some(self.parse_glyph(index)?);
56 }
57 Ok(self.glyphs[index].as_ref().unwrap())
58 }
59
60 fn parse_glyph(&mut self, index: usize) -> Result<Glyph> {
61 let start = self.parse_offset(index)?;
62 let end = self.parse_offset(index + 1)?;
63 let bytes = &self.glyf_table_bytes[start..end];
64 let horizontal_metrics = self.parse_horizontal_metrics(index)?;
65 Ok(if bytes.is_empty() {
66 Glyph {
67 horizontal_metrics,
68 bounds: Rectangle::default(),
69 outline: Outline::new(),
70 }
71 } else {
72 let mut reader = Reader::new(&bytes);
73 let contour_count = reader.read_i16()?;
74 let bounds = Rectangle::new(
75 Point::new(reader.read_i16()? as f32, reader.read_i16()? as f32),
76 Point::new(reader.read_i16()? as f32, reader.read_i16()? as f32),
77 );
78 let bytes = &bytes[10..];
79 if contour_count >= 0 {
80 Self::parse_simple_glyph(bytes, horizontal_metrics, bounds, contour_count as usize)?
81 } else {
82 self.parse_composite_glyph(bytes, horizontal_metrics, bounds)?
83 }
84 })
85 }
86
87 fn parse_offset(&self, index: usize) -> Result<usize> {
88 let mut reader = Reader::new(&self.loca_table_bytes);
89 Ok(match self.index_to_loc_format {
90 IndexToLocFormat::Short => {
91 reader.skip(index * 2)?;
92 reader.read_u16()? as usize * 2
93 }
94 IndexToLocFormat::Long => {
95 reader.skip(index * 4)?;
96 reader.read_u32()? as usize
97 }
98 })
99 }
100
101 fn parse_horizontal_metrics(&self, index: usize) -> Result<HorizontalMetrics> {
102 let mut reader = Reader::new(self.hmtx_table_bytes);
103 if index < self.advance_width_count {
104 reader.skip(index * 4)?;
105 Ok(HorizontalMetrics {
106 advance_width: reader.read_u16()? as f32,
107 left_side_bearing: reader.read_i16()? as f32,
108 })
109 } else {
110 reader.skip((self.advance_width_count - 1) * 4)?;
111 let advance_width = reader.read_u16()? as f32;
112 reader.skip(2)?;
113 reader.skip((index - self.advance_width_count) * 2)?;
114 Ok(HorizontalMetrics {
115 advance_width,
116 left_side_bearing: reader.read_i16()? as f32,
117 })
118 }
119 }
120
121 fn parse_simple_glyph(
122 bytes: &'a [u8],
123 horizontal_metrics: HorizontalMetrics,
124 bounds: Rectangle,
125 contour_count: usize,
126 ) -> Result<Glyph> {
127 let mut reader = Reader::new(bytes);
128 reader.skip((contour_count - 1) * mem::size_of::<u16>())?;
129 let point_count = reader.read_u16()? as usize + 1;
130 let instruction_count = reader.read_u16()? as usize;
131 reader.skip(instruction_count)?;
132 let mut flags_bytes_count = 0;
133 let mut x_coordinates_bytes_count = 0;
134 let mut y_coordinates_bytes_count = 0;
135 let mut flags_count = point_count;
136 while flags_count > 0 {
137 let flags = SimpleGlyphFlags(reader.read_u8()?);
138 let repeat_count = if flags.repeat_flag() {
139 flags_bytes_count += 2;
140 1 + reader.read_u8()? as usize
141 } else {
142 flags_bytes_count += 1;
143 1
144 };
145 if repeat_count > flags_count {
146 return Err(Error);
147 }
148 if flags.x_short_vector() {
149 x_coordinates_bytes_count += repeat_count;
150 } else if !flags.x_is_same_or_positive_x_short_vector() {
151 x_coordinates_bytes_count += repeat_count * mem::size_of::<i16>();
152 }
153 if flags.y_short_vector() {
154 y_coordinates_bytes_count += repeat_count;
155 } else if !flags.y_is_same_or_positive_y_short_vector() {
156 y_coordinates_bytes_count += repeat_count * mem::size_of::<i16>();
157 }
158 flags_count -= repeat_count;
159 }
160 let instructions_bytes_start = (contour_count + 1) * mem::size_of::<u16>();
161 let flags_bytes_start = instructions_bytes_start + instruction_count;
162 let x_coordinates_bytes_start = flags_bytes_start + flags_bytes_count;
163 let y_coordinates_bytes_start = x_coordinates_bytes_start + x_coordinates_bytes_count;
164 if y_coordinates_bytes_count > bytes.len() - y_coordinates_bytes_start {
165 return Err(Error);
166 }
167 let mut end_pts_for_contours_reader = Reader::new(&bytes[..instructions_bytes_start]);
168 let mut point_reader = OutlinePointReader::new(
169 &bytes[flags_bytes_start..x_coordinates_bytes_start],
170 &bytes[x_coordinates_bytes_start..y_coordinates_bytes_start],
171 &bytes[y_coordinates_bytes_start..],
172 );
173 let mut outline = Outline::new();
174 let mut start = 0;
175 for _ in 0..contour_count {
176 let end = end_pts_for_contours_reader.read_u16()? as usize + 1;
177 let mut contour = outline.begin_contour();
178 for _ in 0..(end - start) {
179 contour.push(point_reader.read_outline_point()?);
180 }
181 contour.end();
182 start = end;
183 }
184 Ok(Glyph {
185 horizontal_metrics,
186 bounds,
187 outline,
188 })
189 }
190
191 fn parse_composite_glyph(
192 &mut self,
193 bytes: &'a [u8],
194 mut horizontal_metrics: HorizontalMetrics,
195 bounds: Rectangle,
196 ) -> Result<Glyph> {
197 let mut outline = Outline::new();
198 let mut reader = Reader::new(bytes);
199 let mut flags = CompositeGlyphFlags(reader.read_u16()?);
200 loop {
201 let component_glyph = self.parse_glyph(reader.read_u16()? as usize)?;
202 if flags.use_my_metrics() {
203 horizontal_metrics = component_glyph.horizontal_metrics;
204 }
205 let (argument_1, argument_2) = if flags.arg_1_and_arg_2_are_words() {
206 (reader.read_i16()?, reader.read_i16()?)
207 } else {
208 (reader.read_i8()? as i16, reader.read_i8()? as i16)
209 };
210 let xy = if flags.we_have_a_scale() {
211 LinearTransformation::uniform_scaling(reader.read_f2dot14()?)
212 } else if flags.we_have_an_x_and_y_scale() {
213 LinearTransformation::scaling(Vector::new(
214 reader.read_f2dot14()?,
215 reader.read_f2dot14()?,
216 ))
217 } else if flags.we_have_a_two_by_two() {
218 LinearTransformation::new(
219 Vector::new(reader.read_f2dot14()?, reader.read_f2dot14()?),
220 Vector::new(reader.read_f2dot14()?, reader.read_f2dot14()?),
221 )
222 } else {
223 LinearTransformation::identity()
224 };
225 let z = if flags.args_are_xy_values() {
226 Vector::new(
227 xy.x.x.hypot(xy.y.x) * argument_1 as f32,
228 xy.x.y.hypot(xy.y.y) * argument_2 as f32,
229 )
230 } else {
231 component_glyph
232 .outline
233 .points()
234 .get(argument_2 as usize)
235 .ok_or(Error)?
236 .point
237 .transform(&xy)
238 - outline
239 .points()
240 .get(argument_1 as usize)
241 .ok_or(Error)?
242 .point
243 };
244 for component_contour in component_glyph.outline.contours() {
245 let mut contour = outline.begin_contour();
246 contour.extend_from_internal_iter(
247 component_contour
248 .points()
249 .iter()
250 .cloned()
251 .map(|point| point.transform(&AffineTransformation::new(xy, z))),
252 );
253 contour.end();
254 }
255 if !flags.more_components() {
256 break;
257 }
258 flags = CompositeGlyphFlags(reader.read_u16()?);
259 }
260 if flags.we_have_instructions() {
261 let instruction_length = reader.read_u16()? as usize;
262 reader.skip(instruction_length)?;
263 }
264 Ok(Glyph {
265 horizontal_metrics,
266 bounds,
267 outline,
268 })
269 }
270}
271
272#[derive(Clone, Copy, Debug, Hash, PartialEq)]
273enum IndexToLocFormat {
274 Short,
275 Long,
276}
277
278impl IndexToLocFormat {
279 fn from_i16(value: i16) -> Option<IndexToLocFormat> {
280 match value {
281 0 => Some(IndexToLocFormat::Short),
282 1 => Some(IndexToLocFormat::Long),
283 _ => None,
284 }
285 }
286}
287
288#[derive(Clone, Debug)]
289struct OutlinePointReader<'a> {
290 flags_reader: SimpleGlyphFlagsReader<'a>,
291 x_coordinates_reader: Reader<'a>,
292 y_coordinates_reader: Reader<'a>,
293 current_point: Point,
294}
295
296impl<'a> OutlinePointReader<'a> {
297 fn new(
298 flags_bytes: &'a [u8],
299 x_coordinates_bytes: &'a [u8],
300 y_coordinates_bytes: &'a [u8],
301 ) -> OutlinePointReader<'a> {
302 OutlinePointReader {
303 flags_reader: SimpleGlyphFlagsReader::new(flags_bytes),
304 x_coordinates_reader: Reader::new(x_coordinates_bytes),
305 y_coordinates_reader: Reader::new(y_coordinates_bytes),
306 current_point: Point::origin(),
307 }
308 }
309
310 fn read_outline_point(&mut self) -> Result<OutlinePoint> {
311 let flags = self.flags_reader.read()?;
312 self.current_point += Vector::new(
313 if flags.x_short_vector() {
314 let x = self.x_coordinates_reader.read_u8()? as f32;
315 if flags.x_is_same_or_positive_x_short_vector() {
316 x
317 } else {
318 -x
319 }
320 } else {
321 if flags.x_is_same_or_positive_x_short_vector() {
322 0.0
323 } else {
324 self.x_coordinates_reader.read_i16()? as f32
325 }
326 },
327 if flags.y_short_vector() {
328 let y = self.y_coordinates_reader.read_u8()? as f32;
329 if flags.y_is_same_or_positive_y_short_vector() {
330 y
331 } else {
332 -y
333 }
334 } else {
335 if flags.y_is_same_or_positive_y_short_vector() {
336 0.0
337 } else {
338 self.y_coordinates_reader.read_i16()? as f32
339 }
340 },
341 );
342 Ok(OutlinePoint {
343 is_on_curve: flags.on_curve_point(),
344 point: self.current_point,
345 })
346 }
347}
348
349#[derive(Clone, Debug)]
350struct SimpleGlyphFlagsReader<'a> {
351 reader: Reader<'a>,
352 flags: SimpleGlyphFlags,
353 repeat_count: usize,
354}
355
356impl<'a> SimpleGlyphFlagsReader<'a> {
357 fn new(bytes: &'a [u8]) -> SimpleGlyphFlagsReader<'a> {
358 SimpleGlyphFlagsReader {
359 reader: Reader::new(bytes),
360 flags: SimpleGlyphFlags(0),
361 repeat_count: 0,
362 }
363 }
364
365 fn read(&mut self) -> Result<SimpleGlyphFlags> {
366 if self.repeat_count == 0 {
367 self.flags = SimpleGlyphFlags(self.reader.read_u8()?);
368 self.repeat_count = if self.flags.repeat_flag() {
369 self.reader.read_u8()? as usize
370 } else {
371 0
372 };
373 } else {
374 self.repeat_count -= 1;
375 }
376 Ok(self.flags)
377 }
378}
379
380#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
381struct SimpleGlyphFlags(u8);
382
383impl SimpleGlyphFlags {
384 fn on_curve_point(self) -> bool {
385 self.0 & (1 << 0) != 0
386 }
387
388 fn x_short_vector(self) -> bool {
389 self.0 & (1 << 1) != 0
390 }
391
392 fn y_short_vector(self) -> bool {
393 self.0 & (1 << 2) != 0
394 }
395
396 fn repeat_flag(self) -> bool {
397 self.0 & (1 << 3) != 0
398 }
399
400 fn x_is_same_or_positive_x_short_vector(self) -> bool {
401 self.0 & (1 << 4) != 0
402 }
403
404 fn y_is_same_or_positive_y_short_vector(self) -> bool {
405 self.0 & (1 << 5) != 0
406 }
407}
408
409#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
410struct CompositeGlyphFlags(u16);
411
412impl CompositeGlyphFlags {
413 fn arg_1_and_arg_2_are_words(self) -> bool {
414 self.0 & (1 << 0) != 0
415 }
416
417 fn args_are_xy_values(self) -> bool {
418 self.0 & (1 << 1) != 0
419 }
420
421 fn we_have_a_scale(self) -> bool {
422 self.0 & (1 << 3) != 0
423 }
424
425 fn more_components(self) -> bool {
426 self.0 & (1 << 5) != 0
427 }
428
429 fn we_have_an_x_and_y_scale(self) -> bool {
430 self.0 & (1 << 6) != 0
431 }
432
433 fn we_have_a_two_by_two(self) -> bool {
434 self.0 & (1 << 7) != 0
435 }
436
437 fn we_have_instructions(self) -> bool {
438 self.0 & (1 << 8) != 0
439 }
440
441 fn use_my_metrics(self) -> bool {
442 self.0 & (1 << 9) != 0
443 }
444}
445
446#[derive(Clone, Debug)]
447struct Reader<'a> {
448 bytes: &'a [u8],
449}
450
451impl<'a> Reader<'a> {
452 fn new(bytes: &'a [u8]) -> Reader<'a> {
453 Reader { bytes }
454 }
455
456 fn skip(&mut self, count: usize) -> Result<()> {
457 if count > self.bytes.len() {
458 return Err(Error);
459 }
460 self.bytes = &self.bytes[count..];
461 Ok(())
462 }
463
464 fn read(&mut self, bytes: &mut [u8]) -> Result<()> {
465 if bytes.len() > self.bytes.len() {
466 return Err(Error);
467 }
468 bytes.copy_from_slice(&self.bytes[..bytes.len()]);
469 self.bytes = &self.bytes[bytes.len()..];
470 Ok(())
471 }
472
473 fn read_i8(&mut self) -> Result<i8> {
474 let mut bytes = [0; mem::size_of::<i8>()];
475 self.read(&mut bytes)?;
476 Ok(i8::from_be_bytes(bytes))
477 }
478
479 fn read_i16(&mut self) -> Result<i16> {
480 let mut bytes = [0; mem::size_of::<i16>()];
481 self.read(&mut bytes)?;
482 Ok(i16::from_be_bytes(bytes))
483 }
484
485 fn read_u8(&mut self) -> Result<u8> {
486 let mut bytes = [0; mem::size_of::<u8>()];
487 self.read(&mut bytes)?;
488 Ok(u8::from_be_bytes(bytes))
489 }
490
491 fn read_u16(&mut self) -> Result<u16> {
492 let mut bytes = [0; mem::size_of::<u16>()];
493 self.read(&mut bytes)?;
494 Ok(u16::from_be_bytes(bytes))
495 }
496
497 fn read_u32(&mut self) -> Result<u32> {
498 let mut bytes = [0; mem::size_of::<u32>()];
499 self.read(&mut bytes)?;
500 Ok(u32::from_be_bytes(bytes))
501 }
502
503 fn read_f2dot14(&mut self) -> Result<f32> {
504 Ok(self.read_i16()? as f32 / (1 << 14) as f32)
505 }
506}
507
508pub type Result<T> = result::Result<T, Error>;
509
510#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
511pub struct Error;
512
513pub fn parse_ttf(bytes: &[u8]) -> Result<Font> {
514 let mut reader = Reader::new(&bytes[0..12]);
515 let sfnt_version = reader.read_u32()?;
516 if ![0x00010000, u32::from_be_bytes(*b"true")].contains(&sfnt_version) {
517 return Err(Error);
518 }
519 let table_count = reader.read_u16()? as usize;
520 reader.skip(6)?;
521 let mut cmap_table_bytes = None;
522 let mut glyf_table_bytes = None;
523 let mut head_table_bytes = None;
524 let mut hhea_table_bytes = None;
525 let mut hmtx_table_bytes = None;
526 let mut loca_table_bytes = None;
527 let mut maxp_table_bytes = None;
528 for index in 0..table_count {
529 let mut reader = Reader::new(&bytes[(12 + index * 16)..][..16]);
530 let table_tag = reader.read_u32()?;
531 reader.skip(4)?;
532 let offset = reader.read_u32()? as usize;
533 let length = reader.read_u32()? as usize;
534 let table_bytes = &bytes[offset..][..length];
535 match &table_tag.to_be_bytes() {
536 b"cmap" => cmap_table_bytes = Some(table_bytes),
537 b"glyf" => glyf_table_bytes = Some(table_bytes),
538 b"head" => head_table_bytes = Some(table_bytes),
539 b"hhea" => hhea_table_bytes = Some(table_bytes),
540 b"hmtx" => hmtx_table_bytes = Some(table_bytes),
541 b"loca" => loca_table_bytes = Some(table_bytes),
542 b"maxp" => maxp_table_bytes = Some(table_bytes),
543 _ => {}
544 }
545 }
546 let cmap_table_bytes = cmap_table_bytes.ok_or(Error)?;
547 let glyf_table_bytes = glyf_table_bytes.ok_or(Error)?;
548 let head_table_bytes = head_table_bytes.ok_or(Error)?;
549 let hhea_table_bytes = hhea_table_bytes.ok_or(Error)?;
550 let hmtx_table_bytes = hmtx_table_bytes.ok_or(Error)?;
551 let loca_table_bytes = loca_table_bytes.ok_or(Error)?;
552 let maxp_table_bytes = maxp_table_bytes.ok_or(Error)?;
553 let mut reader = Reader::new(hhea_table_bytes);
554 reader.skip(4)?;
555 let ascender = reader.read_i16()? as f32;
556 let descender = reader.read_i16()? as f32;
557 let line_gap = reader.read_i16()? as f32;
558 reader.skip(24)?;
559 let advance_width_count = reader.read_u16()? as usize;
560 let mut reader = Reader::new(maxp_table_bytes);
561 reader.skip(4)?;
562 let glyph_count = reader.read_u16()? as usize;
563 reader.skip(26)?;
564 let mut reader = Reader::new(head_table_bytes);
565 reader.skip(18)?;
566 let units_per_em = reader.read_u16()? as f32;
567 reader.skip(16)?;
568 let bounds = Rectangle::new(
569 Point::new(reader.read_i16()? as f32, reader.read_i16()? as f32),
570 Point::new(reader.read_i16()? as f32, reader.read_i16()? as f32),
571 );
572 reader.skip(6)?;
573 let index_to_loc_format = IndexToLocFormat::from_i16(reader.read_i16()?).ok_or(Error)?;
574 reader.skip(2)?;
575 Ok(Font {
576 units_per_em,
577 ascender,
578 descender,
579 line_gap,
580 bounds,
581 char_code_to_glyph_index_map: parse_char_code_to_glyph_index_map(cmap_table_bytes)?,
582 glyphs: GlyphsParser::new(
583 glyph_count,
584 advance_width_count,
585 hmtx_table_bytes,
586 index_to_loc_format,
587 loca_table_bytes,
588 glyf_table_bytes,
589 )
590 .parse_glyphs()?,
591 })
592}
593
594fn parse_char_code_to_glyph_index_map(bytes: &[u8]) -> Result<Vec<usize>> {
595 let mut reader = Reader::new(bytes);
596 reader.skip(2)?;
597 let mut subtable_bytes = None;
598 let subtable_count = reader.read_u16()? as usize;
599 for _ in 0..subtable_count {
600 let platform_id = reader.read_u16()?;
601 let encoding_id = reader.read_u16()?;
602 let offset = reader.read_u32()? as usize;
603 if let (0, _) | (3, 1) | (3, 10) = (platform_id, encoding_id) {
604 subtable_bytes = Some(&bytes[offset..]);
605 break;
606 }
607 }
608 let subtable_bytes = subtable_bytes.ok_or(Error)?;
609 let mut reader = Reader::new(subtable_bytes);
610 let format = reader.read_u16()?;
611 let bytes = &subtable_bytes[2..];
612 match format {
613 4 => parse_char_code_to_glyph_index_map_format_4(bytes),
614 _ => Err(Error),
615 }
616}
617
618fn parse_char_code_to_glyph_index_map_format_4(bytes: &[u8]) -> Result<Vec<usize>> {
619 let mut reader = Reader::new(bytes);
620 reader.skip(4)?;
621 let seg_count = reader.read_u16()? as usize / 2;
622 let end_code_bytes_start = 12;
623 let end_code_bytes_end = end_code_bytes_start + seg_count * 2;
624 let start_code_bytes_start = end_code_bytes_end + 2;
625 let id_delta_bytes_start = start_code_bytes_start + seg_count * 2;
626 let id_range_offset_bytes_start = id_delta_bytes_start + seg_count * 2;
627 let end_code_bytes = &bytes[end_code_bytes_start..end_code_bytes_end];
628 let start_code_bytes = &bytes[start_code_bytes_start..id_delta_bytes_start];
629 let id_delta_bytes = &bytes[id_delta_bytes_start..id_range_offset_bytes_start];
630 let id_range_offset_bytes = &bytes[id_range_offset_bytes_start..];
631 let mut end_code_reader = Reader::new(end_code_bytes);
632 let mut start_code_reader = Reader::new(start_code_bytes);
633 let mut id_delta_reader = Reader::new(id_delta_bytes);
634 let mut id_range_offset_reader = Reader::new(id_range_offset_bytes);
635 let mut char_code_to_glyph_index_map = Vec::new();
636 for seg_index in 0..seg_count {
637 let end_code = end_code_reader.read_u16()?;
638 let start_code = start_code_reader.read_u16()?;
639 let id_delta = id_delta_reader.read_u16()? as usize;
640 let id_range_offset = id_range_offset_reader.read_u16()? as usize;
641 for code in start_code..end_code {
642 let mut id = if id_range_offset == 0 {
643 code
644 } else {
645 let id_range_bytes = &id_range_offset_bytes[(seg_index * 2)..];
646 let mut reader = Reader::new(id_range_bytes);
647 reader.skip(id_range_offset + (code - start_code) as usize * 2)?;
648 let id = reader.read_u16()?;
649 id
650 } as usize;
651 if id != 0 {
652 id = (id + id_delta) % 65536;
653 }
654 char_code_to_glyph_index_map.resize(code as usize + 1, 0);
655 char_code_to_glyph_index_map[code as usize] = id;
656 }
657 }
658 Ok(char_code_to_glyph_index_map)
659}