|
|
|
@ -6,6 +6,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
|
|
|
use uuid::Uuid;
|
|
|
|
use uuid::Uuid;
|
|
|
|
use dxf::enums::AttachmentPoint;
|
|
|
|
use dxf::enums::AttachmentPoint;
|
|
|
|
use dxf::enums::{HorizontalTextJustification, VerticalTextJustification};
|
|
|
|
use dxf::enums::{HorizontalTextJustification, VerticalTextJustification};
|
|
|
|
|
|
|
|
use dxf::Point;
|
|
|
|
|
|
|
|
|
|
|
|
/*use parley::{
|
|
|
|
/*use parley::{
|
|
|
|
Alignment, FontContext, FontWeight, InlineBox, Layout, LayoutContext, PositionedLayoutItem,
|
|
|
|
Alignment, FontContext, FontWeight, InlineBox, Layout, LayoutContext, PositionedLayoutItem,
|
|
|
|
@ -56,15 +57,6 @@ impl From<&DynamicText> for XMLElement {
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// it's just annoying if the value for "reference_rectangle_width" in the dxf is “0.0”...
|
|
|
|
// it's just annoying if the value for "reference_rectangle_width" in the dxf is “0.0”...
|
|
|
|
//
|
|
|
|
|
|
|
|
println!("文本:{}", txt.text);
|
|
|
|
|
|
|
|
println!("对齐方式:{}, {}", txt.h_alignment, txt.v_alignment);
|
|
|
|
|
|
|
|
println!("文本宽度: {}", txt.text_width);
|
|
|
|
|
|
|
|
println!("relative_x_scale_factor: {}", txt.relative_x_scale_factor);
|
|
|
|
|
|
|
|
println!("文本高度:{}", pt_size);
|
|
|
|
|
|
|
|
println!("初始左下角位置: x={}, y={}", txt.x, txt.y);
|
|
|
|
|
|
|
|
println!("初始对齐位置: x={}, y={}", txt.align_x, txt.align_y);
|
|
|
|
|
|
|
|
println!("旋转角度: {}", txt.rotation);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算基础位置(不考虑旋转)
|
|
|
|
// 计算基础位置(不考虑旋转)
|
|
|
|
// txt.x和txt.y现在是左下角位置
|
|
|
|
// txt.x和txt.y现在是左下角位置
|
|
|
|
@ -96,8 +88,6 @@ impl From<&DynamicText> for XMLElement {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
println!("左上角位置: x={}, y={}", left_x, top_y);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let base_x = left_x;
|
|
|
|
let base_x = left_x;
|
|
|
|
let base_y = top_y;
|
|
|
|
let base_y = top_y;
|
|
|
|
|
|
|
|
|
|
|
|
@ -119,9 +109,6 @@ impl From<&DynamicText> for XMLElement {
|
|
|
|
(base_x, base_y)
|
|
|
|
(base_x, base_y)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
println!("最终位置: x={}, y={}", x_pos, y_pos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dtxt_xml.add_attribute("x", two_dec(x_pos));
|
|
|
|
dtxt_xml.add_attribute("x", two_dec(x_pos));
|
|
|
|
dtxt_xml.add_attribute("y", two_dec(y_pos));
|
|
|
|
dtxt_xml.add_attribute("y", two_dec(y_pos));
|
|
|
|
dtxt_xml.add_attribute("z", two_dec(txt.z));
|
|
|
|
dtxt_xml.add_attribute("z", two_dec(txt.z));
|
|
|
|
@ -230,8 +217,7 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
|
|
|
|
|
|
|
|
pub fn build(self) -> DynamicText {
|
|
|
|
pub fn build(self) -> DynamicText {
|
|
|
|
let (
|
|
|
|
let (
|
|
|
|
x,
|
|
|
|
anchor_point,
|
|
|
|
y,
|
|
|
|
|
|
|
|
z,
|
|
|
|
z,
|
|
|
|
rotation,
|
|
|
|
rotation,
|
|
|
|
style_name,
|
|
|
|
style_name,
|
|
|
|
@ -240,19 +226,17 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
h_alignment,
|
|
|
|
h_alignment,
|
|
|
|
v_alignment,
|
|
|
|
v_alignment,
|
|
|
|
reference_rectangle_width,
|
|
|
|
reference_rectangle_width,
|
|
|
|
align_x,
|
|
|
|
|
|
|
|
align_y,
|
|
|
|
|
|
|
|
relative_x_scale_factor,
|
|
|
|
relative_x_scale_factor,
|
|
|
|
) = match self.text {
|
|
|
|
) = match self.text {
|
|
|
|
TextEntity::Text(txt) => {
|
|
|
|
TextEntity::Text(txt) => {
|
|
|
|
// let (x, y) = if txt.horizontal_text_justification == HorizontalTextJustification::Left && (txt.vertical_text_justification == VerticalTextJustification::Bottom || txt.vertical_text_justification == VerticalTextJustification::Baseline) {
|
|
|
|
let anchor = resolve_alignment_point(
|
|
|
|
// (txt.location.x, -txt.location.y)
|
|
|
|
&txt.location,
|
|
|
|
// } else {
|
|
|
|
&txt.second_alignment_point,
|
|
|
|
// (txt.second_alignment_point.x, -txt.second_alignment_point.y)
|
|
|
|
txt.horizontal_text_justification,
|
|
|
|
// };
|
|
|
|
txt.vertical_text_justification,
|
|
|
|
|
|
|
|
);
|
|
|
|
(
|
|
|
|
(
|
|
|
|
txt.location.x,
|
|
|
|
anchor,
|
|
|
|
-txt.location.y,
|
|
|
|
|
|
|
|
txt.location.z,
|
|
|
|
txt.location.z,
|
|
|
|
txt.rotation,
|
|
|
|
txt.rotation,
|
|
|
|
&txt.text_style_name,
|
|
|
|
&txt.text_style_name,
|
|
|
|
@ -261,16 +245,13 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
HAlignment::from(txt.horizontal_text_justification),
|
|
|
|
HAlignment::from(txt.horizontal_text_justification),
|
|
|
|
VAlignment::from_text_entity(txt.vertical_text_justification, true),
|
|
|
|
VAlignment::from_text_entity(txt.vertical_text_justification, true),
|
|
|
|
0.0, // as Placeholder: no "reference_rectangle_width" with Text!!!
|
|
|
|
0.0, // as Placeholder: no "reference_rectangle_width" with Text!!!
|
|
|
|
txt.second_alignment_point.x,
|
|
|
|
|
|
|
|
-txt.second_alignment_point.y,
|
|
|
|
|
|
|
|
txt.relative_x_scale_factor,
|
|
|
|
txt.relative_x_scale_factor,
|
|
|
|
)},
|
|
|
|
)},
|
|
|
|
TextEntity::MText(mtxt) => {
|
|
|
|
TextEntity::MText(mtxt) => {
|
|
|
|
// 计算实际的旋转角度,优先使用x_axis_direction向量
|
|
|
|
// 计算实际的旋转角度,优先使用x_axis_direction向量
|
|
|
|
let actual_rotation = calculate_mtext_rotation(mtxt.rotation_angle, &mtxt.x_axis_direction);
|
|
|
|
let actual_rotation = calculate_mtext_rotation(mtxt.rotation_angle, &mtxt.x_axis_direction);
|
|
|
|
(
|
|
|
|
(
|
|
|
|
mtxt.insertion_point.x,
|
|
|
|
mtxt.insertion_point.clone(),
|
|
|
|
-mtxt.insertion_point.y,
|
|
|
|
|
|
|
|
mtxt.insertion_point.z,
|
|
|
|
mtxt.insertion_point.z,
|
|
|
|
actual_rotation,
|
|
|
|
actual_rotation,
|
|
|
|
&mtxt.text_style_name,
|
|
|
|
&mtxt.text_style_name,
|
|
|
|
@ -302,22 +283,17 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
HAlignment::from(mtxt.attachment_point),
|
|
|
|
HAlignment::from(mtxt.attachment_point),
|
|
|
|
VAlignment::from(mtxt.attachment_point),
|
|
|
|
VAlignment::from(mtxt.attachment_point),
|
|
|
|
mtxt.reference_rectangle_width,
|
|
|
|
mtxt.reference_rectangle_width,
|
|
|
|
mtxt.insertion_point.x,
|
|
|
|
|
|
|
|
-mtxt.insertion_point.y,
|
|
|
|
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
)},
|
|
|
|
)},
|
|
|
|
TextEntity::Attrib(attrib) => {
|
|
|
|
TextEntity::Attrib(attrib) => {
|
|
|
|
// 根据DXF文本对齐规则,当水平对齐不是Left时,使用second_alignment_point
|
|
|
|
let anchor = resolve_alignment_point(
|
|
|
|
// let (x, y) = if attrib.horizontal_text_justification == HorizontalTextJustification::Left && (attrib.vertical_text_justification == VerticalTextJustification::Bottom || attrib.vertical_text_justification == VerticalTextJustification::Baseline) {
|
|
|
|
&attrib.location,
|
|
|
|
// println!("{}",111);
|
|
|
|
&attrib.second_alignment_point,
|
|
|
|
// (attrib.location.x, -attrib.location.y)
|
|
|
|
attrib.horizontal_text_justification,
|
|
|
|
// } else {
|
|
|
|
attrib.vertical_text_justification,
|
|
|
|
// println!("{}",222);
|
|
|
|
);
|
|
|
|
// (attrib.second_alignment_point.x, -attrib.second_alignment_point.y)
|
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
(
|
|
|
|
(
|
|
|
|
attrib.location.x,
|
|
|
|
anchor,
|
|
|
|
-attrib.location.y,
|
|
|
|
|
|
|
|
attrib.location.z,
|
|
|
|
attrib.location.z,
|
|
|
|
attrib.rotation,
|
|
|
|
attrib.rotation,
|
|
|
|
&attrib.text_style_name,
|
|
|
|
&attrib.text_style_name,
|
|
|
|
@ -326,8 +302,6 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
HAlignment::from(attrib.horizontal_text_justification),
|
|
|
|
HAlignment::from(attrib.horizontal_text_justification),
|
|
|
|
VAlignment::from_text_entity(attrib.vertical_text_justification, true),
|
|
|
|
VAlignment::from_text_entity(attrib.vertical_text_justification, true),
|
|
|
|
0.0, // as Placeholder: not need to check if Attrib has something similar
|
|
|
|
0.0, // as Placeholder: not need to check if Attrib has something similar
|
|
|
|
attrib.second_alignment_point.x,
|
|
|
|
|
|
|
|
-attrib.second_alignment_point.y,
|
|
|
|
|
|
|
|
attrib.relative_x_scale_factor,
|
|
|
|
attrib.relative_x_scale_factor,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
@ -372,8 +346,16 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
estimate_text_width(&value, text_height, relative_x_scale_factor)
|
|
|
|
estimate_text_width(&value, text_height, relative_x_scale_factor)
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let anchor_qet = (anchor_point.x, -anchor_point.y);
|
|
|
|
|
|
|
|
let (x, y) = compute_left_bottom(
|
|
|
|
|
|
|
|
&anchor_point,
|
|
|
|
|
|
|
|
&h_alignment,
|
|
|
|
|
|
|
|
&v_alignment,
|
|
|
|
|
|
|
|
text_width,
|
|
|
|
|
|
|
|
text_height,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
DynamicText {
|
|
|
|
DynamicText {
|
|
|
|
//x: x - (calc_width as f64/2.0),
|
|
|
|
|
|
|
|
x,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
y,
|
|
|
|
z,
|
|
|
|
z,
|
|
|
|
@ -399,15 +381,15 @@ impl<'a> DTextBuilder<'a> {
|
|
|
|
text_from: "UserText".into(),
|
|
|
|
text_from: "UserText".into(),
|
|
|
|
frame: false,
|
|
|
|
frame: false,
|
|
|
|
text_height,
|
|
|
|
text_height,
|
|
|
|
text_width: -1.0,
|
|
|
|
text_width,
|
|
|
|
relative_x_scale_factor,//宽度系数
|
|
|
|
relative_x_scale_factor,//宽度系数
|
|
|
|
color: self.color.unwrap_or(HexColor::BLACK),
|
|
|
|
color: self.color.unwrap_or(HexColor::BLACK),
|
|
|
|
|
|
|
|
|
|
|
|
text: value,
|
|
|
|
text: value,
|
|
|
|
keep_visual_rotation: false,
|
|
|
|
keep_visual_rotation: false,
|
|
|
|
info_name: None,
|
|
|
|
info_name: None,
|
|
|
|
align_x,
|
|
|
|
align_x: anchor_qet.0,
|
|
|
|
align_y,
|
|
|
|
align_y: anchor_qet.1,
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -521,3 +503,51 @@ fn estimate_text_width(text: &str, line_height: f64, relative_x_scale_factor: f6
|
|
|
|
|
|
|
|
|
|
|
|
base_width * scale
|
|
|
|
base_width * scale
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn resolve_alignment_point(
|
|
|
|
|
|
|
|
location: &Point,
|
|
|
|
|
|
|
|
second_alignment_point: &Point,
|
|
|
|
|
|
|
|
horizontal_justification: HorizontalTextJustification,
|
|
|
|
|
|
|
|
vertical_justification: VerticalTextJustification,
|
|
|
|
|
|
|
|
) -> Point {
|
|
|
|
|
|
|
|
let use_second = !matches!(horizontal_justification, HorizontalTextJustification::Left)
|
|
|
|
|
|
|
|
|| matches!(
|
|
|
|
|
|
|
|
vertical_justification,
|
|
|
|
|
|
|
|
VerticalTextJustification::Middle | VerticalTextJustification::Top
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if use_second
|
|
|
|
|
|
|
|
&& (second_alignment_point.x != 0.0
|
|
|
|
|
|
|
|
|| second_alignment_point.y != 0.0
|
|
|
|
|
|
|
|
|| second_alignment_point.z != 0.0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
second_alignment_point.clone()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
location.clone()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn compute_left_bottom(
|
|
|
|
|
|
|
|
anchor: &Point,
|
|
|
|
|
|
|
|
h_alignment: &HAlignment,
|
|
|
|
|
|
|
|
v_alignment: &VAlignment,
|
|
|
|
|
|
|
|
text_width: f64,
|
|
|
|
|
|
|
|
text_height: f64,
|
|
|
|
|
|
|
|
) -> (f64, f64) {
|
|
|
|
|
|
|
|
let anchor_x = anchor.x;
|
|
|
|
|
|
|
|
let anchor_y = anchor.y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let left_x = match h_alignment {
|
|
|
|
|
|
|
|
HAlignment::Left => anchor_x,
|
|
|
|
|
|
|
|
HAlignment::Center => anchor_x - text_width / 2.0,
|
|
|
|
|
|
|
|
HAlignment::Right => anchor_x - text_width,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let bottom_y = match v_alignment {
|
|
|
|
|
|
|
|
VAlignment::Bottom => anchor_y,
|
|
|
|
|
|
|
|
VAlignment::Center => anchor_y - text_height / 2.0,
|
|
|
|
|
|
|
|
VAlignment::Top => anchor_y - text_height,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(left_x, -bottom_y)
|
|
|
|
|
|
|
|
}
|
|
|
|
|