text: Move lower_from_text_spans to module level
This commit is contained in:
parent
43b2cced0a
commit
d2f5b78503
|
@ -21,6 +21,7 @@ use crate::display_object::{DisplayObjectBase, DisplayObjectPtr};
|
||||||
use crate::drawing::Drawing;
|
use crate::drawing::Drawing;
|
||||||
use crate::events::{ClipEvent, ClipEventResult, TextControlCode};
|
use crate::events::{ClipEvent, ClipEventResult, TextControlCode};
|
||||||
use crate::font::{round_down_to_pixel, FontType, Glyph, TextRenderSettings};
|
use crate::font::{round_down_to_pixel, FontType, Glyph, TextRenderSettings};
|
||||||
|
use crate::html;
|
||||||
use crate::html::{
|
use crate::html::{
|
||||||
BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, Position, TextFormat,
|
BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, Position, TextFormat,
|
||||||
};
|
};
|
||||||
|
@ -287,7 +288,7 @@ impl<'gc> EditText<'gc> {
|
||||||
FontType::Device
|
FontType::Device
|
||||||
};
|
};
|
||||||
|
|
||||||
let (layout, intrinsic_bounds) = LayoutBox::lower_from_text_spans(
|
let (layout, intrinsic_bounds) = html::lower_from_text_spans(
|
||||||
&text_spans,
|
&text_spans,
|
||||||
context,
|
context,
|
||||||
swf_movie.clone(),
|
swf_movie.clone(),
|
||||||
|
@ -848,7 +849,7 @@ impl<'gc> EditText<'gc> {
|
||||||
FontType::Embedded
|
FontType::Embedded
|
||||||
};
|
};
|
||||||
|
|
||||||
let (new_layout, intrinsic_bounds) = LayoutBox::lower_from_text_spans(
|
let (new_layout, intrinsic_bounds) = html::lower_from_text_spans(
|
||||||
&edit_text.text_spans,
|
&edit_text.text_spans,
|
||||||
context,
|
context,
|
||||||
movie,
|
movie,
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod text_format;
|
||||||
|
|
||||||
pub use dimensions::BoxBounds;
|
pub use dimensions::BoxBounds;
|
||||||
pub use dimensions::Position;
|
pub use dimensions::Position;
|
||||||
pub use layout::{LayoutBox, LayoutContent, LayoutMetrics};
|
pub use layout::{lower_from_text_spans, LayoutBox, LayoutContent, LayoutMetrics};
|
||||||
pub use stylesheet::{transform_dashes_to_camel_case, CssStream};
|
pub use stylesheet::{transform_dashes_to_camel_case, CssStream};
|
||||||
pub use text_format::{FormatSpans, TextDisplay, TextFormat, TextSpan};
|
pub use text_format::{FormatSpans, TextDisplay, TextFormat, TextSpan};
|
||||||
|
|
||||||
|
|
|
@ -807,111 +807,78 @@ impl<'gc> LayoutBox<'gc> {
|
||||||
content: LayoutContent::Drawing(drawing),
|
content: LayoutContent::Drawing(drawing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a new layout hierarchy from text spans.
|
/// Construct a new layout hierarchy from text spans.
|
||||||
///
|
///
|
||||||
/// The returned bounds will include both the text bounds itself, as well
|
/// The returned bounds will include both the text bounds itself, as well
|
||||||
/// as left and right margins on any of the lines.
|
/// as left and right margins on any of the lines.
|
||||||
pub fn lower_from_text_spans(
|
pub fn lower_from_text_spans<'gc>(
|
||||||
fs: &FormatSpans,
|
fs: &FormatSpans,
|
||||||
context: &mut UpdateContext<'_, 'gc>,
|
context: &mut UpdateContext<'_, 'gc>,
|
||||||
movie: Arc<SwfMovie>,
|
movie: Arc<SwfMovie>,
|
||||||
bounds: Twips,
|
bounds: Twips,
|
||||||
is_word_wrap: bool,
|
is_word_wrap: bool,
|
||||||
font_type: FontType,
|
font_type: FontType,
|
||||||
) -> (Vec<LayoutBox<'gc>>, BoxBounds<Twips>) {
|
) -> (Vec<LayoutBox<'gc>>, BoxBounds<Twips>) {
|
||||||
let mut layout_context = LayoutContext::new(movie, bounds, fs.displayed_text());
|
let mut layout_context = LayoutContext::new(movie, bounds, fs.displayed_text());
|
||||||
|
|
||||||
for (span_start, _end, span_text, span) in fs.iter_spans() {
|
for (span_start, _end, span_text, span) in fs.iter_spans() {
|
||||||
if let Some(font) = layout_context.resolve_font(context, span, font_type) {
|
if let Some(font) = layout_context.resolve_font(context, span, font_type) {
|
||||||
layout_context.font = Some(font);
|
layout_context.font = Some(font);
|
||||||
layout_context.newspan(span);
|
layout_context.newspan(span);
|
||||||
|
|
||||||
let params = EvalParameters::from_span(span);
|
let params = EvalParameters::from_span(span);
|
||||||
|
|
||||||
for text in span_text.split(&[b'\n', b'\r', b'\t'][..]) {
|
for text in span_text.split(&[b'\n', b'\r', b'\t'][..]) {
|
||||||
let slice_start = text.offset_in(span_text).unwrap();
|
let slice_start = text.offset_in(span_text).unwrap();
|
||||||
let delimiter = if slice_start > 0 {
|
let delimiter = if slice_start > 0 {
|
||||||
span_text
|
span_text
|
||||||
.get(slice_start - 1)
|
.get(slice_start - 1)
|
||||||
.and_then(|c| u8::try_from(c).ok())
|
.and_then(|c| u8::try_from(c).ok())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
match delimiter {
|
match delimiter {
|
||||||
Some(b'\n' | b'\r') => layout_context.explicit_newline(
|
Some(b'\n' | b'\r') => layout_context.explicit_newline(
|
||||||
context,
|
context,
|
||||||
fs.displayed_text(),
|
fs.displayed_text(),
|
||||||
span_start + slice_start - 1,
|
span_start + slice_start - 1,
|
||||||
span,
|
span,
|
||||||
font_type,
|
font_type,
|
||||||
),
|
),
|
||||||
Some(b'\t') => layout_context.tab(),
|
Some(b'\t') => layout_context.tab(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = span_start + slice_start;
|
let start = span_start + slice_start;
|
||||||
|
|
||||||
let mut last_breakpoint = 0;
|
let mut last_breakpoint = 0;
|
||||||
|
|
||||||
if is_word_wrap {
|
if is_word_wrap {
|
||||||
let (mut width, mut offset) = layout_context.wrap_dimensions(span);
|
let (mut width, mut offset) = layout_context.wrap_dimensions(span);
|
||||||
|
|
||||||
while let Some(breakpoint) = font.wrap_line(
|
while let Some(breakpoint) = font.wrap_line(
|
||||||
&text[last_breakpoint..],
|
&text[last_breakpoint..],
|
||||||
params,
|
params,
|
||||||
width,
|
width,
|
||||||
offset,
|
offset,
|
||||||
layout_context.is_start_of_line(),
|
layout_context.is_start_of_line(),
|
||||||
) {
|
) {
|
||||||
// This ensures that the space causing the line break
|
// This ensures that the space causing the line break
|
||||||
// is included in the line it broke.
|
// is included in the line it broke.
|
||||||
let next_breakpoint = string_utils::next_char_boundary(
|
let next_breakpoint =
|
||||||
text,
|
string_utils::next_char_boundary(text, last_breakpoint + breakpoint);
|
||||||
last_breakpoint + breakpoint,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If text doesn't fit at the start of a line, it
|
|
||||||
// won't fit on the next either, abort and put the
|
|
||||||
// whole text on the line (will be cut-off). This
|
|
||||||
// can happen for small text fields with single
|
|
||||||
// characters.
|
|
||||||
if breakpoint == 0 && layout_context.is_start_of_line() {
|
|
||||||
break;
|
|
||||||
} else if breakpoint == 0 {
|
|
||||||
layout_context.newline(
|
|
||||||
context,
|
|
||||||
fs.displayed_text(),
|
|
||||||
start + next_breakpoint,
|
|
||||||
span,
|
|
||||||
font_type,
|
|
||||||
);
|
|
||||||
|
|
||||||
let next_dim = layout_context.wrap_dimensions(span);
|
|
||||||
|
|
||||||
width = next_dim.0;
|
|
||||||
offset = next_dim.1;
|
|
||||||
|
|
||||||
if last_breakpoint >= text.len() {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout_context.append_text(
|
|
||||||
&text[last_breakpoint..next_breakpoint],
|
|
||||||
start + last_breakpoint,
|
|
||||||
start + next_breakpoint,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
|
|
||||||
last_breakpoint = next_breakpoint;
|
|
||||||
if last_breakpoint >= text.len() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// If text doesn't fit at the start of a line, it
|
||||||
|
// won't fit on the next either, abort and put the
|
||||||
|
// whole text on the line (will be cut-off). This
|
||||||
|
// can happen for small text fields with single
|
||||||
|
// characters.
|
||||||
|
if breakpoint == 0 && layout_context.is_start_of_line() {
|
||||||
|
break;
|
||||||
|
} else if breakpoint == 0 {
|
||||||
layout_context.newline(
|
layout_context.newline(
|
||||||
context,
|
context,
|
||||||
fs.displayed_text(),
|
fs.displayed_text(),
|
||||||
|
@ -919,30 +886,63 @@ impl<'gc> LayoutBox<'gc> {
|
||||||
span,
|
span,
|
||||||
font_type,
|
font_type,
|
||||||
);
|
);
|
||||||
|
|
||||||
let next_dim = layout_context.wrap_dimensions(span);
|
let next_dim = layout_context.wrap_dimensions(span);
|
||||||
|
|
||||||
width = next_dim.0;
|
width = next_dim.0;
|
||||||
offset = next_dim.1;
|
offset = next_dim.1;
|
||||||
|
|
||||||
|
if last_breakpoint >= text.len() {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let span_end = text.len();
|
|
||||||
|
|
||||||
if last_breakpoint < span_end {
|
|
||||||
layout_context.append_text(
|
layout_context.append_text(
|
||||||
&text[last_breakpoint..span_end],
|
&text[last_breakpoint..next_breakpoint],
|
||||||
start + last_breakpoint,
|
start + last_breakpoint,
|
||||||
start + span_end,
|
start + next_breakpoint,
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
last_breakpoint = next_breakpoint;
|
||||||
|
if last_breakpoint >= text.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout_context.newline(
|
||||||
|
context,
|
||||||
|
fs.displayed_text(),
|
||||||
|
start + next_breakpoint,
|
||||||
|
span,
|
||||||
|
font_type,
|
||||||
|
);
|
||||||
|
let next_dim = layout_context.wrap_dimensions(span);
|
||||||
|
|
||||||
|
width = next_dim.0;
|
||||||
|
offset = next_dim.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let span_end = text.len();
|
||||||
|
|
||||||
|
if last_breakpoint < span_end {
|
||||||
|
layout_context.append_text(
|
||||||
|
&text[last_breakpoint..span_end],
|
||||||
|
start + last_breakpoint,
|
||||||
|
start + span_end,
|
||||||
|
span,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layout_context.end_layout(context, fs, font_type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout_context.end_layout(context, fs, font_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gc> LayoutBox<'gc> {
|
||||||
pub fn bounds(&self) -> BoxBounds<Twips> {
|
pub fn bounds(&self) -> BoxBounds<Twips> {
|
||||||
self.bounds
|
self.bounds
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue