forked from 1b-agent/opencadstudio-upstream
annotation: TEXT/MTEXT store the model height of their default scale
Annotative text in DWG/DXF holds the model height of its default (native) scale representation; other scales draw it at the ratio of the two. OCS read the stored value as paper height and multiplied it by the annotation scale again, so text from AutoCAD came out far too small (#1734), and annotative text OCS wrote came out too small in AutoCAD. - Rendering uses the active/native context ratio (1 when the object has no representation for the displayed scale). - TEXT with an annotative style asks for the paper height, stores the model height of the creation scale and gets that context; MTEXT starts from the model height; ANNOUPDATE converts a fixed style height the same way. - Properties: the Height row of annotative TEXT and MTEXT is the paper height at the displayed scale, with the model height beside it, and an edit converts back. MTEXT shows Annotative when it has contexts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b221ce5e33
commit
39c3e9af58
8 files changed
+183
-101
No files matched your search
@@ -1608,12 +1608,14 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
self.push_undo_snapshot(i, "ANNOUPDATE");
|
self.push_undo_snapshot(i, "ANNOUPDATE");
|
||||||
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
||||||
|
let paper_to_model = self.tabs[i].scene.creation_annotation_multiplier();
|
||||||
let mut updated = 0usize;
|
let mut updated = 0usize;
|
||||||
for handle in &handles {
|
for handle in &handles {
|
||||||
if crate::scene::annotative::update_entity_from_annotation_style(
|
if crate::scene::annotative::update_entity_from_annotation_style(
|
||||||
&mut self.tabs[i].scene.document,
|
&mut self.tabs[i].scene.document,
|
||||||
*handle,
|
*handle,
|
||||||
scale,
|
scale,
|
||||||
|
paper_to_model,
|
||||||
) {
|
) {
|
||||||
updated += 1;
|
updated += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2697,6 +2697,16 @@ impl OpenCADStudio {
|
|||||||
.header
|
.header
|
||||||
.current_text_style_name
|
.current_text_style_name
|
||||||
.clone();
|
.clone();
|
||||||
|
// An annotative style's default height is on paper; the editor
|
||||||
|
// and the entity work in the model height of this scale.
|
||||||
|
let height = if crate::scene::annotative::text_style_is_annotative(
|
||||||
|
&self.tabs[i].scene.document,
|
||||||
|
&style,
|
||||||
|
) {
|
||||||
|
height * self.tabs[i].scene.creation_annotation_multiplier()
|
||||||
|
} else {
|
||||||
|
height
|
||||||
|
};
|
||||||
let new_cmd = MTextCommand::with_defaults(height, style);
|
let new_cmd = MTextCommand::with_defaults(height, style);
|
||||||
self.command_line.push_info(&new_cmd.prompt());
|
self.command_line.push_info(&new_cmd.prompt());
|
||||||
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
|
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
|
||||||
|
|||||||
@@ -1721,7 +1721,7 @@ impl super::OpenCADStudio {
|
|||||||
annotative,
|
annotative,
|
||||||
);
|
);
|
||||||
if annotative {
|
if annotative {
|
||||||
if let Some(scale) = self.tabs[i].scene.current_annotation_scale_handle() {
|
if let Some(scale) = self.tabs[i].scene.creation_annotation_scale_handle() {
|
||||||
crate::scene::annotative::create_annotation_context(
|
crate::scene::annotative::create_annotation_context(
|
||||||
&mut self.tabs[i].scene.document,
|
&mut self.tabs[i].scene.document,
|
||||||
h,
|
h,
|
||||||
@@ -1755,7 +1755,7 @@ impl super::OpenCADStudio {
|
|||||||
self.push_undo_snapshot(i, "MTEXT");
|
self.push_undo_snapshot(i, "MTEXT");
|
||||||
let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt)));
|
let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt)));
|
||||||
if annotative {
|
if annotative {
|
||||||
let scale = self.tabs[i].scene.current_annotation_scale_handle();
|
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
||||||
if let (Some(handle), Some(scale)) = (handle, scale) {
|
if let (Some(handle), Some(scale)) = (handle, scale) {
|
||||||
crate::scene::annotative::create_annotation_context(
|
crate::scene::annotative::create_annotation_context(
|
||||||
&mut self.tabs[i].scene.document,
|
&mut self.tabs[i].scene.document,
|
||||||
@@ -1837,7 +1837,7 @@ impl super::OpenCADStudio {
|
|||||||
annotative,
|
annotative,
|
||||||
);
|
);
|
||||||
if annotative {
|
if annotative {
|
||||||
if let Some(scale) = self.tabs[i].scene.current_annotation_scale_handle() {
|
if let Some(scale) = self.tabs[i].scene.creation_annotation_scale_handle() {
|
||||||
crate::scene::annotative::create_annotation_context(
|
crate::scene::annotative::create_annotation_context(
|
||||||
&mut self.tabs[i].scene.document,
|
&mut self.tabs[i].scene.document,
|
||||||
h,
|
h,
|
||||||
@@ -1872,7 +1872,7 @@ impl super::OpenCADStudio {
|
|||||||
let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt)));
|
let handle = self.commit_entity_handle(plane.place_entity(EntityType::MText(mt)));
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
if annotative {
|
if annotative {
|
||||||
let scale = self.tabs[i].scene.current_annotation_scale_handle();
|
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
||||||
if let (Some(handle), Some(scale)) = (handle, scale) {
|
if let (Some(handle), Some(scale)) = (handle, scale) {
|
||||||
crate::scene::annotative::create_annotation_context(
|
crate::scene::annotative::create_annotation_context(
|
||||||
&mut self.tabs[i].scene.document,
|
&mut self.tabs[i].scene.document,
|
||||||
|
|||||||
+46
-44
@@ -1538,7 +1538,7 @@ impl OpenCADStudio {
|
|||||||
codec::EntityType::MText(t) => set_row_value(
|
codec::EntityType::MText(t) => set_row_value(
|
||||||
&mut sections,
|
&mut sections,
|
||||||
"annotative",
|
"annotative",
|
||||||
yes_no_choice(t.is_annotative),
|
yes_no_choice(t.is_annotative || is_anno),
|
||||||
),
|
),
|
||||||
codec::EntityType::Dimension(codec::entities::Dimension::Arc(_)) => {
|
codec::EntityType::Dimension(codec::entities::Dimension::Arc(_)) => {
|
||||||
set_row(
|
set_row(
|
||||||
@@ -1600,54 +1600,56 @@ impl OpenCADStudio {
|
|||||||
// text derives its paper height from the two endpoints,
|
// text derives its paper height from the two endpoints,
|
||||||
// while annotative text exposes that paper height and a
|
// while annotative text exposes that paper height and a
|
||||||
// separate calculated model height.
|
// separate calculated model height.
|
||||||
if let codec::EntityType::Text(text) = entity {
|
if let Some(factor) =
|
||||||
let aligned = matches!(
|
self.tabs[i].scene.annotative_text_height_factor(entity.common().handle)
|
||||||
text.horizontal_alignment,
|
{
|
||||||
codec::entities::TextHorizontalAlignment::Aligned
|
// Annotative text stores the model height of its default scale;
|
||||||
);
|
// the Height row edits the paper height at the displayed scale.
|
||||||
let annotative = crate::scene::annotative::is_annotative(doc, entity);
|
let (stored, model_factor, aligned) = match entity {
|
||||||
let model_factor = if annotative {
|
codec::EntityType::Text(text) => {
|
||||||
annotation_scale_handle
|
let aligned = matches!(
|
||||||
.and_then(|handle| match doc.objects.get(&handle) {
|
text.horizontal_alignment,
|
||||||
Some(codec::objects::ObjectType::Scale(scale)) => Some(
|
codec::entities::TextHorizontalAlignment::Aligned
|
||||||
scale.inverse_factor()
|
);
|
||||||
/ self.tabs[i].scene.annotation_scale_unit_factor(),
|
let stored = if aligned {
|
||||||
),
|
crate::entities::text::text_run_placement_at_scale(text, doc, 1.0).height
|
||||||
_ => None,
|
as f64
|
||||||
})
|
} else {
|
||||||
.unwrap_or(self.tabs[i].scene.annotation_scale as f64)
|
text.height
|
||||||
} else {
|
};
|
||||||
1.0
|
(stored, factor, aligned)
|
||||||
};
|
}
|
||||||
let paper_height = if aligned {
|
codec::EntityType::MText(text) => (text.height, factor, false),
|
||||||
crate::entities::text::text_run_placement_at_scale(text, doc, model_factor as f32)
|
_ => unreachable!("annotative_text_height_factor is text-only"),
|
||||||
.height as f64
|
|
||||||
} else {
|
|
||||||
text.height
|
|
||||||
};
|
};
|
||||||
|
let ratio = crate::scene::annotative::text_context_ratio(
|
||||||
|
doc,
|
||||||
|
entity.common().handle,
|
||||||
|
annotation_scale_handle,
|
||||||
|
)
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
let paper_height = stored / model_factor;
|
||||||
for section in sections.iter_mut() {
|
for section in sections.iter_mut() {
|
||||||
if let Some(row) = section.props.iter_mut().find(|row| row.field == "height") {
|
if let Some(row) = section.props.iter_mut().find(|row| row.field == "height") {
|
||||||
if annotative {
|
let editable = !aligned
|
||||||
row.label = t!("Paper text height").into_owned();
|
&& !matches!(row.value, crate::scene::model::object::PropValue::ReadOnly(_));
|
||||||
}
|
*row = crate::entities::common::num_prop(
|
||||||
if aligned {
|
t!("Paper text height").as_ref(),
|
||||||
row.value = crate::scene::model::object::PropValue::ReadOnly(
|
"height",
|
||||||
crate::entities::common::format_length(paper_height),
|
paper_height,
|
||||||
);
|
editable,
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if annotative {
|
insert_row_after(
|
||||||
insert_row_after(
|
&mut sections,
|
||||||
&mut sections,
|
"height",
|
||||||
"height",
|
crate::entities::common::ro_prop(
|
||||||
crate::entities::common::ro_prop(
|
t!("Model text height").as_ref(),
|
||||||
t!("Model text height").as_ref(),
|
"model_text_height",
|
||||||
"model_text_height",
|
crate::entities::common::format_length(stored * ratio),
|
||||||
crate::entities::common::format_length(paper_height * model_factor),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !group_names.is_empty() {
|
if !group_names.is_empty() {
|
||||||
|
|||||||
+27
-12
@@ -276,22 +276,24 @@ impl super::OpenCADStudio {
|
|||||||
t.style = cur_style;
|
t.style = cur_style;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if command_creation {
|
// TEXT asks an annotative style for the paper height; the entity
|
||||||
let annotation_multiplier = if crate::scene::annotative::text_style_is_annotative(
|
// stores the model height of the scale it is created at.
|
||||||
|
let annotative = command_creation
|
||||||
|
&& crate::scene::annotative::text_style_is_annotative(
|
||||||
&self.tabs[i].scene.document,
|
&self.tabs[i].scene.document,
|
||||||
&t.style,
|
&t.style,
|
||||||
) {
|
);
|
||||||
self.tabs[i].scene.creation_annotation_multiplier()
|
let paper_height = t.height;
|
||||||
} else {
|
if annotative {
|
||||||
1.0
|
t.height *= self.tabs[i].scene.creation_annotation_multiplier();
|
||||||
};
|
}
|
||||||
|
if command_creation {
|
||||||
let display_height = crate::entities::text::text_run_placement_at_scale(
|
let display_height = crate::entities::text::text_run_placement_at_scale(
|
||||||
&t,
|
&t,
|
||||||
&self.tabs[i].scene.document,
|
&self.tabs[i].scene.document,
|
||||||
annotation_multiplier as f32,
|
1.0,
|
||||||
)
|
)
|
||||||
.height as f64
|
.height as f64;
|
||||||
* annotation_multiplier;
|
|
||||||
if let Some(command) = self.tabs[i].suspended_cmd.as_mut() {
|
if let Some(command) = self.tabs[i].suspended_cmd.as_mut() {
|
||||||
command.on_editor_display_height(display_height);
|
command.on_editor_display_height(display_height);
|
||||||
}
|
}
|
||||||
@@ -311,9 +313,22 @@ impl super::OpenCADStudio {
|
|||||||
codec::entities::TextHorizontalAlignment::Aligned
|
codec::entities::TextHorizontalAlignment::Aligned
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
self.tabs[i].scene.document.header.text_height = t.height;
|
self.tabs[i].scene.document.header.text_height = paper_height;
|
||||||
|
}
|
||||||
|
let handle = self.commit_entity_handle(plane.place_entity(EntityType::Text(t)));
|
||||||
|
if annotative {
|
||||||
|
let scale = self.tabs[i].scene.creation_annotation_scale_handle();
|
||||||
|
if let (Some(handle), Some(scale)) = (handle, scale) {
|
||||||
|
crate::scene::annotative::create_annotation_context(
|
||||||
|
&mut self.tabs[i].scene.document,
|
||||||
|
handle,
|
||||||
|
scale,
|
||||||
|
);
|
||||||
|
self.tabs[i]
|
||||||
|
.scene
|
||||||
|
.bump_entities(&[(handle, crate::scene::ChangeKind::Modified)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let _ = self.commit_entity_handle(plane.place_entity(EntityType::Text(t)));
|
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
}
|
}
|
||||||
self.refresh_properties();
|
self.refresh_properties();
|
||||||
|
|||||||
@@ -4179,6 +4179,29 @@ impl OpenCADStudio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Annotative text: the row holds the paper height.
|
||||||
|
"height"
|
||||||
|
if self.tabs[i]
|
||||||
|
.scene
|
||||||
|
.annotative_text_height_factor(handle)
|
||||||
|
.is_some() =>
|
||||||
|
{
|
||||||
|
let factor = self.tabs[i]
|
||||||
|
.scene
|
||||||
|
.annotative_text_height_factor(handle)
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
if let (Ok(paper), Some(entity)) = (
|
||||||
|
val.trim().parse::<f64>(),
|
||||||
|
self.tabs[i].scene.document.get_entity_mut(handle),
|
||||||
|
) {
|
||||||
|
crate::scene::view::dispatch::apply_geom_prop_in_working_plane(
|
||||||
|
entity,
|
||||||
|
"height",
|
||||||
|
&(paper * factor).to_string(),
|
||||||
|
plane,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
"hyperlink" => {
|
"hyperlink" => {
|
||||||
// Stored in the standard PE_URL XDATA
|
// Stored in the standard PE_URL XDATA
|
||||||
// record; an empty value clears it.
|
// record; an empty value clears it.
|
||||||
|
|||||||
+46
-41
@@ -722,18 +722,12 @@ pub fn effective_annotation_scale_for(
|
|||||||
if !context_annotative && (text_like || !style_annotative) {
|
if !context_annotative && (text_like || !style_annotative) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
// Annotative TEXT/MTEXT store their paper text height as the base value.
|
// Annotative TEXT/MTEXT store the model height of their default (native)
|
||||||
// `fallback` is the absolute paper-to-model multiplier for the active
|
// scale representation; another scale draws it at the ratio of the two.
|
||||||
// annotation scale and already includes the drawing's INSUNITS conversion.
|
// A scale the object has no representation for shows the stored one.
|
||||||
//
|
|
||||||
// Example for a metre drawing with 2 mm paper text:
|
|
||||||
// 1:1 -> 2 * 0.001 = 0.002 m
|
|
||||||
// 1:100 -> 2 * 0.100 = 0.200 m
|
|
||||||
//
|
|
||||||
// Using active/native here would only produce 1 / 100 and would lose the
|
|
||||||
// millimetre-to-metre conversion entirely.
|
|
||||||
if matches!(entity, EntityType::Text(_) | EntityType::MText(_)) {
|
if matches!(entity, EntityType::Text(_) | EntityType::MText(_)) {
|
||||||
return fallback;
|
return text_context_ratio(doc, entity.common().handle, scale_handle)
|
||||||
|
.map_or(1.0, |ratio| ratio as f32);
|
||||||
}
|
}
|
||||||
if matches!(
|
if matches!(
|
||||||
entity,
|
entity,
|
||||||
@@ -750,41 +744,39 @@ pub fn effective_annotation_scale_for(
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(coll_h) = annotation_scales_dict(doc, entity.common().handle) else {
|
text_context_ratio(doc, entity.common().handle, scale_handle)
|
||||||
return fallback;
|
.map_or(fallback, |ratio| ratio as f32)
|
||||||
};
|
}
|
||||||
let Some(coll) = as_dict(doc, coll_h) else {
|
|
||||||
return fallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
let active = active_object_context_for_scale(doc, entity.common().handle, scale_handle);
|
/// How much larger the representation at `scale_handle` (the displayed scale
|
||||||
|
/// when `None`) draws than the object's default representation: the ratio of
|
||||||
|
/// their model-per-paper factors. `None` when either is missing.
|
||||||
|
pub fn text_context_ratio(
|
||||||
|
doc: &CadDocument,
|
||||||
|
handle: Handle,
|
||||||
|
scale_handle: Option<Handle>,
|
||||||
|
) -> Option<f64> {
|
||||||
|
let coll = as_dict(doc, annotation_scales_dict(doc, handle)?)?;
|
||||||
|
let active = active_object_context_for_scale(doc, handle, scale_handle)?;
|
||||||
let native = coll
|
let native = coll
|
||||||
.entries
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(_, leaf_h)| match doc.objects.get(leaf_h) {
|
.find_map(|(_, leaf_h)| match doc.objects.get(leaf_h) {
|
||||||
Some(ObjectType::ObjectContextData(leaf)) if leaf.is_default => Some(leaf),
|
Some(ObjectType::ObjectContextData(leaf)) if leaf.is_default => Some(leaf),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
})?;
|
||||||
let (Some(active), Some(native)) = (active, native) else {
|
|
||||||
return fallback;
|
|
||||||
};
|
|
||||||
let (Some(ObjectType::Scale(active_scale)), Some(ObjectType::Scale(native_scale))) = (
|
let (Some(ObjectType::Scale(active_scale)), Some(ObjectType::Scale(native_scale))) = (
|
||||||
doc.objects.get(&active.scale),
|
doc.objects.get(&active.scale),
|
||||||
doc.objects.get(&native.scale),
|
doc.objects.get(&native.scale),
|
||||||
) else {
|
) else {
|
||||||
return fallback;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let native_factor = native_scale.inverse_factor();
|
let native_factor = native_scale.inverse_factor();
|
||||||
if native_factor.abs() <= 1.0e-12 {
|
if native_factor.abs() <= 1.0e-12 {
|
||||||
return fallback;
|
return None;
|
||||||
}
|
}
|
||||||
let relative = active_scale.inverse_factor() / native_factor;
|
let relative = active_scale.inverse_factor() / native_factor;
|
||||||
if relative.is_finite() && relative > 0.0 {
|
(relative.is_finite() && relative > 0.0).then_some(relative)
|
||||||
relative as f32
|
|
||||||
} else {
|
|
||||||
fallback
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_horizontal(value: i16) -> codec::entities::TextHorizontalAlignment {
|
fn text_horizontal(value: i16) -> codec::entities::TextHorizontalAlignment {
|
||||||
@@ -1864,6 +1856,7 @@ pub fn update_entity_from_annotation_style(
|
|||||||
doc: &mut CadDocument,
|
doc: &mut CadDocument,
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
current_scale: Option<Handle>,
|
current_scale: Option<Handle>,
|
||||||
|
paper_to_model: f64,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
enum StyleUpdate {
|
enum StyleUpdate {
|
||||||
Text { annotative: bool, height: f64 },
|
Text { annotative: bool, height: f64 },
|
||||||
@@ -1943,19 +1936,10 @@ pub fn update_entity_from_annotation_style(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut style_height = None;
|
||||||
let annotative = match update {
|
let annotative = match update {
|
||||||
StyleUpdate::Text { annotative, height } => {
|
StyleUpdate::Text { annotative, height } => {
|
||||||
if height > 0.0 {
|
style_height = (height > 0.0).then_some(height);
|
||||||
if let Some(entity) = doc.get_entity_mut(handle) {
|
|
||||||
match entity {
|
|
||||||
EntityType::Text(text) => text.height = height,
|
|
||||||
EntityType::MText(text) => text.height = height,
|
|
||||||
EntityType::AttributeEntity(attribute) => attribute.height = height,
|
|
||||||
EntityType::AttributeDefinition(attribute) => attribute.height = height,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
annotative
|
annotative
|
||||||
}
|
}
|
||||||
StyleUpdate::Dimension { annotative } => annotative,
|
StyleUpdate::Dimension { annotative } => annotative,
|
||||||
@@ -1972,6 +1956,27 @@ pub fn update_entity_from_annotation_style(
|
|||||||
create_annotation_context(doc, handle, scale);
|
create_annotation_context(doc, handle, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(mut height) = style_height {
|
||||||
|
// An annotative style's height is on paper; the entity stores the
|
||||||
|
// model height of its default representation.
|
||||||
|
let text = matches!(
|
||||||
|
doc.get_entity(handle),
|
||||||
|
Some(EntityType::Text(_) | EntityType::MText(_))
|
||||||
|
);
|
||||||
|
if annotative && text {
|
||||||
|
let ratio = text_context_ratio(doc, handle, current_scale).unwrap_or(1.0);
|
||||||
|
height *= paper_to_model / ratio;
|
||||||
|
}
|
||||||
|
if let Some(entity) = doc.get_entity_mut(handle) {
|
||||||
|
match entity {
|
||||||
|
EntityType::Text(text) => text.height = height,
|
||||||
|
EntityType::MText(text) => text.height = height,
|
||||||
|
EntityType::AttributeEntity(attribute) => attribute.height = height,
|
||||||
|
EntityType::AttributeDefinition(attribute) => attribute.height = height,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6176,6 +6176,31 @@ impl Scene {
|
|||||||
added
|
added
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For an annotative TEXT/MTEXT, its stored height per unit of paper text
|
||||||
|
/// height at the displayed scale (the stored height is the model height
|
||||||
|
/// of its default representation). `None` for anything else.
|
||||||
|
pub(crate) fn annotative_text_height_factor(&self, handle: Handle) -> Option<f64> {
|
||||||
|
let entity = self.document.get_entity(handle)?;
|
||||||
|
if !matches!(entity, EntityType::Text(_) | EntityType::MText(_))
|
||||||
|
|| !crate::scene::annotative::is_annotative(&self.document, entity)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let scale = self.displayed_annotation_scale_handle();
|
||||||
|
let model_per_paper = scale
|
||||||
|
.and_then(|scale| match self.document.objects.get(&scale) {
|
||||||
|
Some(ObjectType::Scale(scale)) => {
|
||||||
|
Some(scale.inverse_factor() / self.annotation_scale_unit_factor())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or(self.annotation_scale as f64);
|
||||||
|
let ratio =
|
||||||
|
crate::scene::annotative::text_context_ratio(&self.document, handle, scale)
|
||||||
|
.unwrap_or(1.0);
|
||||||
|
Some(model_per_paper / ratio)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn displayed_annotation_scale_handle(&self) -> Option<Handle> {
|
pub(crate) fn displayed_annotation_scale_handle(&self) -> Option<Handle> {
|
||||||
if self.current_layout == "Model" {
|
if self.current_layout == "Model" {
|
||||||
return self.scale_object_handle(&self.document.header.current_annotation_scale);
|
return self.scale_object_handle(&self.document.header.current_annotation_scale);
|
||||||
|
|||||||
Reference in new issue
Block a user