[fontations] Implement LinearGradients

This commit is contained in:
Behdad Esfahbod 2025-03-04 23:56:01 -07:00 committed by Khaled Hosny
parent 1a39f8935e
commit 4b1f655a83

View file

@ -10,7 +10,7 @@ use read_fonts::tables::cpal::ColorRecord;
use read_fonts::TableProvider;
use skrifa::charmap::Charmap;
use skrifa::charmap::MapVariant::Variant;
use skrifa::color::{Brush, ColorGlyphCollection, ColorPainter, CompositeMode, Transform};
use skrifa::color::{Brush, ColorGlyphCollection, ColorPainter, ColorStop, CompositeMode, Extend, Transform};
use skrifa::font::FontRef;
use skrifa::instance::{Location, NormalizedCoord, Size};
use skrifa::metrics::BoundingBox;
@ -346,6 +346,53 @@ impl HbColorPainter {
}
}
struct ColorLineData<'a> {
color_stops: &'a [ColorStop],
extend: Extend,
}
extern "C" fn _hb_fontations_get_color_stops (
_color_line: *mut hb_color_line_t,
color_line_data: *mut ::std::os::raw::c_void,
start: ::std::os::raw::c_uint,
count_out: *mut ::std::os::raw::c_uint,
color_stops_out: *mut hb_color_stop_t,
user_data: *mut ::std::os::raw::c_void,
) -> ::std::os::raw::c_uint
{
let color_painter = unsafe { &*(color_line_data as *const HbColorPainter) };
let color_line_data = unsafe { &*(user_data as *const ColorLineData) };
let color_stops = &color_line_data.color_stops;
if count_out.is_null() {
return color_stops.len() as u32;
}
let count = unsafe { *count_out };
for i in 0..count {
let stop = color_stops.get(start as usize + i as usize);
if stop.is_none() {
unsafe { *count_out = i; };
return color_stops.len() as u32;
}
let stop = stop.unwrap();
unsafe {
*(color_stops_out.offset(i as isize)) = hb_color_stop_t {
offset: stop.offset,
color: color_painter.lookup_color(stop.palette_index, stop.alpha),
is_foreground: (stop.palette_index == 0xFFFF) as hb_bool_t,
};
}
}
return color_stops.len() as u32;
}
extern "C" fn _hb_fontations_get_extend (
_color_line: *mut hb_color_line_t,
color_line_data: *mut ::std::os::raw::c_void,
_user_data: *mut ::std::os::raw::c_void,
) -> hb_paint_extend_t
{
let color_line_data = unsafe { &*(color_line_data as *const ColorLineData) };
color_line_data.extend as hb_paint_extend_t // They are the same
}
impl ColorPainter for HbColorPainter {
fn push_transform(&mut self, transform: Transform) {
unsafe {
@ -421,6 +468,34 @@ impl ColorPainter for HbColorPainter {
);
}
}
Brush::LinearGradient {
color_stops,
extend,
p0,
p1,
} => {
let color_stops = ColorLineData { color_stops: &color_stops, extend };
unsafe {
let mut cl = std::mem::zeroed::<hb_color_line_t>();
cl.data = self as *mut HbColorPainter as *mut ::std::os::raw::c_void;
cl.get_color_stops = Some(_hb_fontations_get_color_stops);
cl.get_color_stops_user_data = &color_stops as *const ColorLineData as *mut ::std::os::raw::c_void;
cl.get_extend = Some(_hb_fontations_get_extend);
cl.get_extend_user_data = &extend as *const Extend as *mut ::std::os::raw::c_void;
hb_paint_linear_gradient(
self.paint_funcs,
self.paint_data,
&mut cl,
p0.x,
p0.y,
p1.x,
p1.y,
p1.x, // TODO: Where's p2?
p1.y, // TODO: Where's p2?
);
}
}
_ => {}
}
}
@ -435,7 +510,7 @@ impl ColorPainter for HbColorPainter {
if mode.is_none() {
return;
}
let mode = mode.unwrap() as hb_paint_composite_mode_t;
let mode = mode.unwrap() as hb_paint_composite_mode_t; // They are the same
unsafe {
hb_paint_pop_group(self.paint_funcs, self.paint_data, mode);
}
@ -469,7 +544,7 @@ extern "C" fn _hb_fontations_paint_glyph(
let mut color_records = Box::<[ColorRecord]>::default();
if cpal.is_ok() {
let cpal = cpal.unwrap();
// fontations doesn't seem to provide a way to access palettes
// TODO fontations doesn't seem to provide a way to access palettes
// really. Just assume the first palette starts at the beginning
// of the color records array.
let color_records_array = cpal.color_records_array();