Accept colors in styling runs passed to layout_str

Also move from the runs being expressed as ranges to the runs being expressed as a sequence of contiguous scalar lengths.
This commit is contained in:
Nathan Sobo
2021-05-21 14:10:38 -06:00
parent b42f5142f7
commit 92ff7f4e5e
7 changed files with 187 additions and 173 deletions
+39 -20
View File
@@ -1,4 +1,5 @@
use crate::{
color::ColorU,
fonts::{FontId, GlyphId, Metrics, Properties},
geometry::{
rect::{RectF, RectI},
@@ -6,7 +7,7 @@ use crate::{
vector::{vec2f, vec2i, Vector2F},
},
platform,
text_layout::{Glyph, Line, Run},
text_layout::{Glyph, LineLayout, Run},
};
use cocoa::appkit::{CGFloat, CGPoint};
use core_foundation::{
@@ -21,7 +22,7 @@ use core_graphics::{
use core_text::{line::CTLine, string_attributes::kCTFontAttributeName};
use font_kit::{canvas::RasterizationOptions, hinting::HintingOptions, source::SystemSource};
use parking_lot::RwLock;
use std::{char, convert::TryFrom};
use std::{cell::RefCell, char, convert::TryFrom};
#[allow(non_upper_case_globals)]
const kCGImageAlphaOnly: u32 = 7;
@@ -80,8 +81,8 @@ impl platform::FontSystem for FontSystem {
&self,
text: &str,
font_size: f32,
runs: &[(std::ops::Range<usize>, FontId)],
) -> Line {
runs: &[(usize, FontId, ColorU)],
) -> LineLayout {
self.0.read().layout_str(text, font_size, runs)
}
}
@@ -185,8 +186,8 @@ impl FontSystemState {
&self,
text: &str,
font_size: f32,
runs: &[(std::ops::Range<usize>, FontId)],
) -> Line {
runs: &[(usize, FontId, ColorU)],
) -> LineLayout {
let font_id_attr_name = CFString::from_static_string("zed_font_id");
let len = text.len();
@@ -205,16 +206,34 @@ impl FontSystemState {
let mut utf8_and_utf16_ixs = utf8_and_utf16_ixs.clone();
string.replace_str(&CFString::new(text), CFRange::init(0, 0));
let last_run: RefCell<Option<(usize, FontId)>> = Default::default();
let font_runs = runs
.iter()
.filter_map(|(len, font_id, _)| {
let mut last_run = last_run.borrow_mut();
if let Some((last_len, last_font_id)) = last_run.as_mut() {
if font_id == last_font_id {
*last_len += *len;
None
} else {
let result = (*last_len, *last_font_id);
*last_len = *len;
*last_font_id = *font_id;
Some(result)
}
} else {
*last_run = Some((*len, *font_id));
None
}
})
.chain(std::iter::from_fn(|| last_run.borrow_mut().take()));
let mut utf8_ix = 0;
let mut utf16_ix = 0;
for (range, font_id) in runs {
while utf8_ix < range.start {
let (next_utf8_ix, next_utf16_ix) = utf8_and_utf16_ixs.next().unwrap();
utf8_ix = next_utf8_ix;
utf16_ix = next_utf16_ix;
}
for (run_len, font_id) in font_runs {
let utf8_end = utf16_ix + run_len;
let utf16_start = utf16_ix;
while utf8_ix < range.end {
while utf8_ix < utf8_end {
let (next_utf8_ix, next_utf16_ix) = utf8_and_utf16_ixs.next().unwrap();
utf8_ix = next_utf8_ix;
utf16_ix = next_utf16_ix;
@@ -279,7 +298,7 @@ impl FontSystemState {
}
let typographic_bounds = line.get_typographic_bounds();
Line {
LineLayout {
width: typographic_bounds.width as f32,
ascent: typographic_bounds.ascent as f32,
descent: typographic_bounds.descent as f32,
@@ -308,9 +327,9 @@ mod tests {
"hello world",
16.0,
&[
(0..2, menlo_bold),
(2..6, menlo_italic),
(6..11, menlo_regular),
(2, menlo_bold, Default::default()),
(4, menlo_italic, Default::default()),
(5, menlo_regular, Default::default()),
],
);
assert_eq!(line.runs.len(), 3);
@@ -336,9 +355,9 @@ mod tests {
text,
16.0,
&[
(0..9, zapfino_regular),
(9..22, menlo_regular),
(22..text.len(), zapfino_regular),
(9, zapfino_regular, ColorU::default()),
(13, menlo_regular, ColorU::default()),
(text.len() - 22, zapfino_regular, ColorU::default()),
],
);
assert_eq!(
+8 -3
View File
@@ -8,20 +8,20 @@ pub mod current {
}
use crate::{
color::ColorU,
executor,
fonts::{FontId, GlyphId, Metrics as FontMetrics, Properties as FontProperties},
geometry::{
rect::{RectF, RectI},
vector::Vector2F,
},
text_layout::Line,
text_layout::LineLayout,
ClipboardItem, Menu, Scene,
};
use async_task::Runnable;
pub use event::Event;
use std::{
any::Any,
ops::Range,
path::{Path, PathBuf},
rc::Rc,
sync::Arc,
@@ -122,5 +122,10 @@ pub trait FontSystem: Send + Sync {
subpixel_shift: Vector2F,
scale_factor: f32,
) -> Option<(RectI, Vec<u8>)>;
fn layout_str(&self, text: &str, font_size: f32, runs: &[(Range<usize>, FontId)]) -> Line;
fn layout_str(
&self,
text: &str,
font_size: f32,
runs: &[(usize, FontId, ColorU)],
) -> LineLayout;
}