1use byteorder::{BigEndian, ReadBytesExt};
14use dwrote::CustomFontCollectionLoaderImpl;
15use dwrote::Font as DWriteFont;
16use dwrote::FontCollection as DWriteFontCollection;
17use dwrote::FontFace as DWriteFontFace;
18use dwrote::FontFallback as DWriteFontFallback;
19use dwrote::FontFile as DWriteFontFile;
20use dwrote::FontMetrics as DWriteFontMetrics;
21use dwrote::FontStyle as DWriteFontStyle;
22use dwrote::GlyphOffset as DWriteGlyphOffset;
23use dwrote::GlyphRunAnalysis as DWriteGlyphRunAnalysis;
24use dwrote::InformationalStringId as DWriteInformationalStringId;
25use dwrote::OutlineBuilder as DWriteOutlineBuilder;
26use dwrote::{DWRITE_TEXTURE_ALIASED_1x1, DWRITE_TEXTURE_CLEARTYPE_3x1};
27use dwrote::{DWRITE_GLYPH_RUN, DWRITE_MEASURING_MODE_NATURAL};
28use dwrote::{DWRITE_RENDERING_MODE_ALIASED, DWRITE_RENDERING_MODE_NATURAL};
29use pathfinder_geometry::line_segment::LineSegment2F;
30use pathfinder_geometry::rect::{RectF, RectI};
31use pathfinder_geometry::transform2d::Transform2F;
32use pathfinder_geometry::vector::{Vector2F, Vector2I};
33use std::borrow::Cow;
34use std::ffi::OsString;
35use std::fmt::{self, Debug, Formatter};
36use std::fs::File;
37use std::io::{self, Read, Seek, SeekFrom};
38use std::os::windows::ffi::OsStringExt;
39use std::os::windows::io::AsRawHandle;
40use std::path::{Path, PathBuf};
41use std::sync::{Arc, Mutex};
42use winapi::shared::minwindef::{FALSE, MAX_PATH};
43use winapi::um::dwrite::DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE;
44use winapi::um::dwrite::DWRITE_READING_DIRECTION;
45use winapi::um::dwrite::DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
46use winapi::um::fileapi;
47
48use crate::canvas::{Canvas, Format, RasterizationOptions};
49use crate::error::{FontLoadingError, GlyphLoadingError};
50use crate::file_type::FileType;
51use crate::handle::Handle;
52use crate::hinting::HintingOptions;
53use crate::loader::{FallbackFont, FallbackResult, Loader};
54use crate::metrics::Metrics;
55use crate::outline::{OutlineBuilder, OutlineSink};
56use crate::properties::{Properties, Stretch, Style, Weight};
57
58const ERROR_BOUND: f32 = 0.0001;
59
60const OPENTYPE_TABLE_TAG_HEAD: u32 = 0x68656164;
61
62#[allow(missing_debug_implementations)]
64pub struct NativeFont {
65 pub dwrite_font: DWriteFont,
67 pub dwrite_font_face: DWriteFontFace,
69}
70
71pub struct Font {
73 dwrite_font: DWriteFont,
74 dwrite_font_face: DWriteFontFace,
75 cached_data: Mutex<Option<Arc<Vec<u8>>>>,
76}
77
78struct MyTextAnalysisSource {
79 text_utf16_len: u32,
80 locale: String,
81}
82
83impl dwrote::TextAnalysisSourceMethods for MyTextAnalysisSource {
84 fn get_locale_name<'a>(&'a self, text_pos: u32) -> (Cow<'a, str>, u32) {
85 (self.locale.as_str().into(), self.text_utf16_len - text_pos)
86 }
87
88 fn get_paragraph_reading_direction(&self) -> DWRITE_READING_DIRECTION {
89 DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
90 }
91}
92
93impl Font {
94 fn from_dwrite_font_file(
95 font_file: DWriteFontFile,
96 mut font_index: u32,
97 font_data: Option<Arc<Vec<u8>>>,
98 ) -> Result<Font, FontLoadingError> {
99 let collection_loader = CustomFontCollectionLoaderImpl::new(&[font_file.clone()]);
100 let collection = DWriteFontCollection::from_loader(collection_loader);
101 let families = collection.families_iter();
102 for family in families {
103 for family_font_index in 0..family.get_font_count() {
104 if font_index > 0 {
105 font_index -= 1;
106 continue;
107 }
108 let dwrite_font = family.get_font(family_font_index);
109 let dwrite_font_face = dwrite_font.create_font_face();
110 return Ok(Font {
111 dwrite_font,
112 dwrite_font_face,
113 cached_data: Mutex::new(font_data),
114 });
115 }
116 }
117 Err(FontLoadingError::NoSuchFontInCollection)
118 }
119
120 pub fn from_bytes(font_data: Arc<Vec<u8>>, font_index: u32) -> Result<Font, FontLoadingError> {
125 let font_file =
126 DWriteFontFile::new_from_data(font_data.clone()).ok_or(FontLoadingError::Parse)?;
127 Font::from_dwrite_font_file(font_file, font_index, Some(font_data))
128 }
129
130 pub fn from_file(file: &mut File, font_index: u32) -> Result<Font, FontLoadingError> {
135 unsafe {
136 let mut path = vec![0; MAX_PATH + 1];
137 let path_len = fileapi::GetFinalPathNameByHandleW(
138 file.as_raw_handle(),
139 path.as_mut_ptr(),
140 path.len() as u32 - 1,
141 0,
142 );
143 if path_len == 0 {
144 return Err(FontLoadingError::Io(io::Error::last_os_error()));
145 }
146 path.truncate(path_len as usize);
147 Font::from_path(PathBuf::from(OsString::from_wide(&path)), font_index)
148 }
149 }
150
151 #[inline]
156 pub fn from_path<P: AsRef<Path>>(path: P, font_index: u32) -> Result<Font, FontLoadingError> {
157 let font_file = DWriteFontFile::new_from_path(path).ok_or(FontLoadingError::Parse)?;
158 Font::from_dwrite_font_file(font_file, font_index, None)
159 }
160
161 #[inline]
163 pub unsafe fn from_native_font(native_font: NativeFont) -> Font {
164 Font {
165 dwrite_font: native_font.dwrite_font,
166 dwrite_font_face: native_font.dwrite_font_face,
167 cached_data: Mutex::new(None),
168 }
169 }
170
171 #[inline]
173 pub fn from_handle(handle: &Handle) -> Result<Self, FontLoadingError> {
174 <Self as Loader>::from_handle(handle)
175 }
176
177 pub fn analyze_bytes(font_data: Arc<Vec<u8>>) -> Result<FileType, FontLoadingError> {
180 match DWriteFontFile::analyze_data(font_data) {
181 0 => Err(FontLoadingError::Parse),
182 1 => Ok(FileType::Single),
183 font_count => Ok(FileType::Collection(font_count)),
184 }
185 }
186
187 pub fn analyze_file(file: &mut File) -> Result<FileType, FontLoadingError> {
189 let mut font_data = vec![];
190 file.seek(SeekFrom::Start(0))
191 .map_err(FontLoadingError::Io)?;
192 match file.read_to_end(&mut font_data) {
193 Err(io_error) => Err(FontLoadingError::Io(io_error)),
194 Ok(_) => Font::analyze_bytes(Arc::new(font_data)),
195 }
196 }
197
198 pub fn native_font(&self) -> NativeFont {
200 NativeFont {
201 dwrite_font: self.dwrite_font.clone(),
202 dwrite_font_face: self.dwrite_font_face.clone(),
203 }
204 }
205
206 #[inline]
208 pub fn analyze_path<P: AsRef<Path>>(path: P) -> Result<FileType, FontLoadingError> {
209 <Self as Loader>::analyze_path(path)
210 }
211
212 #[inline]
214 pub fn postscript_name(&self) -> Option<String> {
215 let dwrite_font = &self.dwrite_font;
216 dwrite_font.informational_string(DWriteInformationalStringId::PostscriptName)
217 }
218
219 #[inline]
221 pub fn full_name(&self) -> String {
222 let dwrite_font = &self.dwrite_font;
223 dwrite_font
224 .informational_string(DWriteInformationalStringId::FullName)
225 .unwrap_or_else(|| dwrite_font.family_name())
226 }
227
228 #[inline]
230 pub fn family_name(&self) -> String {
231 self.dwrite_font.family_name()
232 }
233
234 #[inline]
236 pub fn is_monospace(&self) -> bool {
237 self.dwrite_font.is_monospace().unwrap_or(false)
238 }
239
240 pub fn properties(&self) -> Properties {
242 let dwrite_font = &self.dwrite_font;
243 Properties {
244 style: style_for_dwrite_style(dwrite_font.style()),
245 stretch: Stretch(Stretch::MAPPING[(dwrite_font.stretch() as usize) - 1]),
246 weight: Weight(dwrite_font.weight().to_u32() as f32),
247 }
248 }
249
250 pub fn glyph_for_char(&self, character: char) -> Option<u32> {
256 let chars = [character as u32];
257 self.dwrite_font_face
258 .get_glyph_indices(&chars)
259 .into_iter()
260 .next()
261 .and_then(|g| {
262 if g != 0 {
265 Some(g as u32)
266 } else {
267 None
268 }
269 })
270 }
271
272 #[inline]
276 pub fn glyph_count(&self) -> u32 {
277 self.dwrite_font_face.get_glyph_count() as u32
278 }
279
280 pub fn outline<S>(
287 &self,
288 glyph_id: u32,
289 _: HintingOptions,
290 sink: &mut S,
291 ) -> Result<(), GlyphLoadingError>
292 where
293 S: OutlineSink,
294 {
295 let outline_sink = OutlineCanonicalizer::new();
296 self.dwrite_font_face.get_glyph_run_outline(
297 self.metrics().units_per_em as f32,
298 &[glyph_id as u16],
299 None,
300 None,
301 false,
302 false,
303 Box::new(outline_sink.clone()),
304 );
305 outline_sink
306 .0
307 .lock()
308 .unwrap()
309 .builder
310 .take_outline()
311 .copy_to(&mut *sink);
312 Ok(())
313 }
314
315 pub fn typographic_bounds(&self, glyph_id: u32) -> Result<RectF, GlyphLoadingError> {
317 let metrics = self
318 .dwrite_font_face
319 .get_design_glyph_metrics(&[glyph_id as u16], false);
320
321 let metrics = &metrics[0];
322 let advance_width = metrics.advanceWidth as i32;
323 let advance_height = metrics.advanceHeight as i32;
324 let left_side_bearing = metrics.leftSideBearing as i32;
325 let right_side_bearing = metrics.rightSideBearing as i32;
326 let top_side_bearing = metrics.topSideBearing as i32;
327 let bottom_side_bearing = metrics.bottomSideBearing as i32;
328 let vertical_origin_y = metrics.verticalOriginY as i32;
329
330 let y_offset = vertical_origin_y + bottom_side_bearing - advance_height;
331 let width = advance_width - (left_side_bearing + right_side_bearing);
332 let height = advance_height - (top_side_bearing + bottom_side_bearing);
333
334 Ok(RectI::new(
335 Vector2I::new(left_side_bearing, y_offset),
336 Vector2I::new(width, height),
337 )
338 .to_f32())
339 }
340
341 pub fn advance(&self, glyph_id: u32) -> Result<Vector2F, GlyphLoadingError> {
344 let metrics = self
345 .dwrite_font_face
346 .get_design_glyph_metrics(&[glyph_id as u16], false);
347 let metrics = &metrics[0];
348 Ok(Vector2F::new(metrics.advanceWidth as f32, 0.0))
349 }
350
351 pub fn origin(&self, glyph: u32) -> Result<Vector2F, GlyphLoadingError> {
353 let metrics = self
354 .dwrite_font_face
355 .get_design_glyph_metrics(&[glyph as u16], false);
356 Ok(Vector2I::new(
357 metrics[0].leftSideBearing,
358 metrics[0].verticalOriginY + metrics[0].bottomSideBearing,
359 )
360 .to_f32())
361 }
362
363 pub fn metrics(&self) -> Metrics {
365 let dwrite_font = &self.dwrite_font;
366
367 match dwrite_font.metrics() {
371 DWriteFontMetrics::Metrics1(metrics) => Metrics {
372 units_per_em: metrics.designUnitsPerEm as u32,
373 ascent: metrics.ascent as f32,
374 descent: -(metrics.descent as f32),
375 line_gap: metrics.lineGap as f32,
376 cap_height: metrics.capHeight as f32,
377 x_height: metrics.xHeight as f32,
378 underline_position: metrics.underlinePosition as f32,
379 underline_thickness: metrics.underlineThickness as f32,
380 bounding_box: RectI::new(
381 Vector2I::new(metrics.glyphBoxLeft as i32, metrics.glyphBoxBottom as i32),
382 Vector2I::new(
383 metrics.glyphBoxRight as i32 - metrics.glyphBoxLeft as i32,
384 metrics.glyphBoxTop as i32 - metrics.glyphBoxBottom as i32,
385 ),
386 )
387 .to_f32(),
388 },
389 DWriteFontMetrics::Metrics0(metrics) => {
390 let bounding_box = match self
391 .dwrite_font_face
392 .get_font_table(OPENTYPE_TABLE_TAG_HEAD.swap_bytes())
393 {
394 Some(head) => {
395 let mut reader = &head[36..];
396 let x_min = reader.read_i16::<BigEndian>().unwrap();
397 let y_min = reader.read_i16::<BigEndian>().unwrap();
398 let x_max = reader.read_i16::<BigEndian>().unwrap();
399 let y_max = reader.read_i16::<BigEndian>().unwrap();
400 RectI::new(
401 Vector2I::new(x_min as i32, y_min as i32),
402 Vector2I::new(x_max as i32 - x_min as i32, y_max as i32 - y_min as i32),
403 )
404 .to_f32()
405 }
406 None => RectF::default(),
407 };
408 Metrics {
409 units_per_em: metrics.designUnitsPerEm as u32,
410 ascent: metrics.ascent as f32,
411 descent: -(metrics.descent as f32),
412 line_gap: metrics.lineGap as f32,
413 cap_height: metrics.capHeight as f32,
414 x_height: metrics.xHeight as f32,
415 underline_position: metrics.underlinePosition as f32,
416 underline_thickness: metrics.underlineThickness as f32,
417 bounding_box,
418 }
419 }
420 }
421 }
422
423 #[inline]
427 pub fn handle(&self) -> Option<Handle> {
428 <Self as Loader>::handle(self)
429 }
430
431 pub fn copy_font_data(&self) -> Option<Arc<Vec<u8>>> {
436 let mut font_data = self.cached_data.lock().unwrap();
437 if font_data.is_none() {
438 let files = self.dwrite_font_face.get_files();
439 if let Some(file) = files.get(0) {
441 *font_data = Some(Arc::new(file.get_font_file_bytes()))
442 }
443 }
444 (*font_data).clone()
445 }
446
447 #[inline]
450 pub fn raster_bounds(
451 &self,
452 glyph_id: u32,
453 point_size: f32,
454 transform: Transform2F,
455 hinting_options: HintingOptions,
456 rasterization_options: RasterizationOptions,
457 ) -> Result<RectI, GlyphLoadingError> {
458 let dwrite_analysis = self.build_glyph_analysis(
459 glyph_id,
460 point_size,
461 transform,
462 hinting_options,
463 rasterization_options,
464 )?;
465
466 let texture_type = match rasterization_options {
467 RasterizationOptions::Bilevel => DWRITE_TEXTURE_ALIASED_1x1,
468 RasterizationOptions::GrayscaleAa | RasterizationOptions::SubpixelAa => {
469 DWRITE_TEXTURE_CLEARTYPE_3x1
470 }
471 };
472
473 let texture_bounds = dwrite_analysis.get_alpha_texture_bounds(texture_type)?;
474 let texture_width = texture_bounds.right - texture_bounds.left;
475 let texture_height = texture_bounds.bottom - texture_bounds.top;
476
477 Ok(RectI::new(
478 Vector2I::new(texture_bounds.left, texture_bounds.top),
479 Vector2I::new(texture_width, texture_height),
480 ))
481 }
482
483 pub fn rasterize_glyph(
493 &self,
494 canvas: &mut Canvas,
495 glyph_id: u32,
496 point_size: f32,
497 transform: Transform2F,
498 hinting_options: HintingOptions,
499 rasterization_options: RasterizationOptions,
500 ) -> Result<(), GlyphLoadingError> {
501 let dwrite_analysis = self.build_glyph_analysis(
505 glyph_id,
506 point_size,
507 transform,
508 hinting_options,
509 rasterization_options,
510 )?;
511
512 let texture_type = match rasterization_options {
513 RasterizationOptions::Bilevel => DWRITE_TEXTURE_ALIASED_1x1,
514 RasterizationOptions::GrayscaleAa | RasterizationOptions::SubpixelAa => {
515 DWRITE_TEXTURE_CLEARTYPE_3x1
516 }
517 };
518
519 let texture_bounds = dwrite_analysis.get_alpha_texture_bounds(texture_type)?;
521 let texture_width = texture_bounds.right - texture_bounds.left;
522 let texture_height = texture_bounds.bottom - texture_bounds.top;
523
524 if texture_width == 0 || texture_height == 0 {
527 return Ok(());
528 }
529
530 let texture_format = if texture_type == DWRITE_TEXTURE_ALIASED_1x1 {
531 Format::A8
532 } else {
533 Format::Rgb24
534 };
535 let texture_bits_per_pixel = texture_format.bits_per_pixel();
536 let texture_bytes_per_pixel = texture_bits_per_pixel as usize / 8;
537 let texture_size = Vector2I::new(texture_width, texture_height);
538 let texture_stride = texture_width as usize * texture_bytes_per_pixel;
539
540 let mut texture_bytes =
541 dwrite_analysis.create_alpha_texture(texture_type, texture_bounds)?;
542 canvas.blit_from(
543 Vector2I::new(texture_bounds.left, texture_bounds.top),
544 &mut texture_bytes,
545 texture_size,
546 texture_stride,
547 texture_format,
548 );
549
550 Ok(())
551 }
552
553 pub fn supports_hinting_options(
560 &self,
561 hinting_options: HintingOptions,
562 for_rasterization: bool,
563 ) -> bool {
564 match (hinting_options, for_rasterization) {
565 (HintingOptions::None, _)
566 | (HintingOptions::Vertical(_), true)
567 | (HintingOptions::VerticalSubpixel(_), true) => true,
568 (HintingOptions::Vertical(_), false)
569 | (HintingOptions::VerticalSubpixel(_), false)
570 | (HintingOptions::Full(_), _) => false,
571 }
572 }
573
574 fn build_glyph_analysis(
575 &self,
576 glyph_id: u32,
577 point_size: f32,
578 transform: Transform2F,
579 _hinting_options: HintingOptions,
580 rasterization_options: RasterizationOptions,
581 ) -> Result<DWriteGlyphRunAnalysis, GlyphLoadingError> {
582 unsafe {
583 let glyph_id = glyph_id as u16;
584 let advance = 0.0;
585 let offset = DWriteGlyphOffset {
586 advanceOffset: 0.0,
587 ascenderOffset: 0.0,
588 };
589 let glyph_run = DWRITE_GLYPH_RUN {
590 fontFace: self.dwrite_font_face.as_ptr(),
591 fontEmSize: point_size,
592 glyphCount: 1,
593 glyphIndices: &glyph_id,
594 glyphAdvances: &advance,
595 glyphOffsets: &offset,
596 isSideways: FALSE,
597 bidiLevel: 0,
598 };
599
600 let rendering_mode = match rasterization_options {
601 RasterizationOptions::Bilevel => DWRITE_RENDERING_MODE_ALIASED,
602 RasterizationOptions::GrayscaleAa | RasterizationOptions::SubpixelAa => {
603 DWRITE_RENDERING_MODE_NATURAL
604 }
605 };
606
607 Ok(DWriteGlyphRunAnalysis::create(
608 &glyph_run,
609 1.0,
610 Some(dwrote::DWRITE_MATRIX {
611 m11: transform.m11(),
612 m12: transform.m12(),
613 m21: transform.m21(),
614 m22: transform.m22(),
615 dx: transform.vector.x(),
616 dy: transform.vector.y(),
617 }),
618 rendering_mode,
619 DWRITE_MEASURING_MODE_NATURAL,
620 0.0,
621 0.0,
622 )?)
623 }
624 }
625
626 fn get_fallbacks(&self, text: &str, locale: &str) -> FallbackResult<Font> {
632 let sys_fallback = DWriteFontFallback::get_system_fallback();
633 if sys_fallback.is_none() {
634 unimplemented!("Need Windows 7 method for font fallbacks")
635 }
636 let text_utf16: Vec<u16> = text.encode_utf16().collect();
637 let text_utf16_len = text_utf16.len() as u32;
638 let number_subst =
639 dwrote::NumberSubstitution::new(DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, locale, true);
640 let text_analysis_source = MyTextAnalysisSource {
641 text_utf16_len,
642 locale: locale.to_owned(),
643 };
644 let text_analysis = dwrote::TextAnalysisSource::from_text_and_number_subst(
645 Box::new(text_analysis_source),
646 text_utf16.into(),
647 number_subst,
648 );
649 let sys_fallback = sys_fallback.unwrap();
650 let collection = DWriteFontCollection::get_system(false);
654 let fallback_result = sys_fallback.map_characters(
655 &text_analysis,
656 0,
657 text_utf16_len,
658 &collection,
659 Some(&self.dwrite_font.family_name()),
660 self.dwrite_font.weight(),
661 self.dwrite_font.style(),
662 self.dwrite_font.stretch(),
663 );
664 let valid_len = convert_len_utf16_to_utf8(text, fallback_result.mapped_length);
665 let fonts = if let Some(dwrite_font) = fallback_result.mapped_font {
666 let dwrite_font_face = dwrite_font.create_font_face();
667 let font = Font {
668 dwrite_font,
669 dwrite_font_face,
670 cached_data: Mutex::new(None),
671 };
672 let fallback_font = FallbackFont {
673 font,
674 scale: fallback_result.scale,
675 };
676 vec![fallback_font]
677 } else {
678 vec![]
679 };
680 FallbackResult { fonts, valid_len }
681 }
682
683 pub fn load_font_table(&self, table_tag: u32) -> Option<Box<[u8]>> {
689 self.dwrite_font_face
690 .get_font_table(table_tag.swap_bytes())
691 .map(|v| v.into())
692 }
693}
694
695fn convert_len_utf16_to_utf8(text: &str, len_utf16: usize) -> usize {
698 let mut l_utf8 = 0;
699 let mut l_utf16 = 0;
700 let mut chars = text.chars();
701 while l_utf16 < len_utf16 {
702 if let Some(c) = chars.next() {
703 l_utf8 += c.len_utf8();
704 l_utf16 += c.len_utf16();
705 } else {
706 break;
707 }
708 }
709 l_utf8
710}
711
712impl Clone for Font {
713 #[inline]
714 fn clone(&self) -> Font {
715 Font {
716 dwrite_font: self.dwrite_font.clone(),
717 dwrite_font_face: self.dwrite_font_face.clone(),
718 cached_data: Mutex::new((*self.cached_data.lock().unwrap()).clone()),
719 }
720 }
721}
722
723impl Debug for Font {
724 fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
725 self.family_name().fmt(fmt)
726 }
727}
728
729impl Loader for Font {
730 type NativeFont = NativeFont;
731
732 #[inline]
733 fn from_bytes(font_data: Arc<Vec<u8>>, font_index: u32) -> Result<Self, FontLoadingError> {
734 Font::from_bytes(font_data, font_index)
735 }
736
737 #[inline]
738 fn from_file(file: &mut File, font_index: u32) -> Result<Font, FontLoadingError> {
739 Font::from_file(file, font_index)
740 }
741
742 fn from_path<P>(path: P, font_index: u32) -> Result<Self, FontLoadingError>
743 where
744 P: AsRef<Path>,
745 {
746 Font::from_path(path, font_index)
747 }
748
749 #[inline]
750 unsafe fn from_native_font(native_font: Self::NativeFont) -> Self {
751 Font::from_native_font(native_font)
752 }
753
754 #[inline]
755 fn analyze_bytes(font_data: Arc<Vec<u8>>) -> Result<FileType, FontLoadingError> {
756 Font::analyze_bytes(font_data)
757 }
758
759 #[inline]
760 fn analyze_file(file: &mut File) -> Result<FileType, FontLoadingError> {
761 Font::analyze_file(file)
762 }
763
764 #[inline]
765 fn native_font(&self) -> Self::NativeFont {
766 self.native_font()
767 }
768
769 #[inline]
770 fn postscript_name(&self) -> Option<String> {
771 self.postscript_name()
772 }
773
774 #[inline]
775 fn full_name(&self) -> String {
776 self.full_name()
777 }
778
779 #[inline]
780 fn family_name(&self) -> String {
781 self.family_name()
782 }
783
784 #[inline]
785 fn is_monospace(&self) -> bool {
786 self.is_monospace()
787 }
788
789 #[inline]
790 fn properties(&self) -> Properties {
791 self.properties()
792 }
793
794 #[inline]
795 fn glyph_for_char(&self, character: char) -> Option<u32> {
796 self.glyph_for_char(character)
797 }
798
799 #[inline]
800 fn glyph_count(&self) -> u32 {
801 self.glyph_count()
802 }
803
804 #[inline]
805 fn outline<S>(
806 &self,
807 glyph_id: u32,
808 hinting: HintingOptions,
809 sink: &mut S,
810 ) -> Result<(), GlyphLoadingError>
811 where
812 S: OutlineSink,
813 {
814 self.outline(glyph_id, hinting, sink)
815 }
816
817 #[inline]
818 fn typographic_bounds(&self, glyph_id: u32) -> Result<RectF, GlyphLoadingError> {
819 self.typographic_bounds(glyph_id)
820 }
821
822 #[inline]
823 fn advance(&self, glyph_id: u32) -> Result<Vector2F, GlyphLoadingError> {
824 self.advance(glyph_id)
825 }
826
827 #[inline]
828 fn origin(&self, origin: u32) -> Result<Vector2F, GlyphLoadingError> {
829 self.origin(origin)
830 }
831
832 #[inline]
833 fn metrics(&self) -> Metrics {
834 self.metrics()
835 }
836
837 #[inline]
838 fn supports_hinting_options(
839 &self,
840 hinting_options: HintingOptions,
841 for_rasterization: bool,
842 ) -> bool {
843 self.supports_hinting_options(hinting_options, for_rasterization)
844 }
845
846 #[inline]
847 fn copy_font_data(&self) -> Option<Arc<Vec<u8>>> {
848 self.copy_font_data()
849 }
850
851 #[inline]
852 fn rasterize_glyph(
853 &self,
854 canvas: &mut Canvas,
855 glyph_id: u32,
856 point_size: f32,
857 transform: Transform2F,
858 hinting_options: HintingOptions,
859 rasterization_options: RasterizationOptions,
860 ) -> Result<(), GlyphLoadingError> {
861 self.rasterize_glyph(
862 canvas,
863 glyph_id,
864 point_size,
865 transform,
866 hinting_options,
867 rasterization_options,
868 )
869 }
870
871 #[inline]
872 fn get_fallbacks(&self, text: &str, locale: &str) -> FallbackResult<Self> {
873 self.get_fallbacks(text, locale)
874 }
875
876 #[inline]
877 fn load_font_table(&self, table_tag: u32) -> Option<Box<[u8]>> {
878 self.load_font_table(table_tag)
879 }
880}
881
882#[derive(Clone)]
883struct OutlineCanonicalizer(Arc<Mutex<OutlineCanonicalizerInfo>>);
884
885struct OutlineCanonicalizerInfo {
886 builder: OutlineBuilder,
887 last_position: Vector2F,
888}
889
890impl OutlineCanonicalizer {
891 fn new() -> OutlineCanonicalizer {
892 OutlineCanonicalizer(Arc::new(Mutex::new(OutlineCanonicalizerInfo {
893 builder: OutlineBuilder::new(),
894 last_position: Vector2F::default(),
895 })))
896 }
897}
898
899impl DWriteOutlineBuilder for OutlineCanonicalizer {
900 fn move_to(&mut self, to_x: f32, to_y: f32) {
901 let to = Vector2F::new(to_x, -to_y);
902
903 let mut this = self.0.lock().unwrap();
904 this.last_position = to;
905 this.builder.move_to(to);
906 }
907
908 fn line_to(&mut self, to_x: f32, to_y: f32) {
909 let to = Vector2F::new(to_x, -to_y);
910
911 let mut this = self.0.lock().unwrap();
912 this.last_position = to;
913 this.builder.line_to(to);
914 }
915
916 fn close(&mut self) {
917 let mut this = self.0.lock().unwrap();
918 this.builder.close();
919 }
920
921 fn curve_to(
922 &mut self,
923 ctrl0_x: f32,
924 ctrl0_y: f32,
925 ctrl1_x: f32,
926 ctrl1_y: f32,
927 to_x: f32,
928 to_y: f32,
929 ) {
930 let ctrl = LineSegment2F::new(
931 Vector2F::new(ctrl0_x, -ctrl0_y),
932 Vector2F::new(ctrl1_x, -ctrl1_y),
933 );
934 let to = Vector2F::new(to_x, -to_y);
935
936 let mut this = self.0.lock().unwrap();
939 let baseline = LineSegment2F::new(this.last_position, to);
940 let approx_ctrl = LineSegment2F((ctrl * 3.0).0 - baseline.0) * 0.5;
941 let delta_ctrl = (approx_ctrl.to() - approx_ctrl.from()) * 2.0;
942 let max_error = delta_ctrl.length() / 6.0;
943
944 if max_error < ERROR_BOUND {
945 let approx_ctrl = (approx_ctrl.midpoint() * 2.0).round() * 0.5;
947 this.builder.quadratic_curve_to(approx_ctrl, to);
948 } else {
949 this.builder.cubic_curve_to(ctrl, to);
950 }
951
952 this.last_position = to;
953 }
954}
955
956fn style_for_dwrite_style(style: DWriteFontStyle) -> Style {
957 match style {
958 DWriteFontStyle::Normal => Style::Normal,
959 DWriteFontStyle::Oblique => Style::Oblique,
960 DWriteFontStyle::Italic => Style::Italic,
961 }
962}