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