avm2: Implement TextField.getLineIndexOfChar()

This commit is contained in:
Kamil Jarosz 2024-06-27 21:17:52 +02:00
parent f2bbd241f9
commit ee8c9e21fa
4 changed files with 44 additions and 5 deletions

View File

@ -170,10 +170,7 @@ package flash.text {
return 0; return 0;
} }
public function getLineIndexOfChar(charIndex:int):int { public native function getLineIndexOfChar(charIndex:int):int;
stub_method("flash.text.TextField", "getLineIndexOfChar");
return 0;
}
public function getParagraphLength(charIndex:int):int { public function getParagraphLength(charIndex:int):int {
stub_method("flash.text.TextField", "getParagraphLength"); stub_method("flash.text.TextField", "getParagraphLength");

View File

@ -1444,3 +1444,28 @@ pub fn get_selected_text<'gc>(
} }
Ok("".into()) Ok("".into())
} }
pub fn get_line_index_of_char<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let Some(this) = this
.as_display_object()
.and_then(|this| this.as_edit_text())
else {
return Ok(Value::Undefined);
};
let index = args.get_i32(activation, 0)?;
if index < 0 {
// Docs say "throw RangeError", reality says "return -1".
return Ok(Value::Number(-1f64));
}
if let Some(line) = this.line_index_of_char(index as usize) {
Ok(line.into())
} else {
Ok(Value::Number(-1f64))
}
}

View File

@ -1931,6 +1931,10 @@ impl<'gc> EditText<'gc> {
Some(first_box.start()) Some(first_box.start())
} }
pub fn line_index_of_char(self, index: usize) -> Option<usize> {
self.0.read().layout.find_line_index_by_position(index)
}
fn execute_avm1_asfunction( fn execute_avm1_asfunction(
self, self,
context: &mut UpdateContext<'_, 'gc>, context: &mut UpdateContext<'_, 'gc>,

View File

@ -10,7 +10,7 @@ use crate::tag_utils::SwfMovie;
use crate::DefaultFont; use crate::DefaultFont;
use gc_arena::Collect; use gc_arena::Collect;
use ruffle_render::shape_utils::DrawCommand; use ruffle_render::shape_utils::DrawCommand;
use std::cmp::{max, min}; use std::cmp::{max, min, Ordering};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::mem; use std::mem;
use std::ops::{Deref, Range}; use std::ops::{Deref, Range};
@ -773,6 +773,19 @@ impl<'gc> Layout<'gc> {
boxes_iter: None, boxes_iter: None,
} }
} }
pub fn find_line_index_by_position(&self, position: usize) -> Option<usize> {
let result = self.lines.binary_search_by(|probe| {
if probe.end <= position {
Ordering::Less
} else if position < probe.start {
Ordering::Greater
} else {
Ordering::Equal
}
});
result.ok()
}
} }
/// A `LayoutLine` represents a single line of text. /// A `LayoutLine` represents a single line of text.