core: Add methods for introspecting text metrics on an `EditText`.
This commit is contained in:
parent
c0b6496b96
commit
1efa29baa6
|
@ -112,6 +112,7 @@ pub struct SystemClasses<'gc> {
|
|||
pub ioerror: ClassObject<'gc>,
|
||||
pub eoferror: ClassObject<'gc>,
|
||||
pub uncaughterrorevents: ClassObject<'gc>,
|
||||
pub textlinemetrics: ClassObject<'gc>,
|
||||
}
|
||||
|
||||
impl<'gc> SystemClasses<'gc> {
|
||||
|
@ -191,6 +192,7 @@ impl<'gc> SystemClasses<'gc> {
|
|||
ioerror: object,
|
||||
eoferror: object,
|
||||
uncaughterrorevents: object,
|
||||
textlinemetrics: object,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -730,6 +732,7 @@ fn load_playerglobal<'gc>(
|
|||
("flash.geom", "Transform", transform),
|
||||
("flash.geom", "ColorTransform", colortransform),
|
||||
("flash.utils", "ByteArray", bytearray),
|
||||
("flash.text", "TextLineMetrics", textlinemetrics),
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::display_object::{DisplayObjectBase, DisplayObjectPtr, TDisplayObject}
|
|||
use crate::drawing::Drawing;
|
||||
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode};
|
||||
use crate::font::{round_down_to_pixel, Glyph, TextRenderSettings};
|
||||
use crate::html::{BoxBounds, FormatSpans, LayoutBox, LayoutContent, TextFormat};
|
||||
use crate::html::{BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, TextFormat};
|
||||
use crate::prelude::*;
|
||||
use crate::string::{utils as string_utils, AvmString, WStr, WString};
|
||||
use crate::tag_utils::SwfMovie;
|
||||
|
@ -1383,6 +1383,78 @@ impl<'gc> EditText<'gc> {
|
|||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Count the number of lines in the text box's layout.
|
||||
pub fn layout_lines(self) -> usize {
|
||||
self.0.read().line_data.len()
|
||||
}
|
||||
|
||||
/// Calculate the layout metrics for a given line.
|
||||
///
|
||||
/// Returns None if the line does not exist or there is not enough data
|
||||
/// about the line to calculate metrics with.
|
||||
pub fn layout_metrics(self, line: usize) -> Option<LayoutMetrics> {
|
||||
let line = self.0.read().line_data.get(line).copied()?;
|
||||
let mut union_bounds = None;
|
||||
let mut font = None;
|
||||
let mut text_format = None;
|
||||
|
||||
let read = self.0.read();
|
||||
|
||||
for layout_box in read.layout.iter() {
|
||||
if layout_box.bounds().offset_y() < line.offset
|
||||
|| layout_box.bounds().extent_y() > line.extent
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
log::error!("{:?}", layout_box);
|
||||
|
||||
if let Some(bounds) = &mut union_bounds {
|
||||
*bounds += layout_box.bounds();
|
||||
} else {
|
||||
union_bounds = Some(layout_box.bounds());
|
||||
}
|
||||
|
||||
if font.is_none() {
|
||||
match layout_box.content() {
|
||||
LayoutContent::Text {
|
||||
font: box_font,
|
||||
text_format: box_text_format,
|
||||
..
|
||||
} => {
|
||||
font = Some(box_font);
|
||||
text_format = Some(box_text_format);
|
||||
}
|
||||
LayoutContent::Bullet {
|
||||
font: box_font,
|
||||
text_format: box_text_format,
|
||||
..
|
||||
} => {
|
||||
font = Some(box_font);
|
||||
text_format = Some(box_text_format);
|
||||
}
|
||||
LayoutContent::Drawing { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let union_bounds = union_bounds?;
|
||||
let font = font?;
|
||||
let size = Twips::from_pixels(text_format?.size?);
|
||||
let ascent = font.get_baseline_for_height(size);
|
||||
let descent = font.get_descent_for_height(size);
|
||||
let leading = font.get_leading_for_height(size);
|
||||
|
||||
Some(LayoutMetrics {
|
||||
ascent,
|
||||
descent,
|
||||
leading,
|
||||
width: union_bounds.width(),
|
||||
height: ascent + descent + leading,
|
||||
x: union_bounds.offset_x() + Twips::from_pixels(EditText::INTERNAL_PADDING),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
|
||||
|
|
|
@ -88,7 +88,6 @@ struct FontData {
|
|||
|
||||
/// The distance from the baseline of the font to the bottom of each glyph,
|
||||
/// in EM-square coordinates.
|
||||
#[allow(dead_code)]
|
||||
descent: u16,
|
||||
|
||||
/// The distance between the bottom of any one glyph and the top of
|
||||
|
@ -227,6 +226,13 @@ impl<'gc> Font<'gc> {
|
|||
Twips::new((self.0.ascent as f32 * scale) as i32)
|
||||
}
|
||||
|
||||
/// Get the descent from the baseline to the bottom of the glyph at a given height.
|
||||
pub fn get_descent_for_height(&self, height: Twips) -> Twips {
|
||||
let scale = height.get() as f32 / self.scale();
|
||||
|
||||
Twips::new((self.0.descent as f32 * scale) as i32)
|
||||
}
|
||||
|
||||
/// Returns whether this font contains kerning information.
|
||||
pub fn has_kerning_info(&self) -> bool {
|
||||
!self.0.kerning_pairs.is_empty()
|
||||
|
|
|
@ -8,7 +8,7 @@ mod text_format;
|
|||
pub use dimensions::BoxBounds;
|
||||
pub use dimensions::Position;
|
||||
pub use dimensions::Size;
|
||||
pub use layout::{LayoutBox, LayoutContent};
|
||||
pub use layout::{LayoutBox, LayoutContent, LayoutMetrics};
|
||||
pub use text_format::{FormatSpans, TextFormat, TextSpan};
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -555,7 +555,7 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> {
|
|||
#[derive(Clone, Debug, Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct LayoutBox<'gc> {
|
||||
/// The rectangle corresponding to the outer boundaries of the
|
||||
/// The rectangle corresponding to the outer boundaries of the content box.
|
||||
bounds: BoxBounds<Twips>,
|
||||
|
||||
/// What content is contained by the content box.
|
||||
|
@ -841,3 +841,14 @@ impl<'gc> LayoutBox<'gc> {
|
|||
matches!(&self.content, LayoutContent::Bullet { .. })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LayoutMetrics {
|
||||
pub ascent: Twips,
|
||||
pub descent: Twips,
|
||||
pub leading: Twips,
|
||||
|
||||
pub width: Twips,
|
||||
pub height: Twips,
|
||||
|
||||
pub x: Twips,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue