Render MText column masks independently
This commit is contained in:
parent
af4401ce67
commit
8b6724700e
1 changed files with 107 additions and 22 deletions
|
|
@ -78,6 +78,80 @@ fn oriented_text_corners(
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn oriented_mtext_corner_groups(
|
||||||
|
verts: &[crate::scene::pipeline::text_gpu::TextVertex],
|
||||||
|
text: &acadrust::MText,
|
||||||
|
rotation: f64,
|
||||||
|
pad: f64,
|
||||||
|
annotation_scale: f64,
|
||||||
|
) -> Vec<[[f64; 2]; 4]> {
|
||||||
|
let columns = &text.column_data;
|
||||||
|
let count = columns.column_count.max(0) as usize;
|
||||||
|
if columns.column_type == 0 || count <= 1 || columns.width <= 0.0 {
|
||||||
|
return vec![oriented_text_corners(
|
||||||
|
verts,
|
||||||
|
[text.insertion_point.x, text.insertion_point.y],
|
||||||
|
rotation,
|
||||||
|
pad,
|
||||||
|
)];
|
||||||
|
}
|
||||||
|
|
||||||
|
let width = columns.width * annotation_scale;
|
||||||
|
let gutter = columns.gutter.max(0.0) * annotation_scale;
|
||||||
|
let total_width = width * count as f64 + gutter * count.saturating_sub(1) as f64;
|
||||||
|
let anchor = match text.attachment_point {
|
||||||
|
acadrust::entities::mtext::AttachmentPoint::TopCenter
|
||||||
|
| acadrust::entities::mtext::AttachmentPoint::MiddleCenter
|
||||||
|
| acadrust::entities::mtext::AttachmentPoint::BottomCenter => 0.5,
|
||||||
|
acadrust::entities::mtext::AttachmentPoint::TopRight
|
||||||
|
| acadrust::entities::mtext::AttachmentPoint::MiddleRight
|
||||||
|
| acadrust::entities::mtext::AttachmentPoint::BottomRight => 1.0,
|
||||||
|
_ => 0.0,
|
||||||
|
};
|
||||||
|
let block_left = -anchor * total_width;
|
||||||
|
let origin = [text.insertion_point.x, text.insertion_point.y];
|
||||||
|
let (sin_r, cos_r) = rotation.sin_cos();
|
||||||
|
let mut bounds = vec![[f64::MAX, f64::MAX, f64::MIN, f64::MIN]; count];
|
||||||
|
for vertex in verts {
|
||||||
|
let x = vertex.pos[0] as f64 + vertex.pos_low[0] as f64 - origin[0];
|
||||||
|
let y = vertex.pos[1] as f64 + vertex.pos_low[1] as f64 - origin[1];
|
||||||
|
let local_x = x * cos_r + y * sin_r;
|
||||||
|
let local_y = -x * sin_r + y * cos_r;
|
||||||
|
let stride = width + gutter;
|
||||||
|
let physical = ((local_x - block_left) / stride)
|
||||||
|
.floor()
|
||||||
|
.clamp(0.0, count.saturating_sub(1) as f64) as usize;
|
||||||
|
bounds[physical][0] = bounds[physical][0].min(local_x);
|
||||||
|
bounds[physical][1] = bounds[physical][1].min(local_y);
|
||||||
|
bounds[physical][2] = bounds[physical][2].max(local_x);
|
||||||
|
bounds[physical][3] = bounds[physical][3].max(local_y);
|
||||||
|
}
|
||||||
|
let to_world = |x: f64, y: f64| {
|
||||||
|
[
|
||||||
|
origin[0] + x * cos_r - y * sin_r,
|
||||||
|
origin[1] + x * sin_r + y * cos_r,
|
||||||
|
]
|
||||||
|
};
|
||||||
|
bounds
|
||||||
|
.into_iter()
|
||||||
|
.filter(|bounds| bounds[0] <= bounds[2] && bounds[1] <= bounds[3])
|
||||||
|
.map(|bounds| {
|
||||||
|
let [left, bottom, right, top] = [
|
||||||
|
bounds[0] - pad,
|
||||||
|
bounds[1] - pad,
|
||||||
|
bounds[2] + pad,
|
||||||
|
bounds[3] + pad,
|
||||||
|
];
|
||||||
|
[
|
||||||
|
to_world(left, bottom),
|
||||||
|
to_world(right, bottom),
|
||||||
|
to_world(right, top),
|
||||||
|
to_world(left, top),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn explicit_mtext_background(entity: &EntityType) -> Option<[f32; 4]> {
|
pub(crate) fn explicit_mtext_background(entity: &EntityType) -> Option<[f32; 4]> {
|
||||||
let EntityType::MText(text) = entity else {
|
let EntityType::MText(text) = entity else {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -849,11 +923,12 @@ pub fn tessellate(
|
||||||
.unwrap_or(m.rotation);
|
.unwrap_or(m.rotation);
|
||||||
let text_height = m.height * anno;
|
let text_height = m.height * anno;
|
||||||
let pad = (m.background_scale - 1.0).max(0.0) * text_height;
|
let pad = (m.background_scale - 1.0).max(0.0) * text_height;
|
||||||
let corners = oriented_text_corners(
|
let corner_groups = oriented_mtext_corner_groups(
|
||||||
&sdf_verts,
|
&sdf_verts,
|
||||||
[m.insertion_point.x, m.insertion_point.y],
|
m,
|
||||||
text_rotation,
|
text_rotation,
|
||||||
pad,
|
pad,
|
||||||
|
anno,
|
||||||
);
|
);
|
||||||
// Fill / mask — two triangles behind the glyphs.
|
// Fill / mask — two triangles behind the glyphs.
|
||||||
if has_fill {
|
if has_fill {
|
||||||
|
|
@ -862,13 +937,18 @@ pub fn tessellate(
|
||||||
} else {
|
} else {
|
||||||
color_or_inherit(&m.background_color, bg_color)
|
color_or_inherit(&m.background_color, bg_color)
|
||||||
};
|
};
|
||||||
let mut ft = Vec::with_capacity(6);
|
let mut ft = Vec::with_capacity(6 * corner_groups.len());
|
||||||
let mut ftl = Vec::with_capacity(6);
|
let mut ftl = Vec::with_capacity(6 * corner_groups.len());
|
||||||
for &k in &[0usize, 1, 2, 0, 2, 3] {
|
for corners in &corner_groups {
|
||||||
let (h, lo) =
|
for &k in &[0usize, 1, 2, 0, 2, 3] {
|
||||||
split_ds_xyz(corners[k][0], corners[k][1], elev_v);
|
let (h, lo) = split_ds_xyz(
|
||||||
ft.push(h);
|
corners[k][0],
|
||||||
ftl.push(lo);
|
corners[k][1],
|
||||||
|
elev_v,
|
||||||
|
);
|
||||||
|
ft.push(h);
|
||||||
|
ftl.push(lo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wires.push(WireModel {
|
wires.push(WireModel {
|
||||||
point_marker: None,
|
point_marker: None,
|
||||||
|
|
@ -907,19 +987,24 @@ pub fn tessellate(
|
||||||
// Text frame — a closed rectangle in the text
|
// Text frame — a closed rectangle in the text
|
||||||
// colour around the same box.
|
// colour around the same box.
|
||||||
if has_frame {
|
if has_frame {
|
||||||
let loop_xy = [
|
let mut fp = Vec::with_capacity(6 * corner_groups.len());
|
||||||
corners[0],
|
let mut fpl = Vec::with_capacity(6 * corner_groups.len());
|
||||||
corners[1],
|
for (group_index, corners) in corner_groups.iter().enumerate() {
|
||||||
corners[2],
|
if group_index > 0 {
|
||||||
corners[3],
|
fp.push([f32::NAN; 3]);
|
||||||
corners[0],
|
fpl.push([0.0; 3]);
|
||||||
];
|
}
|
||||||
let mut fp = Vec::with_capacity(5);
|
for &[x, y] in &[
|
||||||
let mut fpl = Vec::with_capacity(5);
|
corners[0],
|
||||||
for &[x, y] in &loop_xy {
|
corners[1],
|
||||||
let (h, lo) = split_ds_xyz(x, y, elev_v);
|
corners[2],
|
||||||
fp.push(h);
|
corners[3],
|
||||||
fpl.push(lo);
|
corners[0],
|
||||||
|
] {
|
||||||
|
let (h, lo) = split_ds_xyz(x, y, elev_v);
|
||||||
|
fp.push(h);
|
||||||
|
fpl.push(lo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wires.push(WireModel {
|
wires.push(WireModel {
|
||||||
point_marker: None,
|
point_marker: None,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue