forked from 1b-agent/opencadstudio-upstream
feat: embed images (OLE2FRAME), print pipeline fixes, plot prefs, community fonts
- IMAGEEMBED: pack raster images into OLE2FRAME entities so a .dwg is self-contained; 'Embed Image' entry in the XREF attach menu; control/MCP op embed_image for external tools; dxf_name for OLE2FRAME queries. - Scene: populate_images_from_document now rebuilds OLE2FRAME and PDF underlay models too (they used to vanish after any XREF op). - Printing: add PRINTER_ENUM_NETWORK pass when listing printers; GDI spooler fallback (hayro raster at 300 DPI + StretchDIBits) for hosts whose PDF handler registers no print verb; DEVMODE orientation with a 90-degree raster rotation fallback for v4 drivers; fix the fit-scale precedence bug that printed blank pages. - PDF export dialogs on Windows use the async file dialog so the native overwrite confirmation no longer deadlocks the UI thread. - Plot dialog: persist the chosen printer (saved on selection) and the picked plot window across sessions; page setups with no device no longer reset the output device. - Community fonts: detect unresolvable .shx references on open and offer a download from the repository's fonts/ folder (contribution guide in fonts/README.md); custom font source URL setting for intranet font servers; downloaded fonts resolve from the per-user fonts directory.
This commit is contained in:
1 parent
1450fdeedf
commit
28efbffd57
27 files changed
+1767
-66
No files matched your search
@@ -67,7 +67,54 @@ pub(super) const NAMES: &[&str] = &[
|
||||
"undo",
|
||||
"redo",
|
||||
];
|
||||
|
||||
/// Parse the `at` placement point for `embed_image`: `[x,y]` or `[x,y,z]`.
|
||||
fn embed_point(req: &Value) -> Result<acadrust::types::Vector3, Value> {
|
||||
let values = req["at"]
|
||||
.as_array()
|
||||
.filter(|v| (2..=3).contains(&v.len()))
|
||||
.ok_or_else(|| failure("invalid_point", "Expected at:[x,y] or [x,y,z]"))?;
|
||||
let mut p = [0.0_f64; 3];
|
||||
for (i, v) in values.iter().enumerate() {
|
||||
p[i] = v
|
||||
.as_f64()
|
||||
.filter(|v| v.is_finite())
|
||||
.ok_or_else(|| failure("invalid_point", "Expected finite coordinates"))?;
|
||||
}
|
||||
Ok(acadrust::types::Vector3::new(p[0], p[1], p[2]))
|
||||
}
|
||||
impl OpenCADStudio {
|
||||
/// `embed_image` — pack the picture at `path` into an OLE2FRAME placed
|
||||
/// with its lower-left corner at `at` (default width ≈ pixel_width/100,
|
||||
/// like the interactive command's Enter answer) and commit it as one
|
||||
/// undo step. The drawing stays self-contained: no external file to lose.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(super) fn control_embed_image(&mut self, req: &Value) -> Result<Task<Message>, Value> {
|
||||
let i = self.active_tab;
|
||||
let path = string(req, "path")?;
|
||||
let image = crate::io::ole_embed::EmbeddedImage::from_file(std::path::Path::new(&path))
|
||||
.map_err(|e| failure("embed_failed", e))?;
|
||||
let at = embed_point(req)?;
|
||||
let default_width = (image.pixel_width as f64 / 100.0).max(1.0);
|
||||
let width = req["width"].as_f64().filter(|w| *w > 0.0).unwrap_or(default_width);
|
||||
self.push_undo_snapshot(i, "IMAGEEMBED");
|
||||
let handle = crate::io::ole_embed::add_embedded_image(
|
||||
&mut self.tabs[i].scene.document,
|
||||
&image,
|
||||
at,
|
||||
width,
|
||||
)
|
||||
.map_err(|e| failure("embed_failed", e))?;
|
||||
self.post_ref_op(i);
|
||||
self.set_control_result(json!({
|
||||
"handle": format!("{:X}", handle.value()),
|
||||
"kind": "Ole2Frame",
|
||||
"path": path,
|
||||
"width": width,
|
||||
}));
|
||||
Ok(Task::none())
|
||||
}
|
||||
|
||||
pub(super) fn control_properties(&mut self) -> Value {
|
||||
self.refresh_properties();
|
||||
json!({"ok":true,"sections":self.tabs[self.active_tab].properties.sections.iter().map(|s|json!({"title":s.title,"properties":s.props.iter().map(|p|{
|
||||
|
||||
Reference in new issue
Block a user