use bevy::{
color::Srgba,
ecs::component::Component,
math::{FloatOrd, Vec2},
};
use cosmic_text::{fontdb::ID, Attrs};
use std::{num::NonZeroU32, sync::Arc};
use crate::{prepare::family, GlyphMeta, StrokeJoin, Style, TextAlign, TextAnchor, Weight};
#[cfg(feature = "reflect")]
use bevy::prelude::{Reflect, ReflectComponent, ReflectDefault};
#[derive(Debug, Component, Clone)]
#[cfg_attr(feature = "reflect", derive(Reflect))]
#[cfg_attr(feature = "reflect", reflect(Component, Default))]
pub struct Text3dStyling {
pub size: f32,
pub font: Arc<str>,
pub style: Style,
pub weight: Weight,
pub align: TextAlign,
pub anchor: TextAnchor,
pub line_height: f32,
pub color: Srgba,
pub stroke_color: Srgba,
pub fill: bool,
pub stroke: Option<NonZeroU32>,
pub stroke_in_front: bool,
pub stroke_join: StrokeJoin,
pub layer_offset: f32,
pub uv1: (GlyphMeta, GlyphMeta),
pub tab_width: u16,
pub world_scale: Option<Vec2>,
pub text_shadow: Option<(Srgba, Vec2)>,
}
impl Default for Text3dStyling {
fn default() -> Self {
Self {
size: 16.,
color: Srgba::WHITE,
font: Default::default(),
style: Default::default(),
weight: Default::default(),
align: Default::default(),
anchor: TextAnchor::CENTER,
stroke_color: Srgba::WHITE,
fill: true,
stroke: Default::default(),
line_height: 1.0,
layer_offset: 0.01,
stroke_in_front: false,
stroke_join: StrokeJoin::Round,
uv1: (GlyphMeta::Index, GlyphMeta::PerGlyphAdvance),
tab_width: 4,
world_scale: None,
text_shadow: None,
}
}
}
#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct SegmentStyle {
pub font: Option<Arc<str>>,
pub fill_color: Option<Srgba>,
pub stroke_color: Option<Srgba>,
pub fill: Option<bool>,
pub stroke: Option<NonZeroU32>,
pub weight: Option<Weight>,
pub style: Option<Style>,
pub underline: Option<bool>,
pub strikethrough: Option<bool>,
pub magic_number: Option<f32>,
}
impl SegmentStyle {
pub fn as_attr<'t>(&'t self, base: &'t Text3dStyling) -> Attrs<'t> {
let family_name = self.font.as_ref().map(Arc::as_ref).unwrap_or(&base.font);
let family = family(family_name);
Attrs::new()
.weight(self.weight.unwrap_or(base.weight).into())
.style(self.style.unwrap_or(base.style).into())
.family(family)
}
pub fn join(&self, other: Self) -> Self {
SegmentStyle {
font: other.font.or_else(|| self.font.clone()),
fill_color: other.fill_color.or(self.fill_color),
stroke_color: other.stroke_color.or(self.stroke_color),
fill: other.fill.or(self.fill),
stroke: other.stroke.or(self.stroke),
weight: other.weight.or(self.weight),
underline: other.underline.or(self.underline),
strikethrough: other.strikethrough.or(self.strikethrough),
style: other.style.or(self.style),
magic_number: other.magic_number.or(self.magic_number),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct GlyphEntry {
pub font: ID,
pub glyph_id: GlyphTextureOf,
pub join: StrokeJoin,
pub size: FloatOrd,
pub weight: Weight,
pub stroke: Option<NonZeroU32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GlyphTextureOf {
Id(u16),
UnderlineTexture,
StrikethroughTexture,
}
impl From<u16> for GlyphTextureOf {
fn from(id: u16) -> Self {
GlyphTextureOf::Id(id)
}
}