diff --git a/locales/ar-SA/opencadstudio.ftl b/locales/ar-SA/opencadstudio.ftl index 8b7dd9902..7a4c6b081 100644 --- a/locales/ar-SA/opencadstudio.ftl +++ b/locales/ar-SA/opencadstudio.ftl @@ -3667,6 +3667,9 @@ insert = .frames-print = الإطارات والطباعة .frames-off = إيقاف الإطارات .frames-on = تشغيل الإطارات + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT أدخل اسم الكتلة:__ocs_arg_hint__ .insert-filling-attributes = INSERT يجري ملء السمات... diff --git a/locales/bg-BG/opencadstudio.ftl b/locales/bg-BG/opencadstudio.ftl index 3d88014b0..a8777696d 100644 --- a/locales/bg-BG/opencadstudio.ftl +++ b/locales/bg-BG/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = Рамки и печат .frames-off = Рамки изкл. .frames-on = Рамки вкл. + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Въведи име на блок:__ocs_arg_hint__ .insert-filling-attributes = INSERT Попълване на атрибути... diff --git a/locales/cs-CZ/opencadstudio.ftl b/locales/cs-CZ/opencadstudio.ftl index 67aaf37cf..e859bd0ad 100644 --- a/locales/cs-CZ/opencadstudio.ftl +++ b/locales/cs-CZ/opencadstudio.ftl @@ -3652,6 +3652,9 @@ insert = .frames-print = Rámy a tisk .frames-off = Rámy vypnuty .frames-on = Rámy zapnuty + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Název bloku Enter:__ocs_arg_hint__ .insert-filling-attributes = INSERT Vyplňování atributů... diff --git a/locales/de-DE/opencadstudio.ftl b/locales/de-DE/opencadstudio.ftl index f32c9ba95..1c1e2a699 100644 --- a/locales/de-DE/opencadstudio.ftl +++ b/locales/de-DE/opencadstudio.ftl @@ -3655,6 +3655,9 @@ insert = .frames-print = Rahmen und Drucken .frames-off = Rahmen aus .frames-on = Rahmen ein + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Blockname eingeben:__ocs_arg_hint__ .insert-filling-attributes = INSERT Attribute ausfüllen... diff --git a/locales/el-GR/opencadstudio.ftl b/locales/el-GR/opencadstudio.ftl index 1729d534a..090f5e925 100644 --- a/locales/el-GR/opencadstudio.ftl +++ b/locales/el-GR/opencadstudio.ftl @@ -3662,6 +3662,9 @@ insert = .frames-print = Πλαίσια και εκτύπωση .frames-off = Πλαίσια ανενεργά .frames-on = Πλαίσια ενεργά + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Δώστε όνομα μπλοκ:__ocs_arg_hint__ .insert-filling-attributes = INSERT Συμπλήρωση χαρακτηριστικών... diff --git a/locales/en-US/opencadstudio.ftl b/locales/en-US/opencadstudio.ftl index 05e319474..c53231dd3 100644 --- a/locales/en-US/opencadstudio.ftl +++ b/locales/en-US/opencadstudio.ftl @@ -3656,6 +3656,9 @@ insert = .frames-print = Frames & Print .frames-off = Frames Off .frames-on = Frames On + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter block name:__ocs_arg_hint__ .insert-filling-attributes = INSERT Filling attributes... diff --git a/locales/es-ES/opencadstudio.ftl b/locales/es-ES/opencadstudio.ftl index 92fd93eff..455bef6c5 100644 --- a/locales/es-ES/opencadstudio.ftl +++ b/locales/es-ES/opencadstudio.ftl @@ -3655,6 +3655,9 @@ insert = .frames-print = Marcos e impresión .frames-off = Marcos desactivados .frames-on = Marcos activados + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Introduzca el nombre del bloque:__ocs_arg_hint__ .insert-filling-attributes = INSERT Rellenando atributos... diff --git a/locales/fi-FI/opencadstudio.ftl b/locales/fi-FI/opencadstudio.ftl index 058b1a6a5..167a404e3 100644 --- a/locales/fi-FI/opencadstudio.ftl +++ b/locales/fi-FI/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = Kehykset ja painatus .frames-off = Kehykset pois päältä .frames-on = Kehykset päällä + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter -lohkon nimi:__ocs_arg_hint__ .insert-filling-attributes = INSERT Täytetään määritteitä... diff --git a/locales/fr-FR/opencadstudio.ftl b/locales/fr-FR/opencadstudio.ftl index 7607d15b3..f89c504bc 100644 --- a/locales/fr-FR/opencadstudio.ftl +++ b/locales/fr-FR/opencadstudio.ftl @@ -3655,6 +3655,9 @@ insert = .frames-print = Cadres & Imprimer .frames-off = Cadres désactivés .frames-on = Cadres en marche + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Saisissez le nom du bloc:__ocs_arg_hint__ .insert-filling-attributes = INSERT Attributs de remplissage... diff --git a/locales/hi-IN/opencadstudio.ftl b/locales/hi-IN/opencadstudio.ftl index 4929071d4..766f615dd 100644 --- a/locales/hi-IN/opencadstudio.ftl +++ b/locales/hi-IN/opencadstudio.ftl @@ -3643,6 +3643,9 @@ insert = .frames-print = फ्रेम्स एंड प्रिंट .frames-off = फ़्रेम बंद .frames-on = फ्रेम्स ऑन + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT ब्लॉक का नाम दर्ज करें:__ocs_arg_hint__ .insert-filling-attributes = INSERT गुण भरना ... diff --git a/locales/hu-HU/opencadstudio.ftl b/locales/hu-HU/opencadstudio.ftl index 08ce8b3d0..ff6b3f133 100644 --- a/locales/hu-HU/opencadstudio.ftl +++ b/locales/hu-HU/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = Keretek és nyomtatás .frames-off = Keretek ki .frames-on = Keretek bekapcsolva + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter blokknév: __ocs_arg_hint__ .insert-filling-attributes = INSERT Attribútumok kitöltése... diff --git a/locales/it-IT/opencadstudio.ftl b/locales/it-IT/opencadstudio.ftl index 1994c37d3..23b347ebe 100644 --- a/locales/it-IT/opencadstudio.ftl +++ b/locales/it-IT/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = Cornici e stampa .frames-off = Cornici disattivate .frames-on = Cornici attivate + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter nome del blocco:__ocs_arg_hint__ .insert-filling-attributes = INSERT Attributi di riempimento... diff --git a/locales/ja-JP/opencadstudio.ftl b/locales/ja-JP/opencadstudio.ftl index d9daa920a..fe7568e4e 100644 --- a/locales/ja-JP/opencadstudio.ftl +++ b/locales/ja-JP/opencadstudio.ftl @@ -3643,6 +3643,9 @@ insert = .frames-print = フレームと印刷 .frames-off = フレームをオフ .frames-on = フレームをオン + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT ブロック名を入力:__ocs_arg_hint__ .insert-filling-attributes = INSERT 属性を入力中... diff --git a/locales/ko-KR/opencadstudio.ftl b/locales/ko-KR/opencadstudio.ftl index 8a537142a..7e3a9eaf8 100644 --- a/locales/ko-KR/opencadstudio.ftl +++ b/locales/ko-KR/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = 프레임 및 인쇄 .frames-off = 프레임 끄기 .frames-on = 프레임 켜짐 + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter 블록 이름:__ocs_arg_hint__ .insert-filling-attributes = INSERT 채우기 속성... diff --git a/locales/nl-NL/opencadstudio.ftl b/locales/nl-NL/opencadstudio.ftl index 314a83d35..47d3f4ec9 100644 --- a/locales/nl-NL/opencadstudio.ftl +++ b/locales/nl-NL/opencadstudio.ftl @@ -3653,6 +3653,9 @@ insert = .frames-print = Frames & afdrukken .frames-off = Frames uitgeschakeld .frames-on = Frames aan + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Geef symboolnaam in:__ocs_arg_hint__ .insert-filling-attributes = INSERT Attributen vullen... diff --git a/locales/pl-PL/opencadstudio.ftl b/locales/pl-PL/opencadstudio.ftl index ef384bbc5..5efb47bec 100644 --- a/locales/pl-PL/opencadstudio.ftl +++ b/locales/pl-PL/opencadstudio.ftl @@ -3654,6 +3654,9 @@ insert = .frames-print = Ramki i druk .frames-off = Ramki wyłączone .frames-on = Ramki włączone + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Enter nazwa bloku: __ocs_arg_hint__ .insert-filling-attributes = INSERT Wypełnianie atrybutów... diff --git a/locales/pt-BR/opencadstudio.ftl b/locales/pt-BR/opencadstudio.ftl index cb5ea8a3e..1936fdc7c 100644 --- a/locales/pt-BR/opencadstudio.ftl +++ b/locales/pt-BR/opencadstudio.ftl @@ -3655,6 +3655,9 @@ insert = .frames-print = Molduras e impressão .frames-off = Molduras desativadas .frames-on = Molduras ativadas + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Insira o nome do bloco:__ocs_arg_hint__ .insert-filling-attributes = INSERT Preenchendo atributos... diff --git a/locales/ru-RU/opencadstudio.ftl b/locales/ru-RU/opencadstudio.ftl index 42a3d5334..f1df6f44e 100644 --- a/locales/ru-RU/opencadstudio.ftl +++ b/locales/ru-RU/opencadstudio.ftl @@ -3656,6 +3656,9 @@ insert = .frames-print = Frames & Print (недоступная ссылка) .frames-off = Снятие рам .frames-on = В кадрах + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Введите имя блока: __ocs_arg_hint__ .insert-filling-attributes = INSERT Наполнение атрибутов... diff --git a/locales/tr-TR/opencadstudio.ftl b/locales/tr-TR/opencadstudio.ftl index eb92c4bcb..27cd07e41 100644 --- a/locales/tr-TR/opencadstudio.ftl +++ b/locales/tr-TR/opencadstudio.ftl @@ -3625,6 +3625,9 @@ insert = .frames-print = Çerçeveler ve Yazdırma .frames-off = Çerçeveler Kapalı .frames-on = Çerçeveler Açık + .select-images = Görüntüleri seçin: + .transparency-mode-on = Saydamlık modunu girin [ON/OFF] : + .transparency-mode-off = Saydamlık modunu girin [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT Blok adını girin:__ocs_arg_hint__ .insert-filling-attributes = INSERT Öznitelikler dolduruluyor... diff --git a/locales/zh-CN/opencadstudio.ftl b/locales/zh-CN/opencadstudio.ftl index 828fc7429..cc91fac16 100644 --- a/locales/zh-CN/opencadstudio.ftl +++ b/locales/zh-CN/opencadstudio.ftl @@ -3640,6 +3640,9 @@ insert = .frames-print = 边框与打印 .frames-off = 边框关 .frames-on = 边框开 + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT 输入块名:__ocs_arg_hint__ .insert-filling-attributes = INSERT 正在填充属性... diff --git a/locales/zh-TW/opencadstudio.ftl b/locales/zh-TW/opencadstudio.ftl index bbf1928ca..30a164535 100644 --- a/locales/zh-TW/opencadstudio.ftl +++ b/locales/zh-TW/opencadstudio.ftl @@ -3652,6 +3652,9 @@ insert = .frames-print = 邊框與列印 .frames-off = 邊框關 .frames-on = 邊框開 + .select-images = Select image(s): + .transparency-mode-on = Enter transparency mode [ON/OFF] : + .transparency-mode-off = Enter transparency mode [ON/OFF] : .insert-prompt-hint = INSERT __ocs_arg_prompt____ocs_arg_hint__: .insert-enter-block-name-hint = INSERT 輸入圖塊名:__ocs_arg_hint__ .insert-filling-attributes = INSERT 正在填充屬性... diff --git a/src/app/commands/display.rs b/src/app/commands/display.rs index 7fddf031d..2f00501d6 100644 --- a/src/app/commands/display.rs +++ b/src/app/commands/display.rs @@ -929,6 +929,55 @@ impl OpenCADStudio { } } } + // TRANSPARENCY — raster images show transparent pixels (ON) or + // draw every pixel in its colour (OFF). + "TRANSPARENCY" => { + let c = crate::modules::insert::image_transparency::TransparencyCommand::new(); + self.command_line.push_info(&c.prompt()); + self.tabs[i].active_cmd = Some(Box::new(c)); + } + "TRANSPARENCY MODE" | "TRANSPARENCY ON" | "TRANSPARENCY OFF" => { + use codec::entities::ImageDisplayFlags; + let images: Vec<(codec::Handle, bool)> = self.tabs[i] + .scene + .selected_entities() + .iter() + .filter(|(handle, _)| !self.tabs[i].scene.is_layer_locked(*handle)) + .filter_map(|(handle, _)| match self.tabs[i].scene.document.get_entity(*handle) { + Some(codec::EntityType::RasterImage(image)) => { + Some((*handle, image.flags.contains(ImageDisplayFlags::TRANSPARENCY_ON))) + } + _ => None, + }) + .collect(); + let Some(&(_, first_on)) = images.first() else { + return Some(Task::none()); + }; + let handles: Vec = images.iter().map(|(handle, _)| *handle).collect(); + if cmd == "TRANSPARENCY MODE" { + let c = crate::modules::insert::image_transparency::TransparencyCommand::mode( + handles, first_on, + ); + self.command_line.push_info(&c.prompt()); + self.tabs[i].active_cmd = Some(Box::new(c)); + } else { + let on = cmd == "TRANSPARENCY ON"; + self.push_undo_snapshot(i, "TRANSPARENCY"); + for handle in &handles { + if let Some(codec::EntityType::RasterImage(image)) = + self.tabs[i].scene.document.get_entity_mut(*handle) + { + image.flags.set(ImageDisplayFlags::TRANSPARENCY_ON, on); + } + } + let changes: Vec<_> = handles + .iter() + .map(|handle| (*handle, crate::scene::ChangeKind::Modified)) + .collect(); + self.tabs[i].scene.bump_entities(&changes); + self.tabs[i].dirty = true; + } + } // UNDERLAY — edit properties of selected PDF/DWF/DGN underlay entities. // Usage: // UNDERLAY FADE <0-80> diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index eb9a7a4b1..4f819ae37 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -714,6 +714,7 @@ inventory::submit!(crate::command::CommandRegistration { "IM", "IMAGE", "IMAGEATTACH", + "TRANSPARENCY", "IMAGEEMBED", "IMPORTOBJ", "ISOLATEOBJECTS", diff --git a/src/io/pdf_export.rs b/src/io/pdf_export.rs index 7e9d44269..3f1810a68 100644 --- a/src/io/pdf_export.rs +++ b/src/io/pdf_export.rs @@ -242,8 +242,10 @@ fn emit_image( { return Err("Cannot plot bitmap: invalid coordinates, clip boundary, or opacity.".into()); } + // The low bit (free: the pixel buffer is aligned) keeps the opaque copy + // of a picture apart from its transparent one. let key = ( - std::sync::Arc::as_ptr(&image.pixels) as usize, + std::sync::Arc::as_ptr(&image.pixels) as usize | usize::from(!image.use_alpha), image.width, image.height, ); @@ -255,7 +257,14 @@ fn emit_image( doc.resources.xobjects.map.insert( id.clone(), printpdf::XObject::Image(printpdf::RawImage { - pixels: printpdf::RawImageData::U8(image.pixels.as_ref().clone()), + pixels: printpdf::RawImageData::U8(if image.use_alpha { + image.pixels.as_ref().clone() + } else { + // Transparency off: every pixel opaque in its colour. + let mut opaque = image.pixels.as_ref().clone(); + opaque.chunks_exact_mut(4).for_each(|px| px[3] = 255); + opaque + }), width: image.width as usize, height: image.height as usize, data_format: printpdf::RawImageFormat::RGBA8, diff --git a/src/locale_catalog.rs b/src/locale_catalog.rs index 92edc4613..0b3a4a473 100644 --- a/src/locale_catalog.rs +++ b/src/locale_catalog.rs @@ -1197,6 +1197,9 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static "Frames & Print" => Some(("insert", "frames-print")), "Frames Off" => Some(("insert", "frames-off")), "Frames On" => Some(("insert", "frames-on")), + "Select image(s):" => Some(("insert", "select-images")), + "Enter transparency mode [ON/OFF] :" => Some(("insert", "transparency-mode-on")), + "Enter transparency mode [ON/OFF] :" => Some(("insert", "transparency-mode-off")), "Frames On, Not Plotted" => Some(("draw", "frames-on-not-plotted")), "Freeze" => Some(("layers", "freeze")), "From DXF" => Some(("properties", "from-dxf")), diff --git a/src/modules/insert/image_transparency.rs b/src/modules/insert/image_transparency.rs new file mode 100644 index 000000000..cdf22a30c --- /dev/null +++ b/src/modules/insert/image_transparency.rs @@ -0,0 +1,93 @@ +// TRANSPARENCY — whether raster images show their transparent pixels as +// transparent or draw every pixel in its stored colour. +// +// Select image(s): +// Enter transparency mode [ON/OFF] : (the default is the first +// image's current mode) + +use codec::Handle; +use glam::DVec3; + +use crate::command::{CadCommand, CmdOption, CmdResult}; + +pub struct TransparencyCommand { + handles: Vec, + /// `None` while images are being selected; then the default mode. + default_on: Option, +} + +impl TransparencyCommand { + pub fn new() -> Self { + Self { handles: Vec::new(), default_on: None } + } + + /// The mode prompt for images already chosen. + pub fn mode(handles: Vec, default_on: bool) -> Self { + Self { handles, default_on: Some(default_on) } + } + + fn apply(&mut self, on: bool) -> CmdResult { + let command = if on { "TRANSPARENCY ON" } else { "TRANSPARENCY OFF" }; + CmdResult::Relaunch(command.to_string(), std::mem::take(&mut self.handles)) + } +} + +impl CadCommand for TransparencyCommand { + fn name(&self) -> &'static str { + "TRANSPARENCY" + } + + fn prompt(&self) -> String { + match self.default_on { + None => crate::t!("Select image(s):").into_owned(), + Some(true) => crate::t!("Enter transparency mode [ON/OFF] :").into_owned(), + Some(false) => crate::t!("Enter transparency mode [ON/OFF] :").into_owned(), + } + } + + fn options(&self) -> Vec { + match self.default_on { + None => Vec::new(), + Some(_) => vec![CmdOption::new("ON", "ON"), CmdOption::new("OFF", "OFF")], + } + } + + fn is_selection_gathering(&self) -> bool { + self.default_on.is_none() + } + + fn wants_text_input(&self) -> bool { + self.default_on.is_some() + } + + fn on_selection_complete(&mut self, handles: Vec) -> CmdResult { + self.handles = handles; + CmdResult::NeedPoint + } + + fn on_text_input(&mut self, text: &str) -> Option { + let default_on = self.default_on?; + Some(match text.trim().to_uppercase().as_str() { + "" => self.apply(default_on), + "ON" => self.apply(true), + "OFF" => self.apply(false), + _ => CmdResult::ReportError("Invalid option keyword.".to_string()), + }) + } + + fn on_point(&mut self, _pt: DVec3) -> CmdResult { + CmdResult::NeedPoint + } + + fn on_enter(&mut self) -> CmdResult { + match self.default_on { + None if self.handles.is_empty() => CmdResult::Cancel, + // The app keeps only the images and asks for the mode. + None => CmdResult::Relaunch( + "TRANSPARENCY MODE".to_string(), + std::mem::take(&mut self.handles), + ), + Some(on) => self.apply(on), + } + } +} diff --git a/src/modules/insert/mod.rs b/src/modules/insert/mod.rs index e157971ca..0e3393464 100644 --- a/src/modules/insert/mod.rs +++ b/src/modules/insert/mod.rs @@ -9,6 +9,7 @@ mod content_browser; pub(crate) mod create_block; mod design_center; mod edit_block; +pub(crate) mod image_transparency; pub(crate) mod insert_block; mod landxml; pub(crate) mod picker; diff --git a/src/scene/model/image_model.rs b/src/scene/model/image_model.rs index 5fbd58802..1e312100e 100644 --- a/src/scene/model/image_model.rs +++ b/src/scene/model/image_model.rs @@ -94,6 +94,9 @@ pub struct ImageModel { /// Magnified pixels stay square (raster images); otherwise they blend /// (PDF pages, OLE pictures). pub pixelated: bool, + /// Pixel alpha applies. A raster image whose transparency is off draws + /// every pixel opaque in its stored colour. + pub use_alpha: bool, } impl ImageModel { @@ -165,6 +168,9 @@ impl ImageModel { draw_depth: 0.0, verts, pixelated: true, + use_alpha: img + .flags + .contains(codec::entities::ImageDisplayFlags::TRANSPARENCY_ON), }) } } @@ -274,6 +280,7 @@ impl ImageModel { draw_depth: 0.0, verts, pixelated: false, + use_alpha: true, }) } } @@ -355,6 +362,7 @@ impl ImageModel { draw_depth: 0.0, verts, pixelated: false, + use_alpha: true, }) } } diff --git a/src/scene/pipeline/image_gpu.rs b/src/scene/pipeline/image_gpu.rs index 196c3f830..4a6ecd3f3 100644 --- a/src/scene/pipeline/image_gpu.rs +++ b/src/scene/pipeline/image_gpu.rs @@ -79,7 +79,9 @@ struct ImageParams { /// Signed draw-order depth (-1,1); applied as a clip-z bias in the shader /// so the raster orders against other entity types. 0.0 = neutral. draw_depth: f32, - _pad: [f32; 2], + /// 1.0 when pixel alpha applies, 0.0 when pixels draw opaque. + use_alpha: f32, + _pad: f32, } // 16 bytes // ── Per-image GPU handle ────────────────────────────────────────────────── @@ -196,7 +198,8 @@ impl ImageGpu { let params = ImageParams { opacity: model.opacity.clamp(0.0, 1.0), draw_depth: 0.0, - _pad: [0.0; 2], + use_alpha: if model.use_alpha { 1.0 } else { 0.0 }, + _pad: 0.0, }; let params_buf = Arc::new(super::gpu_upload::upload_buffer( device, diff --git a/src/shaders/image.wgsl b/src/shaders/image.wgsl index ca7860aa7..5bab2a647 100644 --- a/src/shaders/image.wgsl +++ b/src/shaders/image.wgsl @@ -28,7 +28,7 @@ struct Uniforms { struct ImageParams { opacity: f32, draw_depth: f32, // signed (-1,1) draw-order bias; 0 = neutral - _pad1: f32, + use_alpha: f32, // 1 = pixel alpha applies, 0 = pixels draw opaque _pad2: f32, }; @group(1) @binding(2) var img_params: ImageParams; @@ -63,5 +63,6 @@ fn vs_main(in: VertIn) -> VertOut { @fragment fn fs_main(in: VertOut) -> @location(0) vec4 { let col = textureSample(img_texture, img_sampler, in.uv); - return vec4(col.rgb, col.a * img_params.opacity); + let alpha = select(1.0, col.a, img_params.use_alpha > 0.5); + return vec4(col.rgb, alpha * img_params.opacity); }