Compare commits

...

4 Commits

Author SHA1 Message Date
Antonio Scandurra
3ffc9d1447 Merge remote-tracking branch 'origin/main' into gamma-correction 2024-11-18 14:46:12 +01:00
Antonio Scandurra
30794e813b Merge remote-tracking branch 'origin/main' into gamma-correction 2024-11-18 09:33:42 +01:00
Antonio Scandurra
b7e76425da Use WebRender's method to determine lightness 2024-11-12 16:54:13 +01:00
Antonio Scandurra
a80ff28480 Rasterize glyphs using white on black (or viceversa) depending on brightness 2024-11-11 19:06:29 +01:00
4 changed files with 87 additions and 34 deletions

View File

@@ -444,6 +444,13 @@ impl Hsla {
self.a == 0.0
}
/// Returns true if the color is considered "light", false otherwise.
pub fn is_light(&self) -> bool {
const ONE_THIRD: f32 = 1. / 3.;
let Rgba { r, g, b, .. } = self.to_rgb();
r >= ONE_THIRD && g >= ONE_THIRD && b >= ONE_THIRD && r + g + b >= 2.
}
/// Blends `other` on top of `self` based on `other`'s alpha value. The resulting color is a combination of `self`'s and `other`'s colors.
///
/// If `other`'s alpha value is 1.0 or greater, `other` color is fully opaque, thus `other` is returned as the output color.

View File

@@ -1,3 +1,4 @@
use super::open_type::apply_features_and_fallbacks;
use crate::{
point, px, size, swap_rgba_pa_to_bgra, Bounds, DevicePixels, Font, FontFallbacks, FontFeatures,
FontId, FontMetrics, FontRun, FontStyle, FontWeight, GlyphId, LineLayout, Pixels,
@@ -14,10 +15,13 @@ use core_foundation::{
string::CFString,
};
use core_graphics::{
base::{kCGImageAlphaPremultipliedLast, CGGlyph},
base::{
kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedLast,
CGGlyph,
},
color_space::CGColorSpace,
context::CGContext,
display::CGPoint,
context::{CGBlendMode, CGContext, CGTextDrawingMode},
display::{CGPoint, CGRect, CGSize},
};
use core_text::{
font::CTFont,
@@ -45,11 +49,6 @@ use pathfinder_geometry::{
use smallvec::SmallVec;
use std::{borrow::Cow, char, cmp, convert::TryFrom, sync::Arc};
use super::open_type::apply_features_and_fallbacks;
#[allow(non_upper_case_globals)]
const kCGImageAlphaOnly: u32 = 7;
pub(crate) struct MacTextSystem(RwLock<MacTextSystemState>);
#[derive(Clone, PartialEq, Eq, Hash)]
@@ -360,30 +359,63 @@ impl MacTextSystemState {
}
let bitmap_size = bitmap_size;
let mut bytes;
let cx;
if params.is_emoji {
bytes = vec![0; bitmap_size.width.0 as usize * 4 * bitmap_size.height.0 as usize];
cx = CGContext::create_bitmap_context(
Some(bytes.as_mut_ptr() as *mut _),
bitmap_size.width.0 as usize,
bitmap_size.height.0 as usize,
8,
bitmap_size.width.0 as usize * 4,
&CGColorSpace::create_device_rgb(),
kCGImageAlphaPremultipliedLast,
);
let color_type = if params.is_emoji {
kCGImageAlphaPremultipliedLast
} else {
bytes = vec![0; bitmap_size.width.0 as usize * bitmap_size.height.0 as usize];
cx = CGContext::create_bitmap_context(
Some(bytes.as_mut_ptr() as *mut _),
bitmap_size.width.0 as usize,
bitmap_size.height.0 as usize,
8,
bitmap_size.width.0 as usize,
&CGColorSpace::create_device_gray(),
kCGImageAlphaOnly,
kCGImageAlphaNoneSkipLast
};
let mut bytes =
vec![0; bitmap_size.width.0 as usize * 4 * bitmap_size.height.0 as usize];
let cx = CGContext::create_bitmap_context(
Some(bytes.as_mut_ptr() as *mut _),
bitmap_size.width.0 as usize,
bitmap_size.height.0 as usize,
8,
bitmap_size.width.0 as usize * 4,
&CGColorSpace::create_device_rgb(),
kCGBitmapByteOrder32Little | color_type,
);
cx.set_allows_font_subpixel_positioning(true);
cx.set_should_subpixel_position_fonts(true);
cx.set_allows_font_subpixel_quantization(false);
cx.set_should_subpixel_quantize_fonts(false);
if !params.is_emoji {
cx.set_should_smooth_fonts(true);
cx.set_should_antialias(true);
let background_color;
let foreground_color;
if params.is_light {
background_color = [0., 0., 0.];
foreground_color = [1., 1., 1.];
} else {
background_color = [1., 1., 1.];
foreground_color = [0., 0., 0.];
}
cx.set_blend_mode(CGBlendMode::Copy);
cx.set_rgb_fill_color(
background_color[0],
background_color[1],
background_color[2],
1.,
);
cx.fill_rect(CGRect {
origin: CGPoint { x: 0.0, y: 0.0 },
size: CGSize {
width: bitmap_size.width.0 as CGFloat,
height: bitmap_size.height.0 as CGFloat,
},
});
cx.set_blend_mode(CGBlendMode::Normal);
cx.set_rgb_fill_color(
foreground_color[0],
foreground_color[1],
foreground_color[2],
1.,
);
cx.set_text_drawing_mode(CGTextDrawingMode::CGTextFill);
}
// Move the origin to bottom left and account for scaling, this
@@ -400,10 +432,7 @@ impl MacTextSystemState {
let subpixel_shift = params
.subpixel_variant
.map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
cx.set_allows_font_subpixel_positioning(true);
cx.set_should_subpixel_position_fonts(true);
cx.set_allows_font_subpixel_quantization(false);
cx.set_should_subpixel_quantize_fonts(false);
self.fonts[params.font_id.0]
.native_font()
.clone_with_font_size(f32::from(params.font_size) as CGFloat)
@@ -421,6 +450,19 @@ impl MacTextSystemState {
for pixel in bytes.chunks_exact_mut(4) {
swap_rgba_pa_to_bgra(pixel);
}
} else {
let mut index = 0;
bytes.retain_mut(|value| {
index += 1;
if index % 4 == 0 {
if !params.is_light {
*value = 255 - *value;
}
true
} else {
false
}
});
}
Ok((bitmap_size, bytes))

View File

@@ -657,6 +657,7 @@ pub(crate) struct RenderGlyphParams {
pub(crate) subpixel_variant: Point<u8>,
pub(crate) scale_factor: f32,
pub(crate) is_emoji: bool,
pub(crate) is_light: bool,
}
impl Eq for RenderGlyphParams {}
@@ -669,6 +670,7 @@ impl Hash for RenderGlyphParams {
self.subpixel_variant.hash(state);
self.scale_factor.to_bits().hash(state);
self.is_emoji.hash(state);
self.is_light.hash(state);
}
}

View File

@@ -2443,6 +2443,7 @@ impl<'a> WindowContext<'a> {
subpixel_variant,
scale_factor,
is_emoji: false,
is_light: color.is_light(),
};
let raster_bounds = self.text_system().raster_bounds(&params)?;
@@ -2507,6 +2508,7 @@ impl<'a> WindowContext<'a> {
subpixel_variant: Default::default(),
scale_factor,
is_emoji: true,
is_light: false,
};
let raster_bounds = self.text_system().raster_bounds(&params)?;