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
openSUSE Build Service is sponsored by