Merge PR #2731: Layers panel: Reset to Initial Visibility

Conflicts:
- ATTRIBUTION.toml: ours (sha256 lines only); hashes recomputed at the end of the track
- crates/engine/Cargo.toml: main's workspace chrono entry, plus the PR's pdfcraft-testkit dev-dependency
This commit is contained in:
aiongg
2026-10-22 01:48:51 +00:00
33 changed files with 183 additions and 10 deletions
Generated
+1
View File
@@ -4134,6 +4134,7 @@ dependencies = [
"pdfcraft-redact",
"pdfcraft-render",
"pdfcraft-sign",
"pdfcraft-testkit",
"pdfcraft-xfa",
"pdfcraft-xfdf",
"png 0.18.1",
+1 -1
View File
@@ -2473,7 +2473,7 @@ fn info(d: &Document) -> Value {
pdfcraft_render::LinkTarget::Other(o) => json!({ "other": o }),
},
})).collect::<Vec<_>>(),
"layers": i.layers.iter().map(|l| json!({ "name": l.name, "visible": l.visible })).collect::<Vec<_>>(),
"layers": i.layers.iter().map(|l| json!({ "name": l.name, "visible": l.visible, "initial": l.initial })).collect::<Vec<_>>(),
// Full-screen presentation settings a page carries (ISO 32000-2 §12.4.4): only pages with
// a `/Trans` or `/Dur` appear; `style` is null for a display time alone.
"transitions": i.transitions.iter().map(|t| json!({
+4 -2
View File
@@ -5832,12 +5832,13 @@ fn doc_info_says_when_a_runaway_script_turned_the_forms_scripts_off() {
let _ = std::fs::remove_dir_all(dir);
}
/// doc_info describes a link's set-layer-visibility action by layer name.
/// doc_info describes a link's set-layer-visibility action by layer name, and each layer's
/// visibility now and as the file opens.
#[test]
fn doc_info_describes_set_layer_links() {
let dir = workdir("layer-links");
let objs = [
"<< /Type /Catalog /Pages 2 0 R /OCProperties << /OCGs [4 0 R 5 0 R] /D << >> >> >>",
"<< /Type /Catalog /Pages 2 0 R /OCProperties << /OCGs [4 0 R 5 0 R] /D << /OFF [5 0 R] >> >> >>",
"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",
"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Annots [6 0 R] >>",
"<< /Type /OCG /Name (Red) >>",
@@ -5868,6 +5869,7 @@ fn doc_info_describes_set_layer_links() {
"preserve_rb": false,
})
);
assert_eq!(info["layers"], json!([{ "name": "Red", "visible": true, "initial": true }, { "name": "Green", "visible": false, "initial": false }]));
}
mod close_argument_tests {
+3
View File
@@ -51,3 +51,6 @@ unicode-segmentation = "1.13"
# Already in the graph through lopdf; used only for the local UTC offset ("today"). The workspace
# entry is std-only; this target adds `clock` for `chrono::Local::now`.
chrono = { workspace = true, features = ["clock"] }
[dev-dependencies]
pdfcraft-testkit = { workspace = true }
+16
View File
@@ -4819,6 +4819,22 @@ impl Session {
true
}
/// Show each layer as the file opens (Acrobat's Layers ▸ Reset to Initial Visibility). Returns
/// `true` if any layer changed; callers must drop cached rasters and text for the document,
/// as for [`Self::set_layer_visible`].
pub fn reset_layers(&mut self, id: DocId) -> bool {
let Some(doc) = self.docs.iter_mut().find(|d| d.id == id) else { return false };
let mut changed = false;
for l in &mut doc.info.layers {
changed |= l.visible != l.initial;
l.visible = l.initial;
}
if changed {
use_layer_choices(doc);
}
changed
}
/// Hide or show every comment on the page (Acrobat's Comments ▸ Hide all comments). Form
/// fields and links still draw. Returns whether anything changed.
pub fn set_hide_comments(&mut self, id: DocId, hide: bool) -> bool {
+54 -1
View File
@@ -685,7 +685,7 @@ fn layer_choices_survive_edits() {
#[test]
fn set_layer_actions_toggle_in_order_and_keep_radio_groups() {
use pdfcraft_render::LayerOp::{Off, On, Toggle};
let layer = |n: u32, visible: bool| Layer { id: (n, 0), name: format!("L{n}"), visible };
let layer = |n: u32, visible: bool| Layer { id: (n, 0), name: format!("L{n}"), visible, initial: visible };
let run = |changes: &[(LayerOp, u32)], preserve_rb: bool| {
// L1 and L2 are a radio-button group; L3 is on its own.
let mut layers = vec![layer(1, true), layer(2, false), layer(3, true)];
@@ -761,6 +761,59 @@ fn set_layer_actions_change_what_renders() {
assert!(!s.set_layer_state(DocId(999), &[(LayerOp::On, (5, 0))], true));
}
#[test]
fn reset_layers_returns_to_the_files_visibility() {
// Red (left half, on) and Green (right half, off) are a radio-button group.
let content = "/OC /R BDC 1 0 0 rg 0 0 50 100 re f EMC /OC /G BDC 0 1 0 rg 50 0 50 100 re f EMC";
let pdf = pdfcraft_testkit::Pdf::new()
.obj("<< /Type /Catalog /Pages 2 0 R /OCProperties << /OCGs [5 0 R 6 0 R] /D << /OFF [6 0 R] /RBGroups [[5 0 R 6 0 R]] >> >> >>")
.obj("<< /Type /Pages /Kids [3 0 R] /Count 1 >>")
.obj("<< /Type /Page /Parent 2 0 R /MediaBox [0 0 100 100] /Contents 4 0 R /Resources << /Properties << /R 5 0 R /G 6 0 R >> >> >>")
.stream("", content)
.obj("<< /Type /OCG /Name (Red) >>")
.obj("<< /Type /OCG /Name (Green) >>")
.build();
// A page drawing on layer Blue, which that file has off.
let other = pdfcraft_testkit::Pdf::new()
.obj("<< /Type /Catalog /Pages 2 0 R /OCProperties << /OCGs [5 0 R] /D << /OFF [5 0 R] >> >> >>")
.obj("<< /Type /Pages /Kids [3 0 R] /Count 1 >>")
.obj("<< /Type /Page /Parent 2 0 R /MediaBox [0 0 100 100] /Contents 4 0 R /Resources << /Properties << /B 5 0 R >> >> >>")
.stream("", "/OC /B BDC 0 0 1 rg 0 0 10 10 re f EMC")
.obj("<< /Type /OCG /Name (Blue) >>")
.build();
let mut s = Session::new();
let id = s.open("layers.pdf", None, Arc::new(pdf), None).unwrap();
let shown = |s: &Session| s.get(id).unwrap().info.layers.iter().map(|l| (l.name.clone(), l.visible)).collect::<Vec<_>>();
let left = |s: &Session| {
let doc = s.get(id).unwrap();
let mut r = pdfcraft_render::PageRenderer::new(doc.bytes.clone(), doc.config.clone());
let p = r.render(pdfcraft_render::RenderRequest { page: 0, kind: pdfcraft_render::RequestKind::Pixels, scale: 1.0, ..Default::default() });
let i = (50 * p.width as usize + 25) * 4;
p.rgba[i..i + 3].to_vec()
};
assert!(s.set_layer_state(id, &[(LayerOp::On, (6, 0))], true));
let edit = Edit::InsertPagesFrom {
name: "b.pdf".into(),
bytes: Arc::new(other),
pages: None,
at: 1,
field_conflicts: pdfcraft_organize::FieldConflicts::Rename,
};
s.apply(id, edit).unwrap();
let blue = s.get(id).unwrap().info.layers.iter().position(|l| l.name == "Blue").unwrap();
assert!(s.set_layer_visible(id, blue, true));
assert_eq!(shown(&s), [("Red".into(), false), ("Green".into(), true), ("Blue".into(), true)]);
assert_eq!(left(&s), [255, 255, 255]);
// Every layer, the inserted one too, goes back to the file's default configuration.
assert!(s.reset_layers(id));
assert_eq!(shown(&s), [("Red".into(), true), ("Green".into(), false), ("Blue".into(), false)]);
assert_eq!(left(&s), [255, 0, 0]);
assert!(!s.reset_layers(id), "already as the file opens");
// What the eye sees is not an edit: Undo still undoes the insert.
assert_eq!(s.get(id).unwrap().can_undo(), Some("Insert pages from b.pdf"));
assert!(!s.reset_layers(DocId(999)));
}
#[test]
fn edits_to_unknown_documents_are_rejected() {
let (mut s, _) = session_with(1);
+21 -1
View File
@@ -425,6 +425,8 @@ pub struct Layer {
pub id: (u32, u16),
pub name: String,
pub visible: bool,
/// Shown as the file opens: the default configuration (`/OCProperties /D`).
pub initial: bool,
}
#[derive(Clone, Debug)]
@@ -1428,7 +1430,7 @@ impl<'a> Inspector<'a> {
_ => !base_off,
};
let Some(id) = id else { continue };
out.push(Layer { id, name: self.text(d, b"Name").unwrap_or_else(|| "Layer".into()), visible });
out.push(Layer { id, name: self.text(d, b"Name").unwrap_or_else(|| "Layer".into()), visible, initial: visible });
}
}
@@ -2358,6 +2360,24 @@ trailer << /Root 1 0 R /Info 4 0 R >>
assert_eq!(info.layer_groups, [vec![(5, 0), (6, 0)], vec![(6, 0), (7, 0)]]);
}
#[test]
fn initial_layer_visibility_is_the_default_configuration() {
// BaseState OFF: Red is listed ON; Green is listed both ON and OFF, and OFF wins; Blue
// isn't listed, so it takes the base state.
let pdf = b"%PDF-1.7
1 0 obj << /Type /Catalog /Pages 2 0 R /OCProperties << /OCGs [5 0 R 6 0 R 7 0 R] /D << /BaseState /OFF /ON [5 0 R 6 0 R] /OFF [6 0 R] >> >> >> endobj
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] >> endobj
5 0 obj << /Type /OCG /Name (Red) >> endobj
6 0 obj << /Type /OCG /Name (Green) >> endobj
7 0 obj << /Type /OCG /Name (Blue) >> endobj
trailer << /Root 1 0 R >>
%%EOF";
let info = inspect(Arc::new(pdf.to_vec()), None).expect("opens");
let layers: Vec<_> = info.layers.iter().map(|l| (l.name.as_str(), l.initial)).collect();
assert_eq!(layers, [("Red", true), ("Green", false), ("Blue", false)]);
}
const ORPHAN_FIELDS: &[u8] = b"%PDF-1.7
1 0 obj << /Type /Catalog /Pages 2 0 R /AcroForm 4 0 R >> endobj
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj
+2
View File
@@ -1362,6 +1362,8 @@
This document has no layers. هذا المستند لا يحتوي على طبقات.
This document has no attachments. هذا المستند لا يحتوي على مرفقات.
Hide layer إخفاء الطبقة
Layer options خيارات الطبقات
Reset to Initial Visibility إعادة تعيين إلى الرؤية الأولية
Show layer إظهار الطبقة
Set layer visibility ضبط ظهور الطبقة
on page {label} في الصفحة {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1304,6 +1304,8 @@
This document has no layers. Този документ няма слоеве.
This document has no attachments. Този документ няма прикачени файлове.
Hide layer Скрий слоя
Layer options Опции за слоеве
Reset to Initial Visibility Възстанови първоначалната видимост
Show layer Покажи слоя
Set layer visibility Задай видимост на слоя
on page {label} на страница {label}
Can't render this file because it contains an unexpected character in line 8 and column 16.
+2
View File
@@ -1431,6 +1431,8 @@ key Space Mezerník
This document has no layers. Tento dokument nemá žádné vrstvy.
This document has no attachments. Tento dokument nemá žádné přílohy.
Hide layer Skrýt vrstvu
Layer options Možnosti vrstev
Reset to Initial Visibility Obnovit počáteční viditelnost
Show layer Zobrazit vrstvu
Set layer visibility Nastavit viditelnost vrstvy
on page {label} na stránce {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1348,6 +1348,8 @@
This document has no layers. Dieses Dokument hat keine Ebenen.
This document has no attachments. Dieses Dokument hat keine Anhänge.
Hide layer Ebene ausblenden
Layer options Ebenenoptionen
Reset to Initial Visibility Ursprüngliche Sichtbarkeit wiederherstellen
Show layer Ebene einblenden
on page {label} auf Seite {label}
Save attachment… Anhang speichern…
Can't render this file because it contains an unexpected character in line 6 and column 51.
+2
View File
@@ -363,6 +363,8 @@
Distribute Κατανομή
Show layer Εμφάνιση επιπέδου
Hide layer Απόκρυψη επιπέδου
Layer options Επιλογές επιπέδων
Reset to Initial Visibility Επαναφορά αρχικής ορατότητας
Collate Συρραφή αντιγράφων
Fit to page Προσαρμογή στη σελίδα
Reverse pages Αντιστροφή σειράς σελίδων
1 # Greek (el) interface catalog. Columns: context <TAB> English source <TAB> Greek translation.
363
364
365
366
367
368
369
370
+2
View File
@@ -1357,6 +1357,8 @@
This document has no layers. Este documento no tiene capas.
This document has no attachments. Este documento no tiene archivos adjuntos.
Hide layer Ocultar capa
Layer options Opciones de capas
Reset to Initial Visibility Restablecer visibilidad inicial
Show layer Mostrar capa
Set layer visibility Definir visibilidad de capas
on page {label} en la página {label}
Can't render this file because it contains an unexpected character in line 6 and column 60.
+2
View File
@@ -1343,6 +1343,8 @@
This document has no layers. Ce document ne contient aucun calque.
This document has no attachments. Ce document ne contient aucune pièce jointe.
Hide layer Masquer le calque
Layer options Options des calques
Reset to Initial Visibility Rétablir la visibilité initiale
Show layer Afficher le calque
on page {label} à la page {label}
Save attachment… Enregistrer la pièce jointe…
Can't render this file because it contains an unexpected character in line 6 and column 39.
+2
View File
@@ -1333,6 +1333,8 @@
This document has no layers. Ebben a dokumentumban nincs réteg.
This document has no attachments. Ebben a dokumentumban nincs melléklet.
Hide layer Réteg elrejtése
Layer options Réteg beállításai
Reset to Initial Visibility Kezdeti láthatóság visszaállítása
Show layer Réteg megjelenítése
on page {label} {label}. oldal
Save attachment… Melléklet mentése…
Can't render this file because it contains an unexpected character in line 7 and column 44.
+2
View File
@@ -1358,6 +1358,8 @@
This document has no layers. Questo documento non ha livelli.
This document has no attachments. Questo documento non ha allegati.
Hide layer Nascondi livello
Layer options Opzioni livelli
Reset to Initial Visibility Ripristina visibilità iniziale
Show layer Mostra livello
Set layer visibility Imposta visibilità livello
on page {label} a pagina {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1363,6 +1363,8 @@
This document has no layers. この文書にレイヤーはありません。
This document has no attachments. この文書に添付ファイルはありません。
Hide layer レイヤーを非表示
Layer options レイヤーのオプション
Reset to Initial Visibility 初期表示状態にリセット
Show layer レイヤーを表示
Set layer visibility レイヤーの表示を設定
on page {label} ページ {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1305,6 +1305,8 @@
This document has no layers. Бұл құжатта қабаттар жоқ.
This document has no attachments. Бұл құжатта тіркемелер жоқ.
Hide layer Қабатты жасыру
Layer options Қабат параметрлері
Reset to Initial Visibility Бастапқы көрінуді қалпына келтіру
Show layer Қабатты көрсету
Set layer visibility Қабаттың көрінісін орнату
on page {label} {label} бетінде
Can't render this file because it contains an unexpected character in line 856 and column 9.
+2
View File
@@ -629,6 +629,8 @@
Height: Aukštis:
Hide field highlights Slėpti laukų paryškinimą
Hide layer Slėpti sluoksnį
Layer options Sluoksnių parinktys
Reset to Initial Visibility Atkurti pradinį matomumą
Hide menu bar Slėpti meniu juostą
Hide password Slėpti slaptažodį
Hide toolbars Slėpti įrankių juostas
Can't render this file because it contains an unexpected character in line 404 and column 9.
+2
View File
@@ -1348,6 +1348,8 @@
This document has no layers. Ten dokument nie zawiera warstw.
This document has no attachments. Ten dokument nie zawiera załączników.
Hide layer Ukryj warstwę
Layer options Opcje warstw
Reset to Initial Visibility Przywróć początkową widoczność
Show layer Pokaż warstwę
Set layer visibility Ustaw widoczność warstwy
on page {label} na stronie {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -1248,6 +1248,8 @@
This document has no layers. Este documento não tem camadas.
This document has no attachments. Este documento não tem anexos.
Hide layer Ocultar camada
Layer options Opções de camadas
Reset to Initial Visibility Redefinir visibilidade inicial
Show layer Mostrar camada
on page {label} na página {label}
Save attachment… Salvar anexo…
Can't render this file because it contains an unexpected character in line 9 and column 16.
+2
View File
@@ -1363,6 +1363,8 @@
This document has no layers. В этом документе нет слоёв.
This document has no attachments. В этом документе нет вложений.
Hide layer Скрыть слой
Layer options Параметры слоёв
Reset to Initial Visibility Восстановить исходную видимость
Show layer Показать слой
Set layer visibility Задать видимость слоя
on page {label} на стр. {label}
Can't render this file because it contains an unexpected character in line 9 and column 16.
+2
View File
@@ -902,6 +902,8 @@
Hide all comments Skrij vse komentarje
Hide field highlights Skrij osvetlitev polj
Hide layer Skrij plast
Layer options Možnosti plasti
Reset to Initial Visibility Ponastavi na začetno vidnost
Hide menu bar Skrij menijsko vrstico
Hide password Skrij geslo
Hide toolbars Skrij orodne vrstice
Can't render this file because it contains an unexpected character in line 9 and column 16.
+2
View File
@@ -1333,6 +1333,8 @@ signature pad Type టైప్ చేయి
This document has no layers. ఈ పత్రంలో లేయర్‌లు లేవు.
This document has no attachments. ఈ పత్రంలో జోడింపులు లేవు.
Hide layer లేయర్‌ను దాచు
Layer options లేయర్ ఎంపికలు
Reset to Initial Visibility ప్రారంభ దృశ్యతకు రీసెట్ చేయి
Show layer లేయర్‌ను చూపించు
on page {label} పేజీ {label}లో
Save attachment… జోడింపును సేవ్ చేయి…
Can't render this file because it contains an unexpected character in line 13 and column 16.
+2
View File
@@ -1320,6 +1320,8 @@
This document has no layers. Bu belgede katman yok.
This document has no attachments. Bu belgede ek yok.
Hide layer Katmanı gizle
Layer options Katman seçenekleri
Reset to Initial Visibility Başlangıç görünürlüğüne sıfırla
Show layer Katmanı göster
on page {label} sayfa {label} üzerinde
Save attachment… Eki kaydet…
Can't render this file because it contains an unexpected character in line 855 and column 9.
+2
View File
@@ -1360,6 +1360,8 @@
This document has no layers. Цей документ не має шарів.
This document has no attachments. Цей документ не має вкладень.
Hide layer Приховати шар
Layer options Параметри шарів
Reset to Initial Visibility Відновити початкову видимість
Show layer Показати шар
Set layer visibility Задати видимість шару
on page {label} на сторінці {label}
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -625,6 +625,8 @@ theme Appearance Giao diện
Height: Chiều cao:
Hide field highlights Ẩn tô sáng trường
Hide layer Ẩn lớp
Layer options Tùy chọn lớp
Reset to Initial Visibility Đặt lại khả năng hiển thị ban đầu
Hide menu bar Ẩn thanh trình đơn
Hide password Ẩn mật khẩu
Hide toolbars Ẩn thanh công cụ
Can't render this file because it contains an unexpected character in line 491 and column 12.
+2
View File
@@ -1311,6 +1311,8 @@
This document has no layers. 本文档没有图层。
This document has no attachments. 本文档没有附件。
Hide layer 隐藏图层
Layer options 图层选项
Reset to Initial Visibility 重置为初始可见性
Show layer 显示图层
Set layer visibility 设置图层可见性
on page {label} 第 {label} 页
Can't render this file because it contains an unexpected character in line 9 and column 16.
+2
View File
@@ -1255,6 +1255,8 @@
This document has no layers. 本文件沒有圖層。
This document has no attachments. 本文件沒有附件。
Hide layer 隱藏圖層
Layer options 圖層選項
Reset to Initial Visibility 重設為初始可見性
Show layer 顯示圖層
Set layer visibility 設定圖層可見性
on page {label} 第 {label} 頁
Can't render this file because it contains an unexpected character in line 9 and column 16.
+14
View File
@@ -653,6 +653,7 @@ pub fn right_panel(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
let mut nav: Option<Nav> = None;
let mut close = false;
let mut toggle_layer: Option<(usize, bool)> = None;
let mut reset_layers = false;
let mut attachment_action: Option<(usize, bool)> = None; // (index, open instead of save)
let mut bm_action: Option<BmAction> = None;
let mut bm_expand: Option<usize> = None;
@@ -745,6 +746,16 @@ pub fn right_panel(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
}
});
}
if panel == RightPanel::Layers && !info.layers.is_empty() {
let more = icons::button(ui, "ellipsis", 26.0, false, tl!("Layer options"));
egui::Popup::menu(&more).show(|ui| {
ui.set_min_width(200.0);
if ui.button(tl!("Reset to Initial Visibility")).clicked() {
reset_layers = true;
ui.close();
}
});
}
let new_tip = crate::commands::command_tip(ui.ctx(), tl!("New bookmark ({key})"), "bookmark.add");
if panel == RightPanel::Bookmarks && bm_editable && icons::button(ui, "bookmark-plus", 26.0, false, &new_tip).clicked() {
bm_action = Some(BmAction::New);
@@ -968,6 +979,9 @@ pub fn right_panel(app: &mut PdfCraftApp, ui: &mut egui::Ui) {
{
app.views[index].invalidate_content();
}
if reset_layers && app.session.reset_layers(id) {
app.views[index].invalidate_content();
}
match nav {
Some(Nav::Page(p)) => app.views[index].go_to_page(p),
Some(Nav::Dest(p, dest)) => match app.session.get(id) {
@@ -104,3 +104,23 @@ fn push_buttons_set_layer_visibility() {
let s = h.state();
assert!(!s.session.get(s.views[0].id).unwrap().dirty, "showing and hiding layers doesn't change the document");
}
#[test]
fn layer_options_reset_to_initial_visibility() {
// Red off and Green on: the opposite of how the file opens.
let mut h = harness(|app| {
app.set_option("layer", "Red=off").unwrap();
app.set_option("layer", "Green=on").unwrap();
app.set_option("panel", "layers").unwrap();
});
assert_eq!(shown(&h), layers(false, true));
h.get_by_label("Layer options").click();
h.run_steps(2);
h.get_by_label("Reset to Initial Visibility").click();
h.run_steps(3);
assert_eq!(shown(&h), layers(true, false));
let s = h.state();
let doc = s.session.get(s.views[0].id).unwrap();
assert!(!doc.dirty, "showing and hiding layers doesn't change the document");
assert_eq!(doc.can_undo(), None, "nor is it an edit to undo");
}
+1 -1
View File
@@ -52,7 +52,7 @@ are borrowed; PDF 2.0 additions and most subset standards are missing. **150–2
| §14.12 | Document parts (DPart) | yes | none | `core.pdf20-dpart` planned |
| §14.13 | Associated files (`/AF`) | yes | none | `core.pdf20-associated-files` planned |
| — | Structural validation (Arlington PDF model) | yes (Preflight syntax checks) | none | `core.arlington-validation` planned |
| — | Optional content (layers) | full | **own** toggle and default state; set-OCG-state actions; no layer editing | `view.layers-panel` |
| — | Optional content (layers) | full | **own** toggle and default state, reset to the default state; set-OCG-state actions; no layer editing | `view.layers-panel`, `view.layers-reset` |
| — | Redaction (`/Redact` annotations, applying) | full | **own**: removes glyphs, image pixels, vectors, XObject content, annotations, fields and tags; verifies no residue | `protect.redact-*`, `protect.redaction-verification` |
## Annotations (§12.5.6)
+4 -4
View File
@@ -1331,11 +1331,11 @@ title = "Reset layers to initial visibility; list for all or current pages"
area = "B"
tier = "P2"
milestone = "M12"
status = "planned"
status = "partial"
commands = []
tools = []
evidence = []
notes = ""
tools = ["doc_info"]
evidence = ["crates/engine/src/tests.rs::reset_layers_returns_to_the_files_visibility", "crates/render/src/inspect.rs::initial_layer_visibility_is_the_default_configuration"]
notes = "Layers panel ▸ Layer options ▸ Reset to Initial Visibility shows each layer as the default configuration (/OCProperties /D) has it; doc_info reports it as `initial`. Not yet: listing the layers of all pages or the current page only."
[[feature]]
id = "view.destinations-panel"