From 4dbc5d8e44239785de44d205df7a481f2895e297 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 19 Sep 2017 16:32:17 +1000 Subject: [PATCH] Implement synthetic italics on Linux. Mac and Windows implementations still need to be implemented. --- webrender/src/frame_builder.rs | 1 + webrender/src/glyph_rasterizer.rs | 1 + webrender/src/platform/unix/font.rs | 18 ++++++++++++++++-- webrender/src/resource_cache.rs | 13 ++++++++----- webrender_api/src/font.rs | 6 +++++- wrench/reftests/text/reftest.list | 3 +++ .../reftests/text/synthetic-italics-ref.yaml | 5 +++++ wrench/reftests/text/synthetic-italics.yaml | 7 +++++++ wrench/src/wrench.rs | 13 +++++++++++-- wrench/src/yaml_frame_reader.rs | 9 +++++++-- 10 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 wrench/reftests/text/synthetic-italics-ref.yaml create mode 100644 wrench/reftests/text/synthetic-italics.yaml diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index ddaee10b2a..26669fb9b2 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -1065,6 +1065,7 @@ impl FrameBuilder { subpx_dir, font.platform_options, font.variations.clone(), + font.synthetic_italics, ); let prim = TextRunPrimitiveCpu { font: prim_font, diff --git a/webrender/src/glyph_rasterizer.rs b/webrender/src/glyph_rasterizer.rs index 4a04637671..da84a7e77a 100644 --- a/webrender/src/glyph_rasterizer.rs +++ b/webrender/src/glyph_rasterizer.rs @@ -411,6 +411,7 @@ fn raterize_200_glyphs() { SubpixelDirection::Horizontal, None, Vec::new(), + false, ); let mut glyph_keys = Vec::with_capacity(200); diff --git a/webrender/src/platform/unix/font.rs b/webrender/src/platform/unix/font.rs index a033ae52f4..2526b75634 100644 --- a/webrender/src/platform/unix/font.rs +++ b/webrender/src/platform/unix/font.rs @@ -9,9 +9,9 @@ use freetype::freetype::{FT_BBox, FT_Outline_Translate, FT_Pixel_Mode, FT_Render use freetype::freetype::{FT_Done_Face, FT_Error, FT_Get_Char_Index, FT_Int32}; use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter, FT_Pos}; use freetype::freetype::{FT_F26Dot6, FT_Face, FT_Glyph_Format, FT_Long, FT_UInt}; -use freetype::freetype::{FT_GlyphSlot, FT_LcdFilter, FT_New_Memory_Face}; +use freetype::freetype::{FT_GlyphSlot, FT_LcdFilter, FT_New_Memory_Face, FT_Outline_Transform}; use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph}; -use freetype::freetype::{FT_Library, FT_Outline_Get_CBox, FT_Set_Char_Size}; +use freetype::freetype::{FT_Library, FT_Matrix, FT_Outline_Get_CBox, FT_Set_Char_Size}; use internal_types::FastHashMap; use std::{mem, ptr, slice}; use std::sync::Arc; @@ -305,6 +305,20 @@ impl FontContext { dx - ((cbox.xMin + dx) & !63), dy - ((cbox.yMin + dy) & !63), ); + + if font.synthetic_italics { + // These magic numbers are pre-encoded fixed point + // values that apply ~12 degree shear. Borrowed + // from the Freetype implementation of the + // FT_GlyphSlot_Oblique function. + let transform = FT_Matrix { + xx: 0x10000, + yx: 0x00000, + xy: 0x0366A, + yy: 0x10000, + }; + FT_Outline_Transform(outline, &transform); + } } let result = unsafe { FT_Render_Glyph(slot, render_mode) }; diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 80476da8fd..043236b012 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -337,22 +337,25 @@ impl ResourceCache { platform_options: Option, variations: Vec, ) { - let mut render_mode = FontRenderMode::Subpixel; + let mut requested_render_mode = FontRenderMode::Subpixel; let mut subpx_dir = SubpixelDirection::Horizontal; if let Some(options) = options { - render_mode = options.render_mode; - if render_mode == FontRenderMode::Mono { - subpx_dir = SubpixelDirection::None; + if let Some(render_mode) = options.render_mode { + requested_render_mode = render_mode; } } + if requested_render_mode == FontRenderMode::Mono { + subpx_dir = SubpixelDirection::None; + } let instance = FontInstance::new( font_key, glyph_size, ColorF::new(0.0, 0.0, 0.0, 1.0), - render_mode, + requested_render_mode, subpx_dir, platform_options, variations, + options.map_or(false, |opts| opts.synthetic_italics), ); self.resources.font_instances.insert(instance_key, instance); } diff --git a/webrender_api/src/font.rs b/webrender_api/src/font.rs index 50635974f1..28ffba530e 100644 --- a/webrender_api/src/font.rs +++ b/webrender_api/src/font.rs @@ -194,7 +194,8 @@ pub struct GlyphOptions { #[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstanceOptions { - pub render_mode: FontRenderMode, + pub render_mode: Option, + pub synthetic_italics: bool, } #[repr(C)] @@ -219,6 +220,7 @@ pub struct FontInstance { pub subpx_dir: SubpixelDirection, pub platform_options: Option, pub variations: Vec, + pub synthetic_italics: bool, } impl FontInstance { @@ -230,6 +232,7 @@ impl FontInstance { subpx_dir: SubpixelDirection, platform_options: Option, variations: Vec, + synthetic_italics: bool, ) -> FontInstance { // In alpha/mono mode, the color of the font is irrelevant. // Forcing it to black in those cases saves rasterizing glyphs @@ -246,6 +249,7 @@ impl FontInstance { subpx_dir, platform_options, variations, + synthetic_italics, } } diff --git a/wrench/reftests/text/reftest.list b/wrench/reftests/text/reftest.list index 029ce1806c..0dacccb26a 100644 --- a/wrench/reftests/text/reftest.list +++ b/wrench/reftests/text/reftest.list @@ -18,3 +18,6 @@ fuzzy(1,100) == decorations-suite.yaml decorations-suite.png == split-batch.yaml split-batch-ref.yaml == shadow-red.yaml shadow-red-ref.yaml fuzzy(1,136) == shadow-grey.yaml shadow-grey-ref.yaml + +# enable when synthetic-italics implemented on mac +# != synthetic-italics.yaml synthetic-italics-ref.yaml diff --git a/wrench/reftests/text/synthetic-italics-ref.yaml b/wrench/reftests/text/synthetic-italics-ref.yaml new file mode 100644 index 0000000000..5c5be707f7 --- /dev/null +++ b/wrench/reftests/text/synthetic-italics-ref.yaml @@ -0,0 +1,5 @@ +root: + items: + - text: "Fake italics are great" + origin: 20 40 + size: 20 diff --git a/wrench/reftests/text/synthetic-italics.yaml b/wrench/reftests/text/synthetic-italics.yaml new file mode 100644 index 0000000000..fa9b78a3f0 --- /dev/null +++ b/wrench/reftests/text/synthetic-italics.yaml @@ -0,0 +1,7 @@ +root: + items: + - text: "Fake italics are great" + origin: 20 40 + size: 20 + synthetic-italics: true + diff --git a/wrench/src/wrench.rs b/wrench/src/wrench.rs index a98f8227ef..390bd10743 100644 --- a/wrench/src/wrench.rs +++ b/wrench/src/wrench.rs @@ -237,6 +237,7 @@ impl Wrench { SubpixelDirection::Horizontal, None, Vec::new(), + false, ); let mut keys = Vec::new(); for glyph_index in &indices { @@ -366,10 +367,18 @@ impl Wrench { key } - pub fn add_font_instance(&mut self, font_key: FontKey, size: Au) -> FontInstanceKey { + pub fn add_font_instance(&mut self, + font_key: FontKey, + size: Au, + synthetic_italics: bool, + ) -> FontInstanceKey { let key = self.api.generate_font_instance_key(); let mut update = ResourceUpdates::new(); - update.add_font_instance(key, font_key, size, None, None, Vec::new()); + let options = FontInstanceOptions { + render_mode: None, + synthetic_italics, + }; + update.add_font_instance(key, font_key, size, Some(options), None, Vec::new()); self.api.update_resources(update); key } diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index aafce9e593..dd7f0a9cd6 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -231,11 +231,12 @@ impl YamlFrameReader { &mut self, font_key: FontKey, size: Au, + synthetic_italics: bool, wrench: &mut Wrench, ) -> FontInstanceKey { *self.font_instances .entry((font_key, size)) - .or_insert_with(|| wrench.add_font_instance(font_key, size)) + .or_insert_with(|| wrench.add_font_instance(font_key, size, synthetic_italics)) } fn to_image_mask(&mut self, item: &Yaml, wrench: &mut Wrench) -> Option { @@ -723,6 +724,7 @@ impl YamlFrameReader { ) { let size = item["size"].as_pt_to_au().unwrap_or(Au::from_f32_px(16.0)); let color = item["color"].as_colorf().unwrap_or(*BLACK_COLOR); + let synthetic_italics = item["synthetic-italics"].as_bool().unwrap_or(false); assert!( item["blur-radius"].is_badvalue(), @@ -731,7 +733,10 @@ impl YamlFrameReader { let desc = FontDescriptor::from_yaml(item, &self.aux_dir); let font_key = self.get_or_create_font(desc, wrench); - let font_instance_key = self.get_or_create_font_instance(font_key, size, wrench); + let font_instance_key = self.get_or_create_font_instance(font_key, + size, + synthetic_italics, + wrench); assert!( !(item["glyphs"].is_badvalue() && item["text"].is_badvalue()),