Restore newline functionality (mostly...)
This commit is contained in:
parent
9f60567f66
commit
5fcaa52687
|
@ -174,24 +174,26 @@ impl<'gc> Font<'gc> {
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a line of text, split it into the shortest number of lines that
|
/// Given a line of text, find the first breakpoint within the text.
|
||||||
/// are shorter than `width`.
|
|
||||||
///
|
///
|
||||||
/// This function assumes only `" "` is valid whitespace to split words on,
|
/// This function assumes only `" "` is valid whitespace to split words on,
|
||||||
/// and will not attempt to break words that are longer than `width`.
|
/// and will not attempt to break words that are longer than `width`, nor
|
||||||
|
/// will it break at newlines.
|
||||||
///
|
///
|
||||||
/// The given `offset` determines the start of the initial line.
|
/// The given `offset` determines the start of the initial line, while the
|
||||||
|
/// `width` indicates how long the line is supposed to be.
|
||||||
|
///
|
||||||
|
/// This function yields `None` if the line is not broken.
|
||||||
///
|
///
|
||||||
/// TODO: This function and, more generally, this entire file will need to
|
/// TODO: This function and, more generally, this entire file will need to
|
||||||
/// be internationalized to implement AS3 `flash.text.engine`.
|
/// be internationalized to implement AS3 `flash.text.engine`.
|
||||||
pub fn split_wrapped_lines(
|
pub fn wrap_line(
|
||||||
self,
|
self,
|
||||||
text: &str,
|
text: &str,
|
||||||
font_size: Twips,
|
font_size: Twips,
|
||||||
width: Twips,
|
width: Twips,
|
||||||
offset: Twips,
|
offset: Twips,
|
||||||
) -> Vec<usize> {
|
) -> Option<usize> {
|
||||||
let mut result = vec![];
|
|
||||||
let mut current_width = width
|
let mut current_width = width
|
||||||
.checked_sub(offset)
|
.checked_sub(offset)
|
||||||
.unwrap_or_else(|| Twips::from_pixels(0.0));
|
.unwrap_or_else(|| Twips::from_pixels(0.0));
|
||||||
|
@ -200,29 +202,19 @@ impl<'gc> Font<'gc> {
|
||||||
for word in text.split(' ') {
|
for word in text.split(' ') {
|
||||||
let measure = self.measure(word, font_size);
|
let measure = self.measure(word, font_size);
|
||||||
let line_start = current_word.as_ptr() as usize - text.as_ptr() as usize;
|
let line_start = current_word.as_ptr() as usize - text.as_ptr() as usize;
|
||||||
let line_end = if (line_start + current_word.len() + 1) < text.len() {
|
let line_end = line_start + current_word.len();
|
||||||
line_start + current_word.len() + 1
|
|
||||||
} else {
|
|
||||||
line_start + current_word.len()
|
|
||||||
};
|
|
||||||
let word_start = word.as_ptr() as usize - text.as_ptr() as usize;
|
let word_start = word.as_ptr() as usize - text.as_ptr() as usize;
|
||||||
let word_end = if (word_start + word.len() + 1) < text.len() {
|
let word_end = word_start + word.len();
|
||||||
word_start + word.len() + 1
|
|
||||||
} else {
|
|
||||||
word_start + word.len()
|
|
||||||
};
|
|
||||||
|
|
||||||
if measure.0 > current_width && measure.0 > width {
|
if measure.0 > current_width && measure.0 > width {
|
||||||
//Failsafe for if we get a word wider than the field.
|
//Failsafe for if we get a word wider than the field.
|
||||||
if !current_word.is_empty() {
|
if !current_word.is_empty() {
|
||||||
result.push(line_end);
|
return Some(line_end);
|
||||||
}
|
}
|
||||||
result.push(word_end);
|
return Some(word_end);
|
||||||
current_word = &text[word_end..word_end];
|
|
||||||
current_width = width;
|
|
||||||
} else if measure.0 > current_width {
|
} else if measure.0 > current_width {
|
||||||
if !current_word.is_empty() {
|
if !current_word.is_empty() {
|
||||||
result.push(line_end);
|
return Some(line_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_word = &text[word_start..word_end];
|
current_word = &text[word_start..word_end];
|
||||||
|
@ -233,7 +225,7 @@ impl<'gc> Font<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn descriptor(self) -> FontDescriptor {
|
pub fn descriptor(self) -> FontDescriptor {
|
||||||
|
|
|
@ -44,6 +44,12 @@ impl<'gc> LayoutContext<'gc> {
|
||||||
&mut self.cursor
|
&mut self.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adjust the text layout cursor down to the next line.
|
||||||
|
fn newline(&mut self, font_size: Twips) {
|
||||||
|
self.cursor.set_x(Twips::from_pixels(0.0));
|
||||||
|
self.cursor += (Twips::from_pixels(0.0), font_size).into();
|
||||||
|
}
|
||||||
|
|
||||||
fn font(&self) -> Option<Font<'gc>> {
|
fn font(&self) -> Option<Font<'gc>> {
|
||||||
self.font
|
self.font
|
||||||
}
|
}
|
||||||
|
@ -217,36 +223,48 @@ impl<'gc> LayoutBox<'gc> {
|
||||||
for (start, _end, text, span) in fs.iter_spans() {
|
for (start, _end, text, span) in fs.iter_spans() {
|
||||||
if let Some(font) = layout_context.resolve_font(context, movie.clone(), &span) {
|
if let Some(font) = layout_context.resolve_font(context, movie.clone(), &span) {
|
||||||
let font_size = Twips::from_pixels(span.size);
|
let font_size = Twips::from_pixels(span.size);
|
||||||
let breakpoint_list =
|
|
||||||
font.split_wrapped_lines(&text, font_size, bounds, layout_context.cursor().x());
|
|
||||||
|
|
||||||
let end = text.len();
|
|
||||||
|
|
||||||
let mut last_breakpoint = 0;
|
let mut last_breakpoint = 0;
|
||||||
|
|
||||||
for breakpoint in breakpoint_list {
|
while let Some(breakpoint) = font.wrap_line(
|
||||||
if last_breakpoint != breakpoint {
|
&text[last_breakpoint..],
|
||||||
Self::append_text_fragment(
|
font_size,
|
||||||
context.gc_context,
|
bounds,
|
||||||
&mut layout_context,
|
layout_context.cursor().x(),
|
||||||
&text[last_breakpoint..breakpoint],
|
) {
|
||||||
start + last_breakpoint,
|
if breakpoint == last_breakpoint {
|
||||||
start + breakpoint,
|
last_breakpoint += 1;
|
||||||
span,
|
continue;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Self::append_text_fragment(
|
||||||
|
context.gc_context,
|
||||||
|
&mut layout_context,
|
||||||
|
&text[last_breakpoint..breakpoint],
|
||||||
|
start + last_breakpoint,
|
||||||
|
start + breakpoint,
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
|
||||||
last_breakpoint = breakpoint;
|
last_breakpoint = breakpoint;
|
||||||
|
if last_breakpoint >= text.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout_context.newline(font_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::append_text_fragment(
|
let span_end = text.len();
|
||||||
context.gc_context,
|
|
||||||
&mut layout_context,
|
if last_breakpoint < span_end {
|
||||||
&text[last_breakpoint..end],
|
Self::append_text_fragment(
|
||||||
start + last_breakpoint,
|
context.gc_context,
|
||||||
start + end,
|
&mut layout_context,
|
||||||
span,
|
&text[last_breakpoint..span_end],
|
||||||
);
|
start + last_breakpoint,
|
||||||
|
start + span_end,
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue