File gamma.patch of Package firefox-gamma
diff --git a/gfx/2d/ScaledFontFontconfig.cpp b/gfx/2d/ScaledFontFontconfig.cpp
--- a/gfx/2d/ScaledFontFontconfig.cpp
+++ b/gfx/2d/ScaledFontFontconfig.cpp
@@ -18,6 +18,9 @@
#include FT_LCD_FILTER_H
#include FT_MULTIPLE_MASTERS_H
+#define GFX_PREF_FC_CONTRAST "gfx.font_rendering.fontconfig.contrast"
+#define GFX_PREF_FC_GAMMA "gfx.font_rendering.fontconfig.gamma"
+
namespace mozilla::gfx {
ScaledFontFontconfig::ScaledFontFontconfig(
@@ -471,6 +474,16 @@ bool ScaledFontFontconfig::GetWRFontInst
}
}
+ int contrast = Preferences::GetInt(GFX_PREF_FC_CONTRAST, -1);
+ if (contrast >= 0 && contrast <= 100) {
+ platformOptions.contrast = contrast;
+ }
+
+ int gamma = Preferences::GetInt(GFX_PREF_FC_GAMMA, -1);
+ if (gamma >= 0 && gamma <= 300) {
+ platformOptions.gamma = gamma;
+ }
+
*aOutOptions = Some(options);
*aOutPlatformOptions = Some(platformOptions);
diff --git a/gfx/layers/wr/WebRenderMessageUtils.h b/gfx/layers/wr/WebRenderMessageUtils.h
--- a/gfx/layers/wr/WebRenderMessageUtils.h
+++ b/gfx/layers/wr/WebRenderMessageUtils.h
@@ -222,7 +222,7 @@ inline auto TiedFields<mozilla::wr::Font
#elif defined(XP_MACOSX)
return std::tie(a.unused);
#else
- return std::tie(a.lcd_filter, a.hinting);
+ return std::tie(a.lcd_filter, a.hinting, a.gamma, a.contrast);
#endif
}
diff --git a/gfx/wr/webrender_api/src/font.rs b/gfx/wr/webrender_api/src/font.rs
--- a/gfx/wr/webrender_api/src/font.rs
+++ b/gfx/wr/webrender_api/src/font.rs
@@ -381,6 +381,8 @@ pub enum FontHinting {
pub struct FontInstancePlatformOptions {
pub lcd_filter: FontLCDFilter,
pub hinting: FontHinting,
+ pub gamma: i16,
+ pub contrast: i16,
}
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
@@ -389,6 +391,8 @@ impl Default for FontInstancePlatformOpt
FontInstancePlatformOptions {
lcd_filter: FontLCDFilter::Default,
hinting: FontHinting::LCD,
+ gamma: -1,
+ contrast: -1,
}
}
}
diff --git a/gfx/wr/wr_glyph_rasterizer/src/lib.rs b/gfx/wr/wr_glyph_rasterizer/src/lib.rs
--- a/gfx/wr/wr_glyph_rasterizer/src/lib.rs
+++ b/gfx/wr/wr_glyph_rasterizer/src/lib.rs
@@ -9,7 +9,6 @@
//! ## Usage
//!
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "windows"))]
mod gamma_lut;
mod rasterizer;
mod telemetry;
diff --git a/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs b/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs
--- a/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs
+++ b/gfx/wr/wr_glyph_rasterizer/src/platform/unix/font.rs
@@ -22,6 +22,7 @@ use freetype::freetype::{FT_LOAD_NO_BITM
use freetype::freetype::{FT_FACE_FLAG_SCALABLE, FT_FACE_FLAG_FIXED_SIZES};
use freetype::freetype::FT_FACE_FLAG_MULTIPLE_MASTERS;
use freetype::succeeded;
+use crate::gamma_lut::{ColorLut, GammaLut};
use crate::rasterizer::{FontInstance, GlyphFormat, GlyphKey};
use crate::rasterizer::{GlyphRasterError, GlyphRasterResult, RasterizedGlyph};
use crate::types::FastHashMap;
@@ -282,6 +283,7 @@ lazy_static! {
pub struct FontContext {
fonts: FastHashMap<FontKey, Arc<Mutex<CachedFont>>>,
+ gamma_luts: FastHashMap<(i16, i16), GammaLut>,
}
fn get_skew_bounds(bottom: i32, top: i32, skew_factor: f32, _vertical: bool) -> (f32, f32) {
@@ -380,6 +382,7 @@ impl FontContext {
pub fn new() -> FontContext {
FontContext {
fonts: FastHashMap::default(),
+ gamma_luts: FastHashMap::default(),
}
}
@@ -416,9 +419,12 @@ impl FontContext {
pub fn delete_font_instance(&mut self, _instance: &FontInstance) {
}
- fn load_glyph(&mut self, font: &FontInstance, glyph: &GlyphKey)
- -> Option<(MutexGuard<CachedFont>, FT_GlyphSlot, f32)> {
- let mut cached = self.fonts.get(&font.font_key)?.lock().ok()?;
+ fn load_glyph<'a>(
+ fonts: &'a FastHashMap<FontKey, Arc<Mutex<CachedFont>>>,
+ font: &FontInstance,
+ glyph: &GlyphKey,
+ ) -> Option<(MutexGuard<'a, CachedFont>, FT_GlyphSlot, f32)> {
+ let mut cached = fonts.get(&font.font_key)?.lock().ok()?;
let face = cached.face;
let mm_var = cached.mm_var;
@@ -500,7 +506,7 @@ impl FontContext {
(face_flags & (FT_FACE_FLAG_SCALABLE as FT_Long)) == 0 &&
(load_flags & FT_LOAD_NO_BITMAP) == 0 {
unsafe { FT_Set_Transform(face, ptr::null_mut(), ptr::null_mut()) };
- self.choose_bitmap_size(face, req_size * y_scale)
+ Self::choose_bitmap_size(face, req_size * y_scale)
} else {
let mut shape = font.transform.invert_scale(x_scale, y_scale);
if font.flags.contains(FontInstanceFlags::FLIP_X) {
@@ -753,11 +759,11 @@ impl FontContext {
font: &FontInstance,
key: &GlyphKey,
) -> Option<GlyphDimensions> {
- let (_cached, slot, scale) = self.load_glyph(font, key)?;
+ let (_cached, slot, scale) = Self::load_glyph(&self.fonts, font, key)?;
Self::get_glyph_dimensions_impl(slot, &font, key, scale, true)
}
- fn choose_bitmap_size(&self, face: FT_Face, requested_size: f64) -> FT_Error {
+ fn choose_bitmap_size(face: FT_Face, requested_size: f64) -> FT_Error {
let mut best_dist = unsafe { *(*face).available_sizes.offset(0) }.y_ppem as f64 / 64.0 - requested_size;
let mut best_size = 0;
let num_fixed_sizes = unsafe { (*face).num_fixed_sizes };
@@ -782,9 +788,11 @@ impl FontContext {
// Subpixel positioning is disabled in mono mode.
font.disable_subpixel_position();
}
- FontRenderMode::Alpha | FontRenderMode::Subpixel => {
- // We don't do any preblending with FreeType currently, so the color is not used.
- font.color = ColorU::new(0xFF, 0xFF, 0xFF, 0xFF);
+ FontRenderMode::Alpha => {
+ font.color = font.color.luminance_color().quantize();
+ }
+ FontRenderMode::Subpixel => {
+ font.color = font.color.quantize();
}
}
}
@@ -884,8 +892,9 @@ impl FontContext {
}
pub fn rasterize_glyph(&mut self, font: &FontInstance, key: &GlyphKey) -> GlyphRasterResult {
- let (_cached, slot, scale) = self.load_glyph(font, key)
- .ok_or(GlyphRasterError::LoadFailed)?;
+ let (_cached, slot, scale) = Self
+ ::load_glyph(&self.fonts, font, key)
+ .ok_or(GlyphRasterError::LoadFailed)?;
// Get dimensions of the glyph, to see if we need to rasterize it.
// Don't apply scaling to the dimensions, as the glyph cache needs to know the actual
@@ -1087,6 +1096,10 @@ impl FontContext {
_ => font.get_alpha_glyph_format(),
};
+ if format != FT_Glyph_Format::FT_GLYPH_FORMAT_BITMAP {
+ Self::gamma_correct_pixels(font, &mut self.gamma_luts, &mut final_buffer);
+ }
+
Ok(RasterizedGlyph {
left: left as f32,
top: top as f32,
@@ -1097,5 +1110,38 @@ impl FontContext {
bytes: final_buffer,
})
}
+
+ fn gamma_correct_pixels(
+ font: &FontInstance,
+ gamma_luts: &mut FastHashMap<(i16, i16), GammaLut>,
+ pixels: &mut Vec<u8>,
+ ) {
+ let FontInstancePlatformOptions { gamma, contrast, .. } =
+ font.platform_options.unwrap_or_default();
+
+ let (target_gamma, target_contrast) = match (gamma, contrast) {
+ (-1, _) => return, // Early return if gamma correction is disabled
+ (_, -1) => (gamma as f32 / 100.0, 0.5), // Use 0.5 as a default value recommended by the gamma_lut implementation
+ (_, _) => (gamma as f32 / 100.0, contrast as f32 / 100.0),
+ };
+
+ let gamma_lut = gamma_luts
+ .entry((gamma, contrast))
+ .or_insert_with(||
+ GammaLut::new(
+ target_contrast,
+ target_gamma,
+ target_gamma,
+ ));
+
+ match font.render_mode {
+ FontRenderMode::Alpha => {
+ gamma_lut.preblend_grayscale(pixels, font.color);
+ }
+ FontRenderMode::Subpixel => {
+ gamma_lut.preblend(pixels, font.color);
+ }
+ _ => {}
+ }
+ }
}
-
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2870,6 +2870,14 @@ pref("font.size.monospace.x-math", 13);
pref("font.name-list.monospace.zh-TW", "monospace");
pref("font.name-list.cursive.zh-TW", "cursive");
+ // Gamma-corrected font blending options for Fontconfig/FreeType implementation.
+ // These settings are only relevant when WebRender is enabled. The values specified
+ // below will be divided by 100 before being applied:
+ // gamma: Range [0, 300] - Default: disabled, typical value: 180, 0 for sRGB
+ // contrast: Range [0, 100] - Default: disabled, typical value: 50
+ pref("gfx.font_rendering.fontconfig.gamma", -1);
+ pref("gfx.font_rendering.fontconfig.contrast", -1);
+
pref("intl.ime.use_simple_context_on_password_field", false);
// uim may use key snooper to listen to key events. Unfortunately, we cannot