From 84de6a84d6743835bcfbf9651087d196cb748f82 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Thu, 26 Oct 2017 13:51:38 +0100 Subject: [PATCH 1/3] Implement boldness and stretchiness for Freetype The current implementation for boldness assumes that if Freetype claims a font is not bold then it must have normal weight. However fonts with lighter-than-normal weight are not claimed to be bold. Therefore we get rid of this check. --- components/gfx/platform/freetype/font.rs | 51 +++++++++++++++--------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/components/gfx/platform/freetype/font.rs b/components/gfx/platform/freetype/font.rs index a7dd652b9f5..9aa86349504 100644 --- a/components/gfx/platform/freetype/font.rs +++ b/components/gfx/platform/freetype/font.rs @@ -10,7 +10,7 @@ use freetype::freetype::{FT_F26Dot6, FT_Face, FT_FaceRec}; use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name}; use freetype::freetype::{FT_Get_Kerning, FT_Get_Sfnt_Table, FT_Load_Sfnt_Table}; use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong}; -use freetype::freetype::{FT_Int32, FT_Kerning_Mode, FT_STYLE_FLAG_BOLD, FT_STYLE_FLAG_ITALIC}; +use freetype::freetype::{FT_Int32, FT_Kerning_Mode, FT_STYLE_FLAG_ITALIC}; use freetype::freetype::{FT_Load_Glyph, FT_Set_Char_Size}; use freetype::freetype::{FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_Vector}; use freetype::freetype::FT_Sfnt_Tag; @@ -137,30 +137,45 @@ impl FontHandleMethods for FontHandle { } fn boldness(&self) -> FontWeight { let default_weight = FontWeight::normal(); - if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD as c_long == 0 } { - default_weight - } else { - unsafe { - let os2 = FT_Get_Sfnt_Table(self.face, FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2; - let valid = !os2.is_null() && (*os2).version != 0xffff; - if valid { - let weight =(*os2).usWeightClass as i32; - if weight < 10 { - FontWeight::from_int(weight * 100).unwrap() - } else if weight >= 100 && weight < 1000 { - FontWeight::from_int(weight / 100 * 100).unwrap() - } else { - default_weight - } + unsafe { + let os2 = FT_Get_Sfnt_Table(self.face, FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2; + let valid = !os2.is_null() && (*os2).version != 0xffff; + if valid { + let weight =(*os2).usWeightClass as i32; + if weight < 10 { + FontWeight::from_int(weight * 100).unwrap() + } else if weight >= 100 && weight < 1000 { + FontWeight::from_int(weight / 100 * 100).unwrap() } else { default_weight } + } else { + default_weight } } } fn stretchiness(&self) -> FontStretch { - // TODO(pcwalton): Implement this. - FontStretch::Normal + let default_stretch = FontStretch::Normal; + unsafe { + let os2 = FT_Get_Sfnt_Table(self.face, FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2; + let valid = !os2.is_null() && (*os2).version != 0xffff; + if valid { + match (*os2).usWidthClass { + 1 => FontStretch::UltraCondensed, + 2 => FontStretch::ExtraCondensed, + 3 => FontStretch::Condensed, + 4 => FontStretch::SemiCondensed, + 5 => FontStretch::Normal, // called medium in TrueType spec + 6 => FontStretch::SemiExpanded, + 7 => FontStretch::Expanded, + 8 => FontStretch::ExtraExpanded, + 9 => FontStretch::UltraExpanded, + _ => default_stretch, + } + } else { + default_stretch + } + } } fn glyph_index(&self, codepoint: char) -> Option { From 6647a2f891a97de81ebfe0374986c17f200fbfd7 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Tue, 6 Feb 2018 20:45:02 +0000 Subject: [PATCH 2/3] Change selection of the best font for a style Previously anything with the wrong stretch/italicness was considered equally bad. Now we consider the wrong weight to be least bad, wrong boldness of intermediate badness, and wrong itallicness to be most bad. --- components/gfx/font_template.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index 2c88384a4d0..95fb618305a 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -40,13 +40,33 @@ impl FontTemplateDescriptor { /// /// The smaller the score, the better the fonts match. 0 indicates an exact match. This must /// be commutative (distance(A, B) == distance(B, A)). + /// + /// The policy is to care most about differences in italicness, then weight, then stretch #[inline] fn distance_from(&self, other: &FontTemplateDescriptor) -> u32 { - if self.stretch != other.stretch || self.italic != other.italic { - // A value higher than all weights. - return 1000 + let italic_part = if self.italic == other.italic { 0 } else { 1000 }; + // 0 <= weightPart <= 800 + let weight_part = ((self.weight.0 as i16) - (other.weight.0 as i16)).abs() as u32; + // 0 <= stretchPart <= 8 + let stretch_part = (self.stretch_number() - other.stretch_number()).abs() as u32; + italic_part + weight_part + stretch_part + } + + /// Returns a number between 1 and 9 for the stretch property. + /// 1 is ultra_condensed, 5 is normal, and 9 is ultra_expanded + #[inline] + fn stretch_number(&self) -> i32 { + match self.stretch { + font_stretch::T::UltraCondensed => 1, + font_stretch::T::ExtraCondensed => 2, + font_stretch::T::Condensed => 3, + font_stretch::T::SemiCondensed => 4, + font_stretch::T::Normal => 5, + font_stretch::T::SemiExpanded => 6, + font_stretch::T::Expanded => 7, + font_stretch::T::ExtraExpanded => 8, + font_stretch::T::UltraExpanded => 9, } - ((self.weight.0 as i16) - (other.weight.0 as i16)).abs() as u32 } } From 58d1969c5a1838a431ccfa84b59fd9ed7e0477c9 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Wed, 15 Nov 2017 17:57:12 +0000 Subject: [PATCH 3/3] Added a test for font selection The test picks a font and makes a table asking for that font at every possible weight/stretch combination. One should expect the table entries to get bolder from right to left and wider from top to bottom. --- tests/html/font_selection.html | 85 ++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/html/font_selection.html diff --git a/tests/html/font_selection.html b/tests/html/font_selection.html new file mode 100644 index 00000000000..da4fdca8418 --- /dev/null +++ b/tests/html/font_selection.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
two wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo wordstwo words
+ +