2019-05-24 17:25:03 +00:00
|
|
|
use crate::display_object::{DisplayObject, DisplayObjectBase};
|
2019-05-04 18:45:11 +00:00
|
|
|
use crate::player::{RenderContext, UpdateContext};
|
2019-08-23 01:40:47 +00:00
|
|
|
use crate::prelude::*;
|
2019-05-09 21:14:21 +00:00
|
|
|
use crate::transform::Transform;
|
2019-05-04 18:45:11 +00:00
|
|
|
|
2019-08-28 23:29:43 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2019-08-13 02:00:12 +00:00
|
|
|
pub struct Text<'gc> {
|
|
|
|
base: DisplayObjectBase<'gc>,
|
2019-09-05 05:44:35 +00:00
|
|
|
static_data: gc_arena::Gc<'gc, TextStatic>,
|
2019-05-04 18:45:11 +00:00
|
|
|
}
|
|
|
|
|
2019-08-13 02:00:12 +00:00
|
|
|
impl<'gc> Text<'gc> {
|
2019-09-05 05:44:35 +00:00
|
|
|
pub fn from_swf_tag(context: &mut UpdateContext<'_, 'gc, '_>, tag: &swf::Text) -> Self {
|
2019-05-04 18:45:11 +00:00
|
|
|
Self {
|
|
|
|
base: Default::default(),
|
2019-09-06 22:19:59 +00:00
|
|
|
static_data: gc_arena::Gc::allocate(
|
|
|
|
context.gc_context,
|
|
|
|
TextStatic {
|
|
|
|
id: tag.id,
|
|
|
|
text_transform: tag.matrix.clone().into(),
|
|
|
|
text_blocks: tag.records.clone(),
|
|
|
|
},
|
|
|
|
),
|
2019-05-04 18:45:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-13 02:00:12 +00:00
|
|
|
impl<'gc> DisplayObject<'gc> for Text<'gc> {
|
2019-05-07 10:34:17 +00:00
|
|
|
impl_display_object!(base);
|
2019-05-04 18:45:11 +00:00
|
|
|
|
2019-09-15 18:34:30 +00:00
|
|
|
fn id(&self) -> CharacterId {
|
|
|
|
self.static_data.id
|
|
|
|
}
|
2019-09-15 18:44:18 +00:00
|
|
|
|
2019-05-04 18:45:11 +00:00
|
|
|
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
|
|
|
// Noop
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render(&self, context: &mut RenderContext) {
|
|
|
|
context.transform_stack.push(self.transform());
|
2019-08-23 01:40:47 +00:00
|
|
|
context.transform_stack.push(&Transform {
|
2019-09-05 05:44:35 +00:00
|
|
|
matrix: self.static_data.text_transform,
|
2019-08-23 01:40:47 +00:00
|
|
|
..Default::default()
|
|
|
|
});
|
2019-05-04 18:45:11 +00:00
|
|
|
|
|
|
|
let mut color = swf::Color {
|
|
|
|
r: 0,
|
|
|
|
g: 0,
|
|
|
|
b: 0,
|
|
|
|
a: 0,
|
|
|
|
};
|
|
|
|
let mut font_id = 0;
|
|
|
|
let mut height = 0;
|
2019-05-09 21:14:21 +00:00
|
|
|
let mut transform: Transform = Default::default();
|
2019-09-05 05:44:35 +00:00
|
|
|
for block in &self.static_data.text_blocks {
|
2019-08-27 00:46:38 +00:00
|
|
|
if let Some(x) = block.x_offset {
|
|
|
|
transform.matrix.tx = x.get() as f32;
|
|
|
|
}
|
|
|
|
if let Some(y) = block.y_offset {
|
|
|
|
transform.matrix.ty = y.get() as f32;
|
|
|
|
}
|
|
|
|
color = block.color.as_ref().unwrap_or(&color).clone();
|
2019-05-04 18:45:11 +00:00
|
|
|
font_id = block.font_id.unwrap_or(font_id);
|
|
|
|
height = block.height.unwrap_or(height);
|
|
|
|
if let Some(font) = context.library.get_font(font_id) {
|
2019-10-07 18:39:44 +00:00
|
|
|
let scale = f32::from(height) / font.scale();
|
|
|
|
transform.matrix.a = scale;
|
|
|
|
transform.matrix.d = scale;
|
|
|
|
transform.color_transform.r_mult = f32::from(color.r) / 255.0;
|
|
|
|
transform.color_transform.g_mult = f32::from(color.g) / 255.0;
|
|
|
|
transform.color_transform.b_mult = f32::from(color.b) / 255.0;
|
|
|
|
transform.color_transform.a_mult = f32::from(color.a) / 255.0;
|
2019-05-04 18:45:11 +00:00
|
|
|
for c in &block.glyphs {
|
|
|
|
if let Some(glyph) = font.get_glyph(c.index as usize) {
|
2019-05-09 21:14:21 +00:00
|
|
|
context.transform_stack.push(&transform);
|
|
|
|
context
|
|
|
|
.renderer
|
2019-10-08 02:27:31 +00:00
|
|
|
.render_shape(glyph.shape, context.transform_stack.transform());
|
2019-05-09 21:14:21 +00:00
|
|
|
context.transform_stack.pop();
|
2019-05-17 20:25:01 +00:00
|
|
|
transform.matrix.tx += c.advance as f32;
|
2019-05-04 18:45:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context.transform_stack.pop();
|
2019-08-23 01:40:47 +00:00
|
|
|
context.transform_stack.pop();
|
2019-05-04 18:45:11 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-24 17:25:03 +00:00
|
|
|
|
2019-08-13 02:00:12 +00:00
|
|
|
unsafe impl<'gc> gc_arena::Collect for Text<'gc> {
|
2019-05-24 17:25:03 +00:00
|
|
|
#[inline]
|
2019-08-23 06:28:51 +00:00
|
|
|
fn trace(&self, cc: gc_arena::CollectionContext) {
|
|
|
|
self.base.trace(cc);
|
2019-09-05 05:44:35 +00:00
|
|
|
self.static_data.trace(cc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Static data shared between all instances of a text object.
|
|
|
|
#[allow(dead_code)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct TextStatic {
|
|
|
|
id: CharacterId,
|
|
|
|
text_transform: Matrix,
|
|
|
|
text_blocks: Vec<swf::TextRecord>,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl<'gc> gc_arena::Collect for TextStatic {
|
|
|
|
#[inline]
|
|
|
|
fn needs_trace() -> bool {
|
|
|
|
false
|
2019-05-24 17:25:03 +00:00
|
|
|
}
|
|
|
|
}
|