Pre-strip HTML from HTML tags, rather than skipping them.
This commit is contained in:
parent
7d225f8b55
commit
18516c8eac
|
@ -55,11 +55,34 @@ impl<'gc> EditText<'gc> {
|
|||
let is_multiline = swf_tag.is_multiline;
|
||||
let is_word_wrap = swf_tag.is_word_wrap;
|
||||
|
||||
let text = if swf_tag.is_html {
|
||||
let mut result = String::new();
|
||||
let tag_text = swf_tag.initial_text.clone().unwrap_or_default();
|
||||
let mut chars = tag_text.chars().peekable();
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
// TODO: SWF text fields can contain a limited subset of HTML (and often do in SWF versions >6).
|
||||
// This is a quicky-and-dirty way to skip the HTML tags. This is obviously not correct
|
||||
// and we will need to properly parse and handle the HTML at some point.
|
||||
// See SWF19 pp. 173-174 for supported HTML tags.
|
||||
if c == '<' {
|
||||
// Skip characters until we see a close bracket.
|
||||
chars.by_ref().skip_while(|&x| x != '>').next();
|
||||
} else {
|
||||
result.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
} else {
|
||||
swf_tag.initial_text.clone().unwrap_or_default()
|
||||
};
|
||||
|
||||
EditText(GcCell::allocate(
|
||||
context.gc_context,
|
||||
EditTextData {
|
||||
base: Default::default(),
|
||||
text: swf_tag.initial_text.clone().unwrap_or_default(),
|
||||
text,
|
||||
new_format: TextFormat::default(),
|
||||
static_data: gc_arena::Gc::allocate(context.gc_context, EditTextStatic(swf_tag)),
|
||||
is_multiline,
|
||||
|
@ -271,12 +294,9 @@ impl<'gc> EditText<'gc> {
|
|||
breakpoints.push(break_base);
|
||||
}
|
||||
|
||||
for breakpoint in font.split_wrapped_lines(
|
||||
natural_line,
|
||||
height,
|
||||
self.line_width(),
|
||||
edit_text.static_data.0.is_html,
|
||||
) {
|
||||
for breakpoint in
|
||||
font.split_wrapped_lines(natural_line, height, self.line_width())
|
||||
{
|
||||
breakpoints.push(break_base + breakpoint);
|
||||
}
|
||||
|
||||
|
@ -349,7 +369,7 @@ impl<'gc> EditText<'gc> {
|
|||
.unwrap_or_else(|| font.scale());
|
||||
|
||||
for chunk in chunks {
|
||||
let chunk_size = font.measure(chunk, height, edit_text.static_data.0.is_html);
|
||||
let chunk_size = font.measure(chunk, height);
|
||||
|
||||
size.0 = size.0.max(chunk_size.0);
|
||||
if let Some(layout) = &static_data.layout {
|
||||
|
@ -449,7 +469,6 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
|
|||
chunk,
|
||||
text_transform.clone(),
|
||||
height,
|
||||
edit_text.static_data.0.is_html,
|
||||
|transform, glyph: &Glyph| {
|
||||
// Render glyph.
|
||||
context.transform_stack.push(transform);
|
||||
|
|
|
@ -133,7 +133,6 @@ impl<'gc> Font<'gc> {
|
|||
text: &str,
|
||||
mut transform: Transform,
|
||||
height: f32,
|
||||
is_html: bool,
|
||||
mut glyph_func: FGlyph,
|
||||
) where
|
||||
FGlyph: FnMut(&Transform, &Glyph),
|
||||
|
@ -146,14 +145,7 @@ impl<'gc> Font<'gc> {
|
|||
let mut chars = text.chars().peekable();
|
||||
let has_kerning_info = self.has_kerning_info();
|
||||
while let Some(c) = chars.next() {
|
||||
// TODO: SWF text fields can contain a limited subset of HTML (and often do in SWF versions >6).
|
||||
// This is a quicky-and-dirty way to skip the HTML tags. This is obviously not correct
|
||||
// and we will need to properly parse and handle the HTML at some point.
|
||||
// See SWF19 pp. 173-174 for supported HTML tags.
|
||||
if is_html && c == '<' {
|
||||
// Skip characters until we see a close bracket.
|
||||
chars.by_ref().skip_while(|&x| x != '>').next();
|
||||
} else if let Some(glyph) = self.get_glyph_for_char(c) {
|
||||
if let Some(glyph) = self.get_glyph_for_char(c) {
|
||||
glyph_func(&transform, &glyph);
|
||||
// Step horizontally.
|
||||
let mut advance = f32::from(glyph.advance);
|
||||
|
@ -168,21 +160,15 @@ impl<'gc> Font<'gc> {
|
|||
}
|
||||
|
||||
/// Measure a particular string's metrics (width and height).
|
||||
pub fn measure(self, text: &str, height: f32, is_html: bool) -> (f32, f32) {
|
||||
pub fn measure(self, text: &str, height: f32) -> (f32, f32) {
|
||||
let mut size = (0.0, 0.0);
|
||||
|
||||
self.evaluate(
|
||||
text,
|
||||
Default::default(),
|
||||
height,
|
||||
is_html,
|
||||
|transform, _glyph| {
|
||||
let tx = transform.matrix.tx / Twips::TWIPS_PER_PIXEL as f32;
|
||||
let ty = transform.matrix.ty / Twips::TWIPS_PER_PIXEL as f32;
|
||||
size.0 = f32::max(size.0, tx);
|
||||
size.1 = f32::max(size.1, ty);
|
||||
},
|
||||
);
|
||||
self.evaluate(text, Default::default(), height, |transform, _glyph| {
|
||||
let tx = transform.matrix.tx / Twips::TWIPS_PER_PIXEL as f32;
|
||||
let ty = transform.matrix.ty / Twips::TWIPS_PER_PIXEL as f32;
|
||||
size.0 = f32::max(size.0, tx);
|
||||
size.1 = f32::max(size.1, ty);
|
||||
});
|
||||
|
||||
size
|
||||
}
|
||||
|
@ -192,19 +178,13 @@ impl<'gc> Font<'gc> {
|
|||
///
|
||||
/// This function assumes only `" "` is valid whitespace to split words on,
|
||||
/// and will not attempt to break words that are longer than `width`.
|
||||
pub fn split_wrapped_lines(
|
||||
self,
|
||||
text: &str,
|
||||
height: f32,
|
||||
width: f32,
|
||||
is_html: bool,
|
||||
) -> Vec<usize> {
|
||||
pub fn split_wrapped_lines(self, text: &str, height: f32, width: f32) -> Vec<usize> {
|
||||
let mut result = vec![];
|
||||
let mut current_width = width;
|
||||
let mut current_word = &text[0..0];
|
||||
|
||||
for word in text.split(' ') {
|
||||
let measure = self.measure(word, height, is_html);
|
||||
let measure = self.measure(word, height);
|
||||
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() {
|
||||
line_start + current_word.len() + 1
|
||||
|
|
Loading…
Reference in New Issue