You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.8 KiB
Rust

//! 旧式 QET `<text>` 图元转换。
//!
//! 当前主流程主要使用 [`super::DynamicText`];该类型保留给仍需要静态文本
//! XML 的路径。它只掌握锚点而没有可靠字形测量,因此右/下边界尚未实现。
use super::{two_dec, FontInfo, ScaleEntity};
use dxf::entities;
use hex_color::HexColor;
use simple_xml_builder::XMLElement;
#[derive(Debug)]
/// QET 静态文本的内容、字体、颜色、位置和旋转。
pub struct Text {
rotation: f64,
value: String,
pub x: f64,
pub y: f64,
font: FontInfo,
color: HexColor,
}
impl From<(&entities::Text, HexColor)> for Text {
fn from((txt, color): (&entities::Text, HexColor)) -> Self {
// STANDARD 是 DXF 默认样式,无需在 QET 字体串中重复写出。
let mut font = FontInfo::default();
font.apply_height(txt.text_height);
if !txt.text_style_name.is_empty() && txt.text_style_name != "STANDARD" {
font.style_name = Some(txt.text_style_name.clone());
}
Text {
x: txt.location.x,
y: -txt.location.y,
rotation: if txt.rotation.abs().round() as i64 % 360 != 0 {
txt.rotation - 180.0
} else {
0.0
},
color,
font,
value: txt.value.clone(),
}
}
}
impl From<&Text> for XMLElement {
fn from(txt: &Text) -> Self {
// QET 静态文本把内容保存在 `text` 属性,而不是子节点中。
let mut txt_xml: XMLElement = XMLElement::new("text");
txt_xml.add_attribute("x", two_dec(txt.x));
txt_xml.add_attribute("y", two_dec(txt.y));
txt_xml.add_attribute("rotation", two_dec(txt.rotation));
txt_xml.add_attribute("color", txt.color.display_rgb());
txt_xml.add_attribute("font", &txt.font);
txt_xml.add_attribute("text", &txt.value);
txt_xml
}
}
impl Text {
/// 围绕块插入支点旋转文本锚点,并叠加文本自身旋转角。
pub(crate) fn rotate_around(&mut self, pivot_x: f64, pivot_y: f64, angle_deg: f64) {
let (x, y) = super::rotate_point_around(self.x, self.y, pivot_x, pivot_y, angle_deg);
self.x = x;
self.y = y;
self.rotation = super::normalize_angle(self.rotation + angle_deg);
}
}
impl ScaleEntity for Text {
fn scale(&mut self, fact_x: f64, fact_y: f64) {
self.x *= fact_x;
self.y *= fact_y;
self.font.scale(fact_y);
}
fn left_bound(&self) -> f64 {
self.x
}
fn top_bound(&self) -> f64 {
self.y
}
fn right_bound(&self) -> f64 {
// 静态 Text 没有字形布局结果,不能可靠计算右边界。
todo!()
}
fn bot_bound(&self) -> f64 {
// 静态 Text 没有字形布局结果,不能可靠计算下边界。
todo!()
}
}