Added an enum with the option for "No Wraping"
This commit is contained in:
parent
48087b592b
commit
b9fef72f76
7 changed files with 169 additions and 96 deletions
|
|
@ -32,6 +32,7 @@ use cosmic_text::{
|
||||||
Metrics,
|
Metrics,
|
||||||
SyntaxEditor,
|
SyntaxEditor,
|
||||||
SyntaxSystem,
|
SyntaxSystem,
|
||||||
|
Wrap,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
|
|
@ -60,6 +61,12 @@ static FONT_SIZES: &'static [Metrics] = &[
|
||||||
Metrics::new(32, 44), // Title 1
|
Metrics::new(32, 44), // Title 1
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static WRAP_MODE: &'static [Wrap] = & [
|
||||||
|
Wrap::None,
|
||||||
|
Wrap::Glyph,
|
||||||
|
Wrap::Word,
|
||||||
|
];
|
||||||
|
|
||||||
fn main() -> cosmic::iced::Result {
|
fn main() -> cosmic::iced::Result {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
|
|
@ -87,6 +94,7 @@ pub enum Message {
|
||||||
Italic(bool),
|
Italic(bool),
|
||||||
Monospaced(bool),
|
Monospaced(bool),
|
||||||
MetricsChanged(Metrics),
|
MetricsChanged(Metrics),
|
||||||
|
WrapChanged(Wrap),
|
||||||
ThemeChanged(&'static str),
|
ThemeChanged(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,6 +221,10 @@ impl Application for Window {
|
||||||
let mut editor = self.editor.lock().unwrap();
|
let mut editor = self.editor.lock().unwrap();
|
||||||
editor.buffer_mut().set_metrics(metrics);
|
editor.buffer_mut().set_metrics(metrics);
|
||||||
},
|
},
|
||||||
|
Message::WrapChanged(wrap) => {
|
||||||
|
let mut editor = self.editor.lock().unwrap();
|
||||||
|
editor.buffer_mut().set_wrap(wrap);
|
||||||
|
},
|
||||||
Message::ThemeChanged(theme) => {
|
Message::ThemeChanged(theme) => {
|
||||||
self.theme = match theme {
|
self.theme = match theme {
|
||||||
"Dark" => Theme::Dark,
|
"Dark" => Theme::Dark,
|
||||||
|
|
@ -252,6 +264,15 @@ impl Application for Window {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let wrap_picker = {
|
||||||
|
let editor = self.editor.lock().unwrap();
|
||||||
|
pick_list(
|
||||||
|
WRAP_MODE,
|
||||||
|
Some(editor.buffer().wrap()),
|
||||||
|
Message::WrapChanged,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let content: Element<_> = column![
|
let content: Element<_> = column![
|
||||||
row![
|
row![
|
||||||
button(theme::Button::Secondary)
|
button(theme::Button::Secondary)
|
||||||
|
|
@ -271,6 +292,8 @@ impl Application for Window {
|
||||||
theme_picker,
|
theme_picker,
|
||||||
text("Font Size:"),
|
text("Font Size:"),
|
||||||
font_size_picker,
|
font_size_picker,
|
||||||
|
text("Wrap:"),
|
||||||
|
wrap_picker,
|
||||||
]
|
]
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.spacing(8)
|
.spacing(8)
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ where
|
||||||
let layout_lines = shape.layout(
|
let layout_lines = shape.layout(
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
limits.max().width as i32,
|
limits.max().width as i32,
|
||||||
self.line.wrap_simple()
|
self.line.wrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut width = 0;
|
let mut width = 0;
|
||||||
|
|
@ -180,7 +180,7 @@ where
|
||||||
let layout_lines = shape.layout(
|
let layout_lines = shape.layout(
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
layout_w,
|
layout_w,
|
||||||
self.line.wrap_simple()
|
self.line.wrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut cache = state.cache.lock().unwrap();
|
let mut cache = state.cache.lock().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use core::{
|
||||||
};
|
};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::{Attrs, AttrsList, BufferLine, FontSystem, LayoutGlyph, LayoutLine, ShapeLine};
|
use crate::{Attrs, AttrsList, BufferLine, FontSystem, LayoutGlyph, LayoutLine, ShapeLine, Wrap};
|
||||||
#[cfg(feature = "swash")]
|
#[cfg(feature = "swash")]
|
||||||
use crate::Color;
|
use crate::Color;
|
||||||
|
|
||||||
|
|
@ -157,6 +157,7 @@ pub struct Buffer<'a> {
|
||||||
scroll: i32,
|
scroll: i32,
|
||||||
/// True if a redraw is requires. Set to false after processing
|
/// True if a redraw is requires. Set to false after processing
|
||||||
redraw: bool,
|
redraw: bool,
|
||||||
|
wrap: Wrap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Buffer<'a> {
|
impl<'a> Buffer<'a> {
|
||||||
|
|
@ -173,6 +174,7 @@ impl<'a> Buffer<'a> {
|
||||||
height: 0,
|
height: 0,
|
||||||
scroll: 0,
|
scroll: 0,
|
||||||
redraw: false,
|
redraw: false,
|
||||||
|
wrap: Wrap::Word,
|
||||||
};
|
};
|
||||||
buffer.set_text("", Attrs::new());
|
buffer.set_text("", Attrs::new());
|
||||||
buffer
|
buffer
|
||||||
|
|
@ -188,7 +190,8 @@ impl<'a> Buffer<'a> {
|
||||||
line.layout(
|
line.layout(
|
||||||
self.font_system,
|
self.font_system,
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
self.width
|
self.width,
|
||||||
|
self.wrap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +220,8 @@ impl<'a> Buffer<'a> {
|
||||||
let layout = line.layout(
|
let layout = line.layout(
|
||||||
self.font_system,
|
self.font_system,
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
self.width
|
self.width,
|
||||||
|
self.wrap
|
||||||
);
|
);
|
||||||
total_layout += layout.len() as i32;
|
total_layout += layout.len() as i32;
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +253,8 @@ impl<'a> Buffer<'a> {
|
||||||
let layout = line.layout(
|
let layout = line.layout(
|
||||||
self.font_system,
|
self.font_system,
|
||||||
self.metrics.font_size,
|
self.metrics.font_size,
|
||||||
self.width
|
self.width,
|
||||||
|
self.wrap
|
||||||
);
|
);
|
||||||
if line_i == cursor.line {
|
if line_i == cursor.line {
|
||||||
let layout_cursor = self.layout_cursor(&cursor);
|
let layout_cursor = self.layout_cursor(&cursor);
|
||||||
|
|
@ -350,7 +355,7 @@ impl<'a> Buffer<'a> {
|
||||||
/// Lay out the provided line index and return the result
|
/// Lay out the provided line index and return the result
|
||||||
pub fn line_layout(&mut self, line_i: usize) -> Option<&[LayoutLine]> {
|
pub fn line_layout(&mut self, line_i: usize) -> Option<&[LayoutLine]> {
|
||||||
let line = self.lines.get_mut(line_i)?;
|
let line = self.lines.get_mut(line_i)?;
|
||||||
Some(line.layout(self.font_system, self.metrics.font_size, self.width))
|
Some(line.layout(self.font_system, self.metrics.font_size, self.width, self.wrap))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current [`Metrics`]
|
/// Get the current [`Metrics`]
|
||||||
|
|
@ -367,6 +372,20 @@ impl<'a> Buffer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current [`Wrap`]
|
||||||
|
pub fn wrap(&self) -> Wrap {
|
||||||
|
self.wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the current [`Wrap`]
|
||||||
|
pub fn set_wrap(&mut self, wrap: Wrap) {
|
||||||
|
if wrap != self.wrap {
|
||||||
|
self.wrap = wrap;
|
||||||
|
self.relayout();
|
||||||
|
self.shape_until_scroll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current buffer dimensions (width, height)
|
/// Get the current buffer dimensions (width, height)
|
||||||
pub fn size(&self) -> (i32, i32) {
|
pub fn size(&self) -> (i32, i32) {
|
||||||
(self.width, self.height)
|
(self.width, self.height)
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ use alloc::{
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{AttrsList, FontSystem, LayoutLine, ShapeLine};
|
use crate::{AttrsList, FontSystem, LayoutLine, ShapeLine, Wrap};
|
||||||
|
|
||||||
/// A line (or paragraph) of text that is shaped and laid out
|
/// A line (or paragraph) of text that is shaped and laid out
|
||||||
pub struct BufferLine {
|
pub struct BufferLine {
|
||||||
//TODO: make this not pub(crate)
|
//TODO: make this not pub(crate)
|
||||||
text: String,
|
text: String,
|
||||||
attrs_list: AttrsList,
|
attrs_list: AttrsList,
|
||||||
wrap_simple: bool,
|
wrap: Wrap,
|
||||||
shape_opt: Option<ShapeLine>,
|
shape_opt: Option<ShapeLine>,
|
||||||
layout_opt: Option<Vec<LayoutLine>>,
|
layout_opt: Option<Vec<LayoutLine>>,
|
||||||
}
|
}
|
||||||
|
|
@ -24,7 +24,7 @@ impl BufferLine {
|
||||||
Self {
|
Self {
|
||||||
text: text.into(),
|
text: text.into(),
|
||||||
attrs_list,
|
attrs_list,
|
||||||
wrap_simple: false,
|
wrap: Wrap::Word,
|
||||||
shape_opt: None,
|
shape_opt: None,
|
||||||
layout_opt: None,
|
layout_opt: None,
|
||||||
}
|
}
|
||||||
|
|
@ -69,18 +69,18 @@ impl BufferLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get simple wrapping setting (wrap by characters only)
|
/// Get wrapping setting (wrap by characters/words or no wrapping)
|
||||||
pub fn wrap_simple(&self) -> bool {
|
pub fn wrap(&self) -> Wrap {
|
||||||
self.wrap_simple
|
self.wrap
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set simple wrapping setting (wrap by characters only)
|
/// Set wrapping setting (wrap by characters/words or no wrapping)
|
||||||
///
|
///
|
||||||
/// Will reset shape and layout if it differs from current simple wrapping setting.
|
/// Will reset shape and layout if it differs from current wrapping setting.
|
||||||
/// Returns true if the line was reset
|
/// Returns true if the line was reset
|
||||||
pub fn set_wrap_simple(&mut self, wrap_simple: bool) -> bool {
|
pub fn set_wrap(&mut self, wrap: Wrap) -> bool {
|
||||||
if wrap_simple != self.wrap_simple {
|
if wrap != self.wrap {
|
||||||
self.wrap_simple = wrap_simple;
|
self.wrap = wrap;
|
||||||
self.reset();
|
self.reset();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -116,7 +116,7 @@ impl BufferLine {
|
||||||
self.reset();
|
self.reset();
|
||||||
|
|
||||||
let mut new = Self::new(text, attrs_list);
|
let mut new = Self::new(text, attrs_list);
|
||||||
new.wrap_simple = self.wrap_simple;
|
new.wrap = self.wrap;
|
||||||
new
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,14 +152,14 @@ impl BufferLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout line, will cache results
|
/// Layout line, will cache results
|
||||||
pub fn layout(&mut self, font_system: &FontSystem, font_size: i32, width: i32) -> &[LayoutLine] {
|
pub fn layout(&mut self, font_system: &FontSystem, font_size: i32, width: i32, wrap: Wrap) -> &[LayoutLine] {
|
||||||
if self.layout_opt.is_none() {
|
if self.layout_opt.is_none() {
|
||||||
let wrap_simple = self.wrap_simple;
|
self.wrap = wrap;
|
||||||
let shape = self.shape(font_system);
|
let shape = self.shape(font_system);
|
||||||
let layout = shape.layout(
|
let layout = shape.layout(
|
||||||
font_size,
|
font_size,
|
||||||
width,
|
width,
|
||||||
wrap_simple
|
wrap
|
||||||
);
|
);
|
||||||
self.layout_opt = Some(layout);
|
self.layout_opt = Some(layout);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ use crate::{
|
||||||
Editor,
|
Editor,
|
||||||
Style,
|
Style,
|
||||||
Weight,
|
Weight,
|
||||||
|
Wrap,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SyntaxSystem {
|
pub struct SyntaxSystem {
|
||||||
|
|
@ -225,7 +226,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> {
|
||||||
|
|
||||||
// Update line attributes. This operation only resets if the line changes
|
// Update line attributes. This operation only resets if the line changes
|
||||||
line.set_attrs_list(attrs_list);
|
line.set_attrs_list(attrs_list);
|
||||||
line.set_wrap_simple(false);
|
line.set_wrap(Wrap::Word);
|
||||||
|
|
||||||
//TODO: efficiently do syntax highlighting without having to shape whole buffer
|
//TODO: efficiently do syntax highlighting without having to shape whole buffer
|
||||||
buffer.line_shape(line_i);
|
buffer.line_shape(line_i);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
use core::fmt::Display;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
|
@ -57,3 +59,24 @@ pub struct LayoutLine {
|
||||||
/// Glyphs in line
|
/// Glyphs in line
|
||||||
pub glyphs: Vec<LayoutGlyph>,
|
pub glyphs: Vec<LayoutGlyph>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapping mode
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
pub enum Wrap {
|
||||||
|
/// No wrapping
|
||||||
|
None,
|
||||||
|
/// Wraps at a glyph level
|
||||||
|
Glyph,
|
||||||
|
/// Word Wrapping
|
||||||
|
Word,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Wrap {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::None => write!(f, "No Wrap"),
|
||||||
|
Self::Word => write!(f, "Word Wrap"),
|
||||||
|
Self::Glyph => write!(f, "Character"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
149
src/shape.rs
149
src/shape.rs
|
|
@ -8,7 +8,7 @@ use core::ops::Range;
|
||||||
use unicode_script::{Script, UnicodeScript};
|
use unicode_script::{Script, UnicodeScript};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::{AttrsList, CacheKey, Color, Font, FontSystem, LayoutGlyph, LayoutLine};
|
use crate::{AttrsList, CacheKey, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap};
|
||||||
use crate::fallback::FontFallbackIter;
|
use crate::fallback::FontFallbackIter;
|
||||||
|
|
||||||
fn shape_fallback(
|
fn shape_fallback(
|
||||||
|
|
@ -432,6 +432,9 @@ pub struct ShapeLine {
|
||||||
pub spans: Vec<ShapeSpan>,
|
pub spans: Vec<ShapeSpan>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Visual Line Ranges: (span_index, (first_word_index, first_glyph_index), (last_word_index, last_glyph_index))
|
||||||
|
type VlRange = (usize, (usize, usize), (usize, usize));
|
||||||
|
|
||||||
impl ShapeLine {
|
impl ShapeLine {
|
||||||
pub fn new<'a>(
|
pub fn new<'a>(
|
||||||
font_system: &'a FontSystem,
|
font_system: &'a FontSystem,
|
||||||
|
|
@ -543,7 +546,7 @@ impl ShapeLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A modified version of second part of unicode_bidi::bidi_info::visual run
|
// A modified version of second part of unicode_bidi::bidi_info::visual run
|
||||||
fn reorder(&self, line_range: &[(usize, (usize, usize), (usize, usize))]) -> Vec<Range<usize>> {
|
fn reorder(&self, line_range: &[VlRange]) -> Vec<Range<usize>> {
|
||||||
let line : Vec<unicode_bidi::Level> = line_range.iter().map(|(span_index, _, _)| self.spans[*span_index].level).collect();
|
let line : Vec<unicode_bidi::Level> = line_range.iter().map(|(span_index, _, _)| self.spans[*span_index].level).collect();
|
||||||
// Find consecutive level runs.
|
// Find consecutive level runs.
|
||||||
let mut runs = Vec::new();
|
let mut runs = Vec::new();
|
||||||
|
|
@ -608,7 +611,7 @@ impl ShapeLine {
|
||||||
&self,
|
&self,
|
||||||
font_size: i32,
|
font_size: i32,
|
||||||
line_width: i32,
|
line_width: i32,
|
||||||
wrap_simple: bool,
|
wrap: Wrap,
|
||||||
) -> Vec<LayoutLine> {
|
) -> Vec<LayoutLine> {
|
||||||
let mut layout_lines = Vec::with_capacity(1);
|
let mut layout_lines = Vec::with_capacity(1);
|
||||||
|
|
||||||
|
|
@ -622,31 +625,37 @@ impl ShapeLine {
|
||||||
let start_x = if self.rtl { line_width as f32 } else { 0.0 };
|
let start_x = if self.rtl { line_width as f32 } else { 0.0 };
|
||||||
let end_x = if self.rtl { 0.0 } else { line_width as f32 };
|
let end_x = if self.rtl { 0.0 } else { line_width as f32 };
|
||||||
let mut x = start_x;
|
let mut x = start_x;
|
||||||
let mut y = 0.0;
|
let mut y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This would keep the maximum number of spans that would fit on a visual line
|
// This would keep the maximum number of spans that would fit on a visual line
|
||||||
// If one span is too large, this variable will hold the range of words inside that span
|
// If one span is too large, this variable will hold the range of words inside that span
|
||||||
// that fits on a line.
|
// that fits on a line.
|
||||||
let mut current_visual_line: Vec<(usize, (usize, usize), (usize, usize))> = Vec::with_capacity(1);
|
let mut current_visual_line: Vec<VlRange> = Vec::with_capacity(1);
|
||||||
|
|
||||||
let mut fit_x = line_width as f32;
|
if wrap == Wrap::None {
|
||||||
|
for (span_index, span) in self.spans.iter().enumerate() {
|
||||||
|
current_visual_line.push((span_index, (0,0), (span.words.len(), 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let mut fit_x = line_width as f32;
|
||||||
|
for (span_index, span) in self.spans.iter().enumerate() {
|
||||||
|
|
||||||
for (span_index, span) in self.spans.iter().enumerate() {
|
let mut word_ranges = Vec::new();
|
||||||
|
let mut word_range_width = 0.;
|
||||||
|
|
||||||
let mut word_ranges: Vec<((usize, usize), (usize, usize), f32)> = Vec::new();
|
// Create the word ranges that fits in a visual line
|
||||||
let mut word_range_width = 0.;
|
if self.rtl != span.level.is_rtl() { // incongruent directions
|
||||||
|
let mut fitting_start = (span.words.len(), 0);
|
||||||
// Create the word ranges that fits in a visual line
|
for (i, word) in span.words.iter().enumerate().rev() {
|
||||||
if self.rtl != span.level.is_rtl() { // incongruent directions
|
let word_size = font_size as f32 * word.x_advance;
|
||||||
let mut fitting_start = (span.words.len(), 0);
|
if fit_x - word_size >= 0. { // fits
|
||||||
for (i, word) in span.words.iter().enumerate().rev() {
|
fit_x -= word_size;
|
||||||
let word_size = font_size as f32 * word.x_advance;
|
word_range_width += word_size;
|
||||||
if fit_x - word_size >= 0. { // fits
|
continue;
|
||||||
fit_x -= word_size;
|
} else if wrap == Wrap::Glyph {
|
||||||
word_range_width += word_size;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
if wrap_simple {
|
|
||||||
for (glyph_i, glyph) in word.glyphs.iter().enumerate().rev() {
|
for (glyph_i, glyph) in word.glyphs.iter().enumerate().rev() {
|
||||||
let glyph_size = font_size as f32 * glyph.x_advance;
|
let glyph_size = font_size as f32 * glyph.x_advance;
|
||||||
if fit_x - glyph_size >= 0. {
|
if fit_x - glyph_size >= 0. {
|
||||||
|
|
@ -660,7 +669,7 @@ impl ShapeLine {
|
||||||
fitting_start = (i, glyph_i+1);
|
fitting_start = (i, glyph_i+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else { // Wrap::Word
|
||||||
word_ranges.push(((i+1, 0), fitting_start, word_range_width));
|
word_ranges.push(((i+1, 0), fitting_start, word_range_width));
|
||||||
|
|
||||||
if word.blank {
|
if word.blank {
|
||||||
|
|
@ -674,19 +683,17 @@ impl ShapeLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
word_ranges.push(((0,0),fitting_start, word_range_width));
|
||||||
word_ranges.push(((0,0),fitting_start, word_range_width));
|
|
||||||
|
|
||||||
} else { // congruent direction
|
} else { // congruent direction
|
||||||
let mut fitting_start = (0,0);
|
let mut fitting_start = (0,0);
|
||||||
for (i, word) in span.words.iter().enumerate() {
|
for (i, word) in span.words.iter().enumerate() {
|
||||||
let word_size = font_size as f32 * word.x_advance;
|
let word_size = font_size as f32 * word.x_advance;
|
||||||
if fit_x - word_size >= 0. { // fits
|
if fit_x - word_size >= 0. { // fits
|
||||||
fit_x -= word_size;
|
fit_x -= word_size;
|
||||||
word_range_width += word_size;
|
word_range_width += word_size;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else if wrap == Wrap::Glyph {
|
||||||
if wrap_simple {
|
|
||||||
for (glyph_i, glyph) in word.glyphs.iter().enumerate() {
|
for (glyph_i, glyph) in word.glyphs.iter().enumerate() {
|
||||||
let glyph_size = font_size as f32 * glyph.x_advance;
|
let glyph_size = font_size as f32 * glyph.x_advance;
|
||||||
if fit_x - glyph_size >= 0. {
|
if fit_x - glyph_size >= 0. {
|
||||||
|
|
@ -700,7 +707,7 @@ impl ShapeLine {
|
||||||
fitting_start = (i, glyph_i);
|
fitting_start = (i, glyph_i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else { // Wrap::Word
|
||||||
word_ranges.push((fitting_start,(i,0), word_range_width));
|
word_ranges.push((fitting_start,(i,0), word_range_width));
|
||||||
|
|
||||||
if word.blank {
|
if word.blank {
|
||||||
|
|
@ -714,48 +721,48 @@ impl ShapeLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
word_ranges.push((fitting_start, (span.words.len(), 0), word_range_width));
|
||||||
word_ranges.push((fitting_start, (span.words.len(), 0), word_range_width));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a visual line
|
|
||||||
for ((starting_word, starting_glyph), (ending_word, ending_glyph), word_range_width) in word_ranges {
|
|
||||||
// To simplify the algorithm above, we might push empty ranges but we ignore them here
|
|
||||||
if ending_word == starting_word && starting_glyph == ending_glyph {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a visual line
|
||||||
let fits = !if self.rtl {
|
for ((starting_word, starting_glyph), (ending_word, ending_glyph), word_range_width) in word_ranges {
|
||||||
x - word_range_width < end_x
|
// To simplify the algorithm above, we might push empty ranges but we ignore them here
|
||||||
} else {
|
if ending_word == starting_word && starting_glyph == ending_glyph {
|
||||||
x + word_range_width > end_x
|
continue;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
if fits {
|
let fits = !if self.rtl {
|
||||||
current_visual_line.push((span_index, (starting_word, starting_glyph), (ending_word, ending_glyph)));
|
x - word_range_width < end_x
|
||||||
if self.rtl {
|
|
||||||
x -= word_range_width;
|
|
||||||
} else {
|
} else {
|
||||||
x += word_range_width;
|
x + word_range_width > end_x
|
||||||
}
|
};
|
||||||
} else {
|
|
||||||
if !current_visual_line.is_empty(){
|
|
||||||
vl_range_of_spans.push(current_visual_line);
|
if fits {
|
||||||
current_visual_line = Vec::with_capacity(1);
|
current_visual_line.push((span_index, (starting_word, starting_glyph), (ending_word, ending_glyph)));
|
||||||
x = start_x;
|
if self.rtl {
|
||||||
}
|
x -= word_range_width;
|
||||||
current_visual_line.push((span_index, (starting_word, starting_glyph), (ending_word, ending_glyph)));
|
} else {
|
||||||
if self.rtl {
|
x += word_range_width;
|
||||||
x -= word_range_width;
|
}
|
||||||
} else {
|
} else {
|
||||||
x += word_range_width;
|
if !current_visual_line.is_empty(){
|
||||||
}
|
vl_range_of_spans.push(current_visual_line);
|
||||||
if word_range_width > line_width as f32 { // single word is bigger than line_width
|
current_visual_line = Vec::with_capacity(1);
|
||||||
vl_range_of_spans.push(current_visual_line);
|
x = start_x;
|
||||||
current_visual_line = Vec::with_capacity(1);
|
}
|
||||||
x = start_x;
|
current_visual_line.push((span_index, (starting_word, starting_glyph), (ending_word, ending_glyph)));
|
||||||
|
if self.rtl {
|
||||||
|
x -= word_range_width;
|
||||||
|
} else {
|
||||||
|
x += word_range_width;
|
||||||
|
}
|
||||||
|
if word_range_width > line_width as f32 { // single word is bigger than line_width
|
||||||
|
vl_range_of_spans.push(current_visual_line);
|
||||||
|
current_visual_line = Vec::with_capacity(1);
|
||||||
|
x = start_x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue