Struct cosmic_text::FontSystem
source · pub struct FontSystem(_);Expand description
Access system fonts
Implementations§
source§impl FontSystem
impl FontSystem
sourcepub fn new() -> Self
pub fn new() -> Self
Create a new FontSystem, that allows access to any installed system fonts
pub fn locale(&self) -> &str
pub fn db(&self) -> &Database
sourcepub fn get_font<'a>(&'a self, id: ID) -> Option<Arc<Font<'a>>>
pub fn get_font<'a>(&'a self, id: ID) -> Option<Arc<Font<'a>>>
Examples found in repository?
src/swash.rs (line 19)
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
fn swash_image(font_system: &FontSystem, context: &mut ScaleContext, cache_key: CacheKey) -> Option<SwashImage> {
let font = match font_system.get_font(cache_key.font_id) {
Some(some) => some,
None => {
log::warn!("did not find font {:?}", cache_key.font_id);
return None;
},
};
// Build the scaler
let mut scaler = context
.builder(font.as_swash())
.size(cache_key.font_size as f32)
.hint(true)
.build();
// Compute the fractional offset-- you'll likely want to quantize this
// in a real renderer
let offset =
Vector::new(cache_key.x_bin.as_float(), cache_key.y_bin.as_float());
// Select our source order
Render::new(&[
// Color outline with the first palette
Source::ColorOutline(0),
// Color bitmap with best fit selection mode
Source::ColorBitmap(StrikeWith::BestFit),
// Standard scalable outline
Source::Outline,
])
// Select a subpixel format
.format(Format::Alpha)
// Apply the fractional offset
.offset(offset)
// Render the image
.render(&mut scaler, cache_key.glyph_id)
}
fn swash_outline_commands(font_system: &FontSystem, context: &mut ScaleContext, cache_key: CacheKey) -> Option<Vec<swash::zeno::Command>> {
use swash::zeno::PathData as _;
let font = match font_system.get_font(cache_key.font_id) {
Some(some) => some,
None => {
log::warn!("did not find font {:?}", cache_key.font_id);
return None;
},
};
// Build the scaler
let mut scaler = context
.builder(font.as_swash())
.size(cache_key.font_size as f32)
.build();
// Scale the outline
let outline = scaler.scale_outline(cache_key.glyph_id).or_else(|| scaler.scale_color_outline(cache_key.glyph_id))?;
// Get the path information of the outline
let path = outline.path();
// Return the commands
Some(path.commands().collect())
}sourcepub fn get_font_matches<'a>(&'a self, attrs: Attrs<'_>) -> Arc<FontMatches<'a>>
pub fn get_font_matches<'a>(&'a self, attrs: Attrs<'_>) -> Arc<FontMatches<'a>>
Examples found in repository?
src/shape.rs (line 131)
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
fn shape_run<'a>(
font_system: &'a FontSystem,
line: &str,
attrs_list: &AttrsList,
start_run: usize,
end_run: usize,
span_rtl: bool,
) -> Vec<ShapeGlyph> {
//TODO: use smallvec?
let mut scripts = Vec::new();
for c in line[start_run..end_run].chars() {
match c.script() {
Script::Common |
Script::Inherited |
Script::Latin |
Script::Unknown => (),
script => if ! scripts.contains(&script) {
scripts.push(script);
},
}
}
log::trace!(
" Run {:?}: '{}'",
scripts,
&line[start_run..end_run],
);
let attrs = attrs_list.get_span(start_run);
let font_matches = font_system.get_font_matches(attrs);
let default_families = [font_matches.default_family.as_str()];
let mut font_iter = FontFallbackIter::new(
&font_matches.fonts,
&default_families,
scripts,
font_matches.locale
);
let (mut glyphs, mut missing) = shape_fallback(
font_iter.next().expect("no default font found"),
line,
attrs_list,
start_run,
end_run,
span_rtl,
);
//TODO: improve performance!
while !missing.is_empty() {
let font = match font_iter.next() {
Some(some) => some,
None => break,
};
log::trace!("Evaluating fallback with font '{}'", font.info.family);
let (mut fb_glyphs, fb_missing) = shape_fallback(
font,
line,
attrs_list,
start_run,
end_run,
span_rtl,
);
// Insert all matching glyphs
let mut fb_i = 0;
while fb_i < fb_glyphs.len() {
let start = fb_glyphs[fb_i].start;
let end = fb_glyphs[fb_i].end;
// Skip clusters that are not missing, or where the fallback font is missing
if !missing.contains(&start) || fb_missing.contains(&start) {
fb_i += 1;
continue;
}
let mut missing_i = 0;
while missing_i < missing.len() {
if missing[missing_i] >= start && missing[missing_i] < end {
// println!("No longer missing {}", missing[missing_i]);
missing.remove(missing_i);
} else {
missing_i += 1;
}
}
// Find prior glyphs
let mut i = 0;
while i < glyphs.len() {
if glyphs[i].start >= start && glyphs[i].end <= end {
break;
} else {
i += 1;
}
}
// Remove prior glyphs
while i < glyphs.len() {
if glyphs[i].start >= start && glyphs[i].end <= end {
let _glyph = glyphs.remove(i);
// log::trace!("Removed {},{} from {}", _glyph.start, _glyph.end, i);
} else {
break;
}
}
while fb_i < fb_glyphs.len() {
if fb_glyphs[fb_i].start >= start && fb_glyphs[fb_i].end <= end {
let fb_glyph = fb_glyphs.remove(fb_i);
// log::trace!("Insert {},{} from font {} at {}", fb_glyph.start, fb_glyph.end, font_i, i);
glyphs.insert(i, fb_glyph);
i += 1;
} else {
break;
}
}
}
}
// Debug missing font fallbacks
font_iter.check_missing(&line[start_run..end_run]);
/*
for glyph in glyphs.iter() {
log::trace!("'{}': {}, {}, {}, {}", &line[glyph.start..glyph.end], glyph.x_advance, glyph.y_advance, glyph.x_offset, glyph.y_offset);
}
*/
glyphs
}