Compare commits
4 Commits
debug-view
...
gamma-corr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ffc9d1447 | ||
|
|
30794e813b | ||
|
|
b7e76425da | ||
|
|
a80ff28480 |
@@ -444,6 +444,13 @@ impl Hsla {
|
|||||||
self.a == 0.0
|
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.
|
/// 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.
|
/// If `other`'s alpha value is 1.0 or greater, `other` color is fully opaque, thus `other` is returned as the output color.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use super::open_type::apply_features_and_fallbacks;
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, size, swap_rgba_pa_to_bgra, Bounds, DevicePixels, Font, FontFallbacks, FontFeatures,
|
point, px, size, swap_rgba_pa_to_bgra, Bounds, DevicePixels, Font, FontFallbacks, FontFeatures,
|
||||||
FontId, FontMetrics, FontRun, FontStyle, FontWeight, GlyphId, LineLayout, Pixels,
|
FontId, FontMetrics, FontRun, FontStyle, FontWeight, GlyphId, LineLayout, Pixels,
|
||||||
@@ -14,10 +15,13 @@ use core_foundation::{
|
|||||||
string::CFString,
|
string::CFString,
|
||||||
};
|
};
|
||||||
use core_graphics::{
|
use core_graphics::{
|
||||||
base::{kCGImageAlphaPremultipliedLast, CGGlyph},
|
base::{
|
||||||
|
kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedLast,
|
||||||
|
CGGlyph,
|
||||||
|
},
|
||||||
color_space::CGColorSpace,
|
color_space::CGColorSpace,
|
||||||
context::CGContext,
|
context::{CGBlendMode, CGContext, CGTextDrawingMode},
|
||||||
display::CGPoint,
|
display::{CGPoint, CGRect, CGSize},
|
||||||
};
|
};
|
||||||
use core_text::{
|
use core_text::{
|
||||||
font::CTFont,
|
font::CTFont,
|
||||||
@@ -45,11 +49,6 @@ use pathfinder_geometry::{
|
|||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{borrow::Cow, char, cmp, convert::TryFrom, sync::Arc};
|
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>);
|
pub(crate) struct MacTextSystem(RwLock<MacTextSystemState>);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
@@ -360,30 +359,63 @@ impl MacTextSystemState {
|
|||||||
}
|
}
|
||||||
let bitmap_size = bitmap_size;
|
let bitmap_size = bitmap_size;
|
||||||
|
|
||||||
let mut bytes;
|
let color_type = if params.is_emoji {
|
||||||
let cx;
|
kCGImageAlphaPremultipliedLast
|
||||||
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,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
bytes = vec![0; bitmap_size.width.0 as usize * bitmap_size.height.0 as usize];
|
kCGImageAlphaNoneSkipLast
|
||||||
cx = CGContext::create_bitmap_context(
|
};
|
||||||
Some(bytes.as_mut_ptr() as *mut _),
|
let mut bytes =
|
||||||
bitmap_size.width.0 as usize,
|
vec![0; bitmap_size.width.0 as usize * 4 * bitmap_size.height.0 as usize];
|
||||||
bitmap_size.height.0 as usize,
|
let cx = CGContext::create_bitmap_context(
|
||||||
8,
|
Some(bytes.as_mut_ptr() as *mut _),
|
||||||
bitmap_size.width.0 as usize,
|
bitmap_size.width.0 as usize,
|
||||||
&CGColorSpace::create_device_gray(),
|
bitmap_size.height.0 as usize,
|
||||||
kCGImageAlphaOnly,
|
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
|
// Move the origin to bottom left and account for scaling, this
|
||||||
@@ -400,10 +432,7 @@ impl MacTextSystemState {
|
|||||||
let subpixel_shift = params
|
let subpixel_shift = params
|
||||||
.subpixel_variant
|
.subpixel_variant
|
||||||
.map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
|
.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]
|
self.fonts[params.font_id.0]
|
||||||
.native_font()
|
.native_font()
|
||||||
.clone_with_font_size(f32::from(params.font_size) as CGFloat)
|
.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) {
|
for pixel in bytes.chunks_exact_mut(4) {
|
||||||
swap_rgba_pa_to_bgra(pixel);
|
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))
|
Ok((bitmap_size, bytes))
|
||||||
|
|||||||
@@ -657,6 +657,7 @@ pub(crate) struct RenderGlyphParams {
|
|||||||
pub(crate) subpixel_variant: Point<u8>,
|
pub(crate) subpixel_variant: Point<u8>,
|
||||||
pub(crate) scale_factor: f32,
|
pub(crate) scale_factor: f32,
|
||||||
pub(crate) is_emoji: bool,
|
pub(crate) is_emoji: bool,
|
||||||
|
pub(crate) is_light: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for RenderGlyphParams {}
|
impl Eq for RenderGlyphParams {}
|
||||||
@@ -669,6 +670,7 @@ impl Hash for RenderGlyphParams {
|
|||||||
self.subpixel_variant.hash(state);
|
self.subpixel_variant.hash(state);
|
||||||
self.scale_factor.to_bits().hash(state);
|
self.scale_factor.to_bits().hash(state);
|
||||||
self.is_emoji.hash(state);
|
self.is_emoji.hash(state);
|
||||||
|
self.is_light.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2443,6 +2443,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
subpixel_variant,
|
subpixel_variant,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
is_emoji: false,
|
is_emoji: false,
|
||||||
|
is_light: color.is_light(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let raster_bounds = self.text_system().raster_bounds(¶ms)?;
|
let raster_bounds = self.text_system().raster_bounds(¶ms)?;
|
||||||
@@ -2507,6 +2508,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
subpixel_variant: Default::default(),
|
subpixel_variant: Default::default(),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
is_emoji: true,
|
is_emoji: true,
|
||||||
|
is_light: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let raster_bounds = self.text_system().raster_bounds(¶ms)?;
|
let raster_bounds = self.text_system().raster_bounds(¶ms)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user