Changed the file structure
This commit is contained in:
parent
7743d0d084
commit
420d3c3dfc
22 changed files with 409 additions and 395 deletions
|
|
@ -58,7 +58,7 @@ impl<'a> TextBuffer<'a> {
|
|||
|
||||
let mut reshaped = 0;
|
||||
while self.shape_lines.len() < self.text_lines.len()
|
||||
&& (self.layout_lines.len() as i32) < lines
|
||||
&& (self.layout_lines.len() as i32) < lines
|
||||
{
|
||||
let line_i = FontLineIndex::new(self.shape_lines.len());
|
||||
self.reshape_line(line_i);
|
||||
|
|
@ -74,7 +74,9 @@ impl<'a> TextBuffer<'a> {
|
|||
pub fn reshape_line(&mut self, line_i: FontLineIndex) {
|
||||
let instant = Instant::now();
|
||||
|
||||
let shape_line = self.font_matches.shape_line(line_i, &self.text_lines[line_i.get()]);
|
||||
let shape_line = self
|
||||
.font_matches
|
||||
.shape_line(line_i, &self.text_lines[line_i.get()]);
|
||||
if line_i.get() < self.shape_lines.len() {
|
||||
self.shape_lines[line_i.get()] = shape_line;
|
||||
} else {
|
||||
|
|
@ -131,7 +133,7 @@ impl<'a> TextBuffer<'a> {
|
|||
self.font_size,
|
||||
self.line_width,
|
||||
&mut self.layout_lines,
|
||||
insert_i
|
||||
insert_i,
|
||||
);
|
||||
|
||||
self.redraw = true;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ impl<'a> FontLayoutLine<'a> {
|
|||
|
||||
// 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());
|
||||
let offset =
|
||||
Vector::new(cache_key.x_bin.as_float(), cache_key.y_bin.as_float());
|
||||
|
||||
// Select our source order
|
||||
Render::new(&[
|
||||
|
|
@ -77,12 +78,12 @@ impl<'a> FontLayoutLine<'a> {
|
|||
// 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)
|
||||
// Select a subpixel format
|
||||
.format(Format::Alpha)
|
||||
// Apply the fractional offset
|
||||
.offset(offset)
|
||||
// Render the image
|
||||
.render(&mut scaler, cache_key.glyph_id)
|
||||
});
|
||||
|
||||
if let Some(ref image) = image_opt {
|
||||
|
|
@ -96,28 +97,25 @@ impl<'a> FontLayoutLine<'a> {
|
|||
let mut i = 0;
|
||||
for off_y in 0..image.placement.height as i32 {
|
||||
for off_x in 0..image.placement.width as i32 {
|
||||
let color =
|
||||
(image.data[i] as u32) << 24 |
|
||||
base & 0xFFFFFF;
|
||||
let color = (image.data[i] as u32) << 24 | base & 0xFFFFFF;
|
||||
f(x + off_x, y + off_y, color);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Content::Color => {
|
||||
let mut i = 0;
|
||||
for off_y in 0..image.placement.height as i32 {
|
||||
for off_x in 0..image.placement.width as i32 {
|
||||
let color =
|
||||
(image.data[i + 3] as u32) << 24 |
|
||||
(image.data[i] as u32) << 16 |
|
||||
(image.data[i + 1] as u32) << 8 |
|
||||
(image.data[i + 2] as u32);
|
||||
let color = (image.data[i + 3] as u32) << 24
|
||||
| (image.data[i] as u32) << 16
|
||||
| (image.data[i + 1] as u32) << 8
|
||||
| (image.data[i + 2] as u32);
|
||||
f(x + off_x, y + off_y, color);
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Content::SubpixelMask => {
|
||||
println!("TODO: SubpixelMask");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,15 @@ pub struct FontMatches<'a> {
|
|||
}
|
||||
|
||||
impl<'a> FontMatches<'a> {
|
||||
fn shape_fallback(&self, font_i: usize, line: &str, start_word: usize, end_word: usize, span_rtl: bool, blank: bool) -> (Vec<FontShapeGlyph>, Vec<usize>) {
|
||||
fn shape_fallback(
|
||||
&self,
|
||||
font_i: usize,
|
||||
line: &str,
|
||||
start_word: usize,
|
||||
end_word: usize,
|
||||
span_rtl: bool,
|
||||
blank: bool,
|
||||
) -> (Vec<FontShapeGlyph>, Vec<usize>) {
|
||||
let word = &line[start_word..end_word];
|
||||
|
||||
let font_scale = self.fonts[font_i].rustybuzz.units_per_em() as f32;
|
||||
|
|
@ -101,15 +109,24 @@ impl<'a> FontMatches<'a> {
|
|||
(glyphs, missing)
|
||||
}
|
||||
|
||||
fn shape_word(&self, line: &str, start_word: usize, end_word: usize, span_rtl: bool, blank: bool) -> FontShapeWord {
|
||||
fn shape_word(
|
||||
&self,
|
||||
line: &str,
|
||||
start_word: usize,
|
||||
end_word: usize,
|
||||
span_rtl: bool,
|
||||
blank: bool,
|
||||
) -> FontShapeWord {
|
||||
let mut font_i = 0;
|
||||
let (mut glyphs, mut missing) = self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank);
|
||||
let (mut glyphs, mut missing) =
|
||||
self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank);
|
||||
|
||||
//TODO: improve performance!
|
||||
font_i += 1;
|
||||
while !missing.is_empty() && font_i < self.fonts.len() {
|
||||
// println!("Evaluating fallback with font {}", font_i);
|
||||
let (mut fb_glyphs, fb_missing) = self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank);
|
||||
let (mut fb_glyphs, fb_missing) =
|
||||
self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank);
|
||||
|
||||
// Insert all matching glyphs
|
||||
let mut fb_i = 0;
|
||||
|
|
@ -187,7 +204,11 @@ impl<'a> FontMatches<'a> {
|
|||
) -> FontShapeSpan {
|
||||
let span = &line[start_span..end_span];
|
||||
|
||||
log::debug!(" Span {}: '{}'", if span_rtl { "RTL" } else { "LTR" }, span);
|
||||
log::debug!(
|
||||
" Span {}: '{}'",
|
||||
if span_rtl { "RTL" } else { "LTR" },
|
||||
span
|
||||
);
|
||||
|
||||
let mut words = Vec::new();
|
||||
|
||||
|
|
@ -202,10 +223,22 @@ impl<'a> FontMatches<'a> {
|
|||
}
|
||||
}
|
||||
if start_word < start_lb {
|
||||
words.push(self.shape_word(line, start_span + start_word, start_span + start_lb, span_rtl, false));
|
||||
words.push(self.shape_word(
|
||||
line,
|
||||
start_span + start_word,
|
||||
start_span + start_lb,
|
||||
span_rtl,
|
||||
false,
|
||||
));
|
||||
}
|
||||
if start_lb < end_lb {
|
||||
words.push(self.shape_word(line, start_span + start_lb, start_span + end_lb, span_rtl, true));
|
||||
words.push(self.shape_word(
|
||||
line,
|
||||
start_span + start_lb,
|
||||
start_span + end_lb,
|
||||
span_rtl,
|
||||
true,
|
||||
));
|
||||
}
|
||||
start_word = end_lb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::Mutex,
|
||||
};
|
||||
use std::{collections::HashMap, sync::Mutex};
|
||||
|
||||
pub use self::cache::*;
|
||||
mod cache;
|
||||
|
|
@ -21,7 +18,6 @@ mod system;
|
|||
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct FontCacheKey {
|
||||
glyph_id: u16,
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||
|
|
|
|||
|
|
@ -26,27 +26,24 @@ impl<'a> FontShapeGlyph<'a> {
|
|||
let x_advance = font_size as f32 * self.x_advance;
|
||||
|
||||
#[cfg(feature = "ab_glyph")]
|
||||
let inner = self.font.ab_glyph.outline_glyph(
|
||||
self.inner.with_scale_and_position(
|
||||
let inner = self
|
||||
.font
|
||||
.ab_glyph
|
||||
.outline_glyph(self.inner.with_scale_and_position(
|
||||
font_size as f32,
|
||||
ab_glyph::point(
|
||||
x + x_offset,
|
||||
y - y_offset,
|
||||
)
|
||||
)
|
||||
);
|
||||
ab_glyph::point(x + x_offset, y - y_offset),
|
||||
));
|
||||
|
||||
#[cfg(feature = "rusttype")]
|
||||
let inner = self.font.rusttype.glyph(self.inner)
|
||||
let inner = self
|
||||
.font
|
||||
.rusttype
|
||||
.glyph(self.inner)
|
||||
.scaled(rusttype::Scale::uniform(font_size as f32))
|
||||
.positioned(rusttype::point(x + x_offset, y - y_offset));
|
||||
|
||||
#[cfg(feature = "swash")]
|
||||
let inner = CacheKey::new(
|
||||
self.inner,
|
||||
font_size,
|
||||
(x + x_offset, y - y_offset),
|
||||
);
|
||||
let inner = CacheKey::new(self.inner, font_size, (x + x_offset, y - y_offset));
|
||||
|
||||
FontLayoutGlyph {
|
||||
start: self.start,
|
||||
|
|
|
|||
|
|
@ -30,31 +30,28 @@ impl FontSystem {
|
|||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
db,
|
||||
}
|
||||
Self { db }
|
||||
}
|
||||
|
||||
pub fn matches<'a, F: Fn(&fontdb::FaceInfo) -> bool>(&'a self, f: F) -> Option<FontMatches<'a>> {
|
||||
pub fn matches<'a, F: Fn(&fontdb::FaceInfo) -> bool>(
|
||||
&'a self,
|
||||
f: F,
|
||||
) -> Option<FontMatches<'a>> {
|
||||
let mut fonts = Vec::new();
|
||||
for face in self.db.faces() {
|
||||
if ! f(face) {
|
||||
if !f(face) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let font_opt = Font::new(
|
||||
&face.post_script_name,
|
||||
match &face.source {
|
||||
fontdb::Source::Binary(data) => {
|
||||
data.deref().as_ref()
|
||||
},
|
||||
fontdb::Source::Binary(data) => data.deref().as_ref(),
|
||||
fontdb::Source::File(path) => {
|
||||
println!("Unsupported fontdb Source::File('{}')", path.display());
|
||||
continue;
|
||||
},
|
||||
fontdb::Source::SharedFile(_path, data) => {
|
||||
data.deref().as_ref()
|
||||
},
|
||||
}
|
||||
fontdb::Source::SharedFile(_path, data) => data.deref().as_ref(),
|
||||
},
|
||||
face.index,
|
||||
);
|
||||
|
|
@ -67,10 +64,8 @@ impl FontSystem {
|
|||
}
|
||||
}
|
||||
|
||||
if ! fonts.is_empty() {
|
||||
Some(FontMatches {
|
||||
fonts
|
||||
})
|
||||
if !fonts.is_empty() {
|
||||
Some(FontMatches { fonts })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,6 @@
|
|||
use orbclient::{Color, EventOption, Renderer, Window, WindowFlag};
|
||||
use std::{
|
||||
cmp,
|
||||
env,
|
||||
fs,
|
||||
time::Instant,
|
||||
};
|
||||
use text::{
|
||||
FontLineIndex,
|
||||
FontSystem,
|
||||
TextAction,
|
||||
TextCursor,
|
||||
TextBuffer,
|
||||
};
|
||||
use std::{cmp, env, fs, time::Instant};
|
||||
use text::{FontLineIndex, FontSystem, TextAction, TextBuffer, TextCursor};
|
||||
|
||||
fn main() {
|
||||
let display_scale = match orbclient::get_display_size() {
|
||||
|
|
@ -112,10 +101,13 @@ fn main() {
|
|||
|
||||
buffer.shape_until(scroll + window_lines);
|
||||
|
||||
scroll = cmp::max(0, cmp::min(
|
||||
buffer.layout_lines().len() as i32 - (window_lines - 1),
|
||||
scroll
|
||||
));
|
||||
scroll = cmp::max(
|
||||
0,
|
||||
cmp::min(
|
||||
buffer.layout_lines().len() as i32 - (window_lines - 1),
|
||||
scroll,
|
||||
),
|
||||
);
|
||||
|
||||
if rehit {
|
||||
let instant = Instant::now();
|
||||
|
|
@ -173,7 +165,12 @@ fn main() {
|
|||
let mut line_y = line_height;
|
||||
let mut start_line_opt = None;
|
||||
let mut end_line = FontLineIndex::new(0);
|
||||
for (line_i, line) in buffer.layout_lines().iter().skip(scroll as usize).enumerate() {
|
||||
for (line_i, line) in buffer
|
||||
.layout_lines()
|
||||
.iter()
|
||||
.skip(scroll as usize)
|
||||
.enumerate()
|
||||
{
|
||||
if line_y >= window.height() as i32 {
|
||||
break;
|
||||
}
|
||||
|
|
@ -236,7 +233,7 @@ fn main() {
|
|||
start_y as i32,
|
||||
line_x as u32,
|
||||
(end_y - start_y) as u32,
|
||||
Color::rgba(0xFF, 0xFF, 0xFF, 0x40)
|
||||
Color::rgba(0xFF, 0xFF, 0xFF, 0x40),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -251,39 +248,39 @@ fn main() {
|
|||
|
||||
for event in window.events() {
|
||||
match event.to_option() {
|
||||
EventOption::Key(event) => {
|
||||
match event.scancode {
|
||||
orbclient::K_CTRL => ctrl_pressed = event.pressed,
|
||||
orbclient::K_LEFT if event.pressed => buffer.action(TextAction::Left),
|
||||
orbclient::K_RIGHT if event.pressed => buffer.action(TextAction::Right),
|
||||
orbclient::K_UP if event.pressed => buffer.action(TextAction::Up),
|
||||
orbclient::K_DOWN if event.pressed => buffer.action(TextAction::Down),
|
||||
orbclient::K_BKSP if event.pressed => buffer.action(TextAction::Backspace),
|
||||
orbclient::K_DEL if event.pressed => buffer.action(TextAction::Delete),
|
||||
orbclient::K_PGUP if event.pressed => {
|
||||
scroll -= window_lines;
|
||||
buffer.redraw = true;
|
||||
},
|
||||
orbclient::K_PGDN if event.pressed => {
|
||||
scroll += window_lines;
|
||||
buffer.redraw = true;
|
||||
},
|
||||
orbclient::K_0 if event.pressed && ctrl_pressed => {
|
||||
font_size_i = font_size_default;
|
||||
buffer.set_font_size(font_sizes[font_size_i].0 * display_scale);
|
||||
},
|
||||
orbclient::K_MINUS if event.pressed && ctrl_pressed => if font_size_i > 0 {
|
||||
EventOption::Key(event) => match event.scancode {
|
||||
orbclient::K_CTRL => ctrl_pressed = event.pressed,
|
||||
orbclient::K_LEFT if event.pressed => buffer.action(TextAction::Left),
|
||||
orbclient::K_RIGHT if event.pressed => buffer.action(TextAction::Right),
|
||||
orbclient::K_UP if event.pressed => buffer.action(TextAction::Up),
|
||||
orbclient::K_DOWN if event.pressed => buffer.action(TextAction::Down),
|
||||
orbclient::K_BKSP if event.pressed => buffer.action(TextAction::Backspace),
|
||||
orbclient::K_DEL if event.pressed => buffer.action(TextAction::Delete),
|
||||
orbclient::K_PGUP if event.pressed => {
|
||||
scroll -= window_lines;
|
||||
buffer.redraw = true;
|
||||
}
|
||||
orbclient::K_PGDN if event.pressed => {
|
||||
scroll += window_lines;
|
||||
buffer.redraw = true;
|
||||
}
|
||||
orbclient::K_0 if event.pressed && ctrl_pressed => {
|
||||
font_size_i = font_size_default;
|
||||
buffer.set_font_size(font_sizes[font_size_i].0 * display_scale);
|
||||
}
|
||||
orbclient::K_MINUS if event.pressed && ctrl_pressed => {
|
||||
if font_size_i > 0 {
|
||||
font_size_i -= 1;
|
||||
buffer.set_font_size(font_sizes[font_size_i].0 * display_scale);
|
||||
}
|
||||
orbclient::K_EQUALS if event.pressed && ctrl_pressed => {
|
||||
if font_size_i + 1 < font_sizes.len() {
|
||||
font_size_i += 1;
|
||||
buffer.set_font_size(font_sizes[font_size_i].0 * display_scale);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
orbclient::K_EQUALS if event.pressed && ctrl_pressed => {
|
||||
if font_size_i + 1 < font_sizes.len() {
|
||||
font_size_i += 1;
|
||||
buffer.set_font_size(font_sizes[font_size_i].0 * display_scale);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
EventOption::TextInput(event) if !ctrl_pressed => {
|
||||
buffer.action(TextAction::Insert(event.character));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue