Merge main into merge/ui-print-optimize2

# Conflicts:
#	crates/automation/src/redact.rs
#	crates/automation/src/tools.rs
#	crates/print/src/lib.rs
#	crates/render/src/inspect.rs
#	crates/render/src/lib.rs
This commit is contained in:
bflatastic committed 2026-11-09 20:56:15 +07:00
commit 2ce2d3cf81
97 files changed
+8153 -480

No files matched your search

+19 -19
View File
@@ -1202,8 +1202,8 @@ milestone = "M3"
status = "shipped"
commands = []
tools = ["link_open"]
evidence = ["crates/ui-egui/tests/it/view.rs::clicking_a_link_goes_to_its_destination", "crates/ui-egui/tests/it/view.rs::link_destinations_scroll_to_their_position", "crates/ui-egui/tests/it/view.rs::a_link_without_a_position_keeps_the_place_on_the_next_page", "crates/ui-egui/src/canvas/tests.rs::a_null_xyz_coordinate_keeps_the_readers_place_on_the_new_page", "crates/render/src/inspect/tests.rs::bookmarks_and_links_keep_their_destination_view", "crates/render/src/inspect/tests.rs::links_read_bounded_local_remote_go_to_actions", "crates/automation/tests/it/automation.rs::local_gotor_link_open_applies_destinations_and_honors_root", "crates/ui-egui/tests/it/document_links.rs::a_local_gotor_link_opens_in_a_tab_and_applies_its_destination", "crates/ui-egui/tests/it/document_links.rs::an_absolute_gotor_waits_for_consent_and_keeps_its_destination_across_tabs", "crates/ui-egui/tests/it/document_links.rs::cancelling_an_absolute_gotor_by_button_escape_or_dismissal_changes_nothing", "crates/automation/tests/it/automation.rs::absolute_gotor_consent_does_not_bypass_validation_or_passwords", "crates/render/src/inspect/tests.rs::launch_actions_that_name_a_pdf_open_it_like_a_remote_link", "crates/automation/tests/it/automation.rs::a_launch_link_to_a_pdf_opens_it_like_a_remote_link"]
notes = "GoTo and URI links plus local-PDF GoToR links: source-relative or local absolute /F paths, /UF preferred in file-spec dictionaries, explicit numeric page/view destinations, and internal tabs. Absolute local GoToR targets require desktop Allow/Cancel confirmation or an explicit allow_absolute opt-in in link_open; relative links open normally. link_open honors --root. Named remote destinations open at default view with a warning; /NewWindow is a tab hint. A Launch action whose /F names a .pdf file (and has no /Win launch parameters) opens that PDF the same way, backslash separators read as / (#4168); URL/network file systems, GoToE, other Launch actions and other actions are not executed. Same-document destinations retain their supported /XYZ, /Fit, /FitH, /FitV and /FitR views; /FitB* is read as whole-page fit. A null /XYZ left or top keeps the reader's place, as ISO 32000-2 §12.3.2.2 says and Acrobat Reader was observed to do (synthetic fixture): the user-space point at the window's top-left stays there on the target page at the same zoom, along each axis the page overflows; CAD exports (WSCAD) write every cross-reference this way. Null /FitH top and /FitV left still go to the page edge."
evidence = ["crates/ui-egui/tests/it/view.rs::clicking_a_link_goes_to_its_destination", "crates/ui-egui/tests/it/view.rs::link_destinations_scroll_to_their_position", "crates/ui-egui/tests/it/view.rs::a_link_without_a_position_keeps_the_place_on_the_next_page", "crates/ui-egui/src/canvas/tests.rs::a_null_xyz_coordinate_keeps_the_readers_place_on_the_new_page", "crates/render/src/inspect/tests.rs::bookmarks_and_links_keep_their_destination_view", "crates/render/src/inspect/tests.rs::links_read_bounded_local_remote_go_to_actions", "crates/automation/tests/it/automation.rs::local_gotor_link_open_applies_destinations_and_honors_root", "crates/ui-egui/tests/it/document_links.rs::a_local_gotor_link_opens_in_a_tab_and_applies_its_destination", "crates/ui-egui/tests/it/document_links.rs::an_absolute_gotor_waits_for_consent_and_keeps_its_destination_across_tabs", "crates/ui-egui/tests/it/document_links.rs::cancelling_an_absolute_gotor_by_button_escape_or_dismissal_changes_nothing", "crates/automation/tests/it/automation.rs::absolute_gotor_consent_does_not_bypass_validation_or_passwords", "crates/render/src/inspect/tests.rs::launch_actions_that_name_a_pdf_open_it_like_a_remote_link", "crates/automation/tests/it/automation.rs::a_launch_link_to_a_pdf_opens_it_like_a_remote_link", "crates/render/src/inspect/tests.rs::relative_uri_actions_resolve_against_the_catalog_base", "crates/render/src/inspect/tests.rs::links_are_active_in_their_quad_points", "crates/automation/tests/it/automation.rs::links_resolve_relative_addresses_and_report_their_quad_points"]
notes = "A relative URI action resolves against the catalog's /URI /Base (ISO 32000-2 Table 211) when that base is an http(s) address, then goes through the usual check and confirmation; without a base, a relative address is still refused (resolving against the document's own location is not done). A link with valid /QuadPoints is active only inside them, otherwise over /Rect (Table 176); link_list reports resolved_url and active_areas. IsMap is not supported. GoTo and URI links plus local-PDF GoToR links: source-relative or local absolute /F paths, /UF preferred in file-spec dictionaries, explicit numeric page/view destinations, and internal tabs. Absolute local GoToR targets require desktop Allow/Cancel confirmation or an explicit allow_absolute opt-in in link_open; relative links open normally. link_open honors --root. Named remote destinations open at default view with a warning; /NewWindow is a tab hint. A Launch action whose /F names a .pdf file (and has no /Win launch parameters) opens that PDF the same way, backslash separators read as / (#4168); URL/network file systems, GoToE, other Launch actions and other actions are not executed. Same-document destinations retain their supported /XYZ, /Fit, /FitH, /FitV and /FitR views; /FitB* is read as whole-page fit. A null /XYZ left or top keeps the reader's place, as ISO 32000-2 §12.3.2.2 says and Acrobat Reader was observed to do (synthetic fixture): the user-space point at the window's top-left stays there on the target page at the same zoom, along each axis the page overflows; CAD exports (WSCAD) write every cross-reference this way. Null /FitH top and /FitV left still go to the page edge."
[[feature]]
id = "view.annotation-hover"
@@ -1346,8 +1346,8 @@ milestone = "M3"
status = "shipped"
commands = []
tools = ["doc_info", "layer_set"]
evidence = ["crates/render/src/raster/tests.rs::layer_override_hides_content", "crates/engine/src/tests.rs::layer_choices_survive_edits", "crates/automation/tests/it/automation.rs::layers_and_hidden_comments_change_what_page_render_draws"]
notes = "layer_set shows or hides a layer by name (every group with that name, as CAD exporters repeat names) or by position, and page_render draws with the document's layer visibility. Still missing: Reset to initial visibility (view.layers-reset), layer properties, and /OC on annotations (#2176)."
evidence = ["crates/render/src/raster/tests.rs::layer_override_hides_content", "crates/engine/src/tests.rs::layer_choices_survive_edits", "crates/automation/tests/it/automation.rs::layers_and_hidden_comments_change_what_page_render_draws", "crates/render/src/raster/tests.rs::the_view_auto_state_sets_a_groups_state_on_screen", "crates/render/src/raster/tests.rs::layer_toggles_and_print_renders_are_not_the_view_auto_state", "crates/render/src/raster/tests.rs::malformed_view_auto_state_is_ignored", "crates/render/src/inspect/tests.rs::the_layers_panel_presents_the_order_tree", "crates/ui-egui/tests/it/layer_actions.rs::the_layers_panel_shows_the_order_tree"]
notes = "layer_set shows or hides a layer by name (every group with that name, as CAD exporters repeat names) or by position, and page_render draws with the document's layer visibility. Still missing: Reset to initial visibility (view.layers-reset), layer properties, and /OC on annotations (#2176). The default configuration's auto state for the View event (/AS, ISO 32000-2 8.11.4.4) sets the groups it manages from their /Usage /View /ViewState as the document opens, on screen and in the panel, and toggles still override it; renders for printing and print previews don't apply it; printing takes the Print event's auto state instead (print.print-ready-pdf). Not yet: the /Zoom, /User and /Language categories. The panel presents the default configuration's /Order (ISO 32000-2 Table 99) as a tree: a nested array one level deeper, a leading text string as a label that can't be toggled. Groups /Order leaves out aren't listed but still draw in their state, and a document without /Order lists none, the default Table 99 gives; doc_info reports the rows as layer_order. Not yet: /ListMode /VisiblePages."
[[feature]]
id = "view.layers-reset"
@@ -1358,7 +1358,7 @@ milestone = "M12"
status = "partial"
commands = []
tools = ["doc_info"]
evidence = ["crates/engine/src/tests.rs::reset_layers_returns_to_the_files_visibility", "crates/render/src/inspect/tests.rs::initial_layer_visibility_is_the_default_configuration"]
evidence = ["crates/engine/src/tests.rs::reset_layers_returns_to_the_files_visibility", "crates/render/src/inspect/tests.rs::initial_layer_visibility_is_the_default_configuration", "crates/render/src/inspect/tests.rs::initial_layer_visibility_applies_the_view_auto_state"]
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]]
@@ -1418,8 +1418,8 @@ milestone = "M3"
status = "shipped"
commands = ["edit.find"]
tools = ["text_find"]
evidence = ["crates/ui-egui/tests/it/ui.rs::find_counts_matches_across_pages", "crates/ui-egui/tests/it/ui.rs::find_reports_no_matches", "crates/automation/tests/it/automation.rs::open_inspect_render_and_find", "crates/render/src/text/tests.rs::identity_v_columns_are_searchable_in_reading_order", "crates/render/src/text/tests.rs::toc_leaders_do_not_hide_word_gaps", "crates/render/src/text/tests.rs::short_tracked_ellipses_remain_searchable", "crates/render/tests/it/search.rs::find_skips_soft_hyphens_and_zero_width_characters", "crates/render/tests/it/search.rs::find_joins_a_word_divided_at_a_line_end_soft_hyphen", "crates/render/tests/it/search.rs::a_zero_width_space_is_a_word_boundary_for_whole_words", "crates/render/tests/it/search.rs::a_chinese_or_japanese_word_divided_by_a_line_end_is_found_on_both_lines", "crates/render/tests/it/search.rs::a_line_break_stays_a_space_beside_latin_or_hangul_and_between_side_by_side_text", "crates/render/tests/it/search.rs::a_word_divided_between_vertical_columns_is_found_in_both", "crates/render/tests/it/search.rs::each_unspaced_range_joins_and_spaced_scripts_do_not", "crates/render/tests/it/search.rs::a_soft_hyphen_and_a_chinese_or_japanese_line_end_combine", "crates/render/src/text/tests.rs::thai_marks_drawn_one_glyph_at_a_time_keep_their_place_and_words"]
notes = "Horizontal and WMode 1 vertical text are grouped independently, including a horizontal heading above right-to-left vertical columns. Dotted TOC leaders preserve word spaces for phrase search (#3086), while short tracked ellipses remain intact and searchable; sparse lines and condensed OCR gaps below the existing height-based threshold remain limitations. Combining marks (Mn/Me) of left-to-right scripts drawn right after their letter stay with it in content order, and Thai or Indic word gaps without a space glyph are found as spaces (#6517). Complex interleaved flows still use a geometric reading-order heuristic. Soft hyphens, zero width spaces and joiners, word joiners and U+FEFF inside a word are skipped, in the page and in the query; a skipped zero width space still ends a word for Whole words only. A line break reads as no word break when the line ends in a soft hyphen, or when it runs on between two Chinese or Japanese characters (East Asian Wide, Fullwidth or Halfwidth, not Hangul and not fullwidth Latin letters or digits), so a divided word is found, in horizontal lines and in vertical columns that continue to the left; the break stays a space beside Latin or Korean text and between text set side by side on one line or in staggered cells."
evidence = ["crates/ui-egui/tests/it/ui.rs::find_counts_matches_across_pages", "crates/ui-egui/tests/it/ui.rs::find_reports_no_matches", "crates/automation/tests/it/automation.rs::open_inspect_render_and_find", "crates/render/src/text/tests.rs::identity_v_columns_are_searchable_in_reading_order", "crates/render/src/text/tests.rs::toc_leaders_do_not_hide_word_gaps", "crates/render/src/text/tests.rs::short_tracked_ellipses_remain_searchable", "crates/render/tests/it/search.rs::find_skips_soft_hyphens_and_zero_width_characters", "crates/render/tests/it/search.rs::find_joins_a_word_divided_at_a_line_end_soft_hyphen", "crates/render/tests/it/search.rs::a_zero_width_space_is_a_word_boundary_for_whole_words", "crates/render/tests/it/search.rs::a_chinese_or_japanese_word_divided_by_a_line_end_is_found_on_both_lines", "crates/render/tests/it/search.rs::a_line_break_stays_a_space_beside_latin_or_hangul_and_between_side_by_side_text", "crates/render/tests/it/search.rs::a_word_divided_between_vertical_columns_is_found_in_both", "crates/render/tests/it/search.rs::each_unspaced_range_joins_and_spaced_scripts_do_not", "crates/render/tests/it/search.rs::a_soft_hyphen_and_a_chinese_or_japanese_line_end_combine", "crates/render/src/text/tests.rs::thai_marks_drawn_one_glyph_at_a_time_keep_their_place_and_words", "crates/render/tests/it/search.rs::a_ligature_matches_its_letters", "crates/render/tests/it/search.rs::a_word_divided_by_a_line_end_hyphen_matches_whole_and_as_written", "crates/automation/tests/it/find_text.rs::text_find_matches_ligatures_and_words_divided_at_a_line_end"]
notes = "Horizontal and WMode 1 vertical text are grouped independently, including a horizontal heading above right-to-left vertical columns. Dotted TOC leaders preserve word spaces for phrase search (#3086), while short tracked ellipses remain intact and searchable; sparse lines and condensed OCR gaps below the existing height-based threshold remain limitations. Combining marks (Mn/Me) of left-to-right scripts drawn right after their letter stay with it in content order, and Thai or Indic word gaps without a space glyph are found as spaces (#6517). Complex interleaved flows still use a geometric reading-order heuristic. Soft hyphens, zero width spaces and joiners, word joiners and U+FEFF inside a word are skipped, in the page and in the query; a skipped zero width space still ends a word for Whole words only. A line break reads as no word break when the line ends in a soft hyphen, or when it runs on between two Chinese or Japanese characters (East Asian Wide, Fullwidth or Halfwidth, not Hangul and not fullwidth Latin letters or digits), so a divided word is found, in horizontal lines and in vertical columns that continue to the left; the break stays a space beside Latin or Korean text and between text set side by side on one line or in staggered cells. A Latin ligature (U+FB00–FB06) matches its letters, and a word divided by a hyphen (U+002D or U+2010) between letters at a line end matches whole, highlighted on both lines, as well as with the hyphen. Missing: accent-insensitive matching (an unaccented query finding accented text; an open pull request adds it)."
[[feature]]
id = "view.find-next-previous"
@@ -4650,8 +4650,8 @@ milestone = "M6"
status = "shipped"
commands = ["form.fields"]
tools = ["form_fill"]
evidence = ["crates/ui-egui/tests/it/forms.rs::check_boxes_radios_and_choices", "crates/forms/src/tests.rs::check_boxes_and_radios_switch_states", "crates/ui-egui/tests/it/forms.rs::tab_and_space_fill_in_a_check_box_between_text_fields", "crates/ui-egui/tests/it/forms.rs::clicking_a_check_box_while_typing_keeps_the_text_and_focuses_the_box", "crates/ui-egui/tests/it/forms.rs::radio_buttons_take_tab_space_and_arrows", "crates/forms/src/tests.rs::a_round_xfa_check_button_draws_a_round_background_and_border", "crates/xfa/src/tests.rs::round_check_buttons_are_marked_for_a_round_appearance", "crates/engine/src/tests.rs::round_xfa_check_buttons_open_drawn_round", "crates/forms/src/tests.rs::radio_buttons_sharing_an_on_state_are_exclusive_unless_in_unison", "crates/ui-egui/tests/it/forms.rs::clicking_a_radio_button_that_shares_its_on_state", "crates/ui-egui/tests/it/forms.rs::a_read_only_radio_button_is_focused_but_not_selected", "crates/automation/tests/it/automation.rs::form_fill_picks_one_of_radio_buttons_sharing_an_on_state"]
notes = "NoToggleToOff honoured; widgets without appearances get our own, drawn round for an XFA check button with shape=\"round\" (its background and border a circle inside the widget, as another viewer draws them on a synthetic form). Tab and Shift+Tab stop on check boxes and on each radio button, Space toggles the focused one, and the arrows move within a radio group (#2223); a click focuses the box too. Radio buttons sharing an on state follow RadiosInUnison (ISO 32000-2 Table 229): with it they turn on together, without it only the clicked one does (its /AS; /V names the shared state), which survives a save; form_fill takes {\"widget\": n} for the same and form_fields lists on_widgets. Without NoToggleToOff a second click deselects the button. Not yet: telling such buttons apart in exported form data (FDF/XFDF carry /V only)"
evidence = ["crates/ui-egui/tests/it/forms.rs::check_boxes_radios_and_choices", "crates/forms/src/tests.rs::check_boxes_and_radios_switch_states", "crates/ui-egui/tests/it/forms.rs::tab_and_space_fill_in_a_check_box_between_text_fields", "crates/ui-egui/tests/it/forms.rs::clicking_a_check_box_while_typing_keeps_the_text_and_focuses_the_box", "crates/ui-egui/tests/it/forms.rs::radio_buttons_take_tab_space_and_arrows", "crates/forms/src/tests.rs::a_round_xfa_check_button_draws_a_round_background_and_border", "crates/xfa/src/tests.rs::round_check_buttons_are_marked_for_a_round_appearance", "crates/engine/src/tests.rs::round_xfa_check_buttons_open_drawn_round", "crates/forms/src/tests.rs::radio_buttons_sharing_an_on_state_are_exclusive_unless_in_unison", "crates/ui-egui/tests/it/forms.rs::clicking_a_radio_button_that_shares_its_on_state", "crates/ui-egui/tests/it/forms.rs::a_read_only_radio_button_is_focused_but_not_selected", "crates/automation/tests/it/automation.rs::form_fill_picks_one_of_radio_buttons_sharing_an_on_state", "crates/forms/src/tests.rs::check_box_kids_with_different_on_states_tick_one_at_a_time", "crates/ui-egui/tests/it/forms.rs::clicking_check_box_kids_with_different_on_states", "crates/automation/tests/it/automation.rs::form_fill_ticks_one_kid_of_a_check_box_by_its_on_state", "crates/xfdf/src/tests.rs::imported_values_tick_the_check_box_kid_they_name"]
notes = "NoToggleToOff honoured; widgets without appearances get our own, drawn round for an XFA check button with shape=\"round\" (its background and border a circle inside the widget, as another viewer draws them on a synthetic form). Tab and Shift+Tab stop on check boxes and on each radio button, Space toggles the focused one, and the arrows move within a radio group (#2223); a click focuses the box too. Radio buttons sharing an on state follow RadiosInUnison (ISO 32000-2 Table 229): with it they turn on together, without it only the clicked one does (its /AS; /V names the shared state), which survives a save; form_fill takes {\"widget\": n} for the same and form_fields lists on_widgets. Without NoToggleToOff a second click deselects the button. A check box whose kids have different on states (ISO 32000-2 §12.7.5.2.3, Table 230) ticks the kid clicked and clears the others, and a second click clears the field; kids sharing an on state tick together. Named values, a reset to /DV, script changes and imported form data tick the kid whose on state they name; form_fill takes the name and form_fields lists the options and the checked one. Not yet: telling such buttons apart in exported form data (FDF/XFDF carry /V only); two same-name field dictionaries (rather than kids) whose on states differ share only the first one's state"
[[feature]]
id = "form.fill-choice"
@@ -4661,9 +4661,9 @@ tier = "P0"
milestone = "M6"
status = "shipped"
commands = ["form.fields"]
tools = ["form_fill"]
evidence = ["crates/ui-egui/tests/it/forms.rs::check_boxes_radios_and_choices", "crates/forms/src/tests.rs::choices_accept_exports_or_display_text", "crates/ui-egui/tests/it/forms.rs::an_editable_combo_box_takes_a_typed_value", "crates/ui-egui/tests/it/forms.rs::a_combo_box_without_edit_takes_no_typing", "crates/automation/tests/it/automation.rs::form_fill_takes_free_text_only_in_an_editable_combo_box"]
notes = "combo and list boxes, multi-select lists; an editable combo box (Edit flag) has a text box over the field as well as its list, and takes typed text on the page and through form_fill; a combo box without Edit takes only its options. No type-ahead or spell check in the typed box"
tools = ["form_fill", "form_fields"]
evidence = ["crates/ui-egui/tests/it/forms.rs::check_boxes_radios_and_choices", "crates/forms/src/tests.rs::choices_accept_exports_or_display_text", "crates/ui-egui/tests/it/forms.rs::an_editable_combo_box_takes_a_typed_value", "crates/ui-egui/tests/it/forms.rs::a_combo_box_without_edit_takes_no_typing", "crates/automation/tests/it/automation.rs::form_fill_takes_free_text_only_in_an_editable_combo_box", "crates/forms/src/tests.rs::a_list_box_with_duplicate_export_values_selects_the_option_i_names", "crates/forms/src/tests.rs::an_unusable_i_falls_back_to_the_first_option_with_the_value", "crates/forms/src/tests.rs::picking_one_of_two_options_with_the_same_export_value_round_trips", "crates/ui-egui/tests/it/forms.rs::a_list_box_click_picks_one_of_two_options_with_the_same_export_value", "crates/automation/tests/it/list_selection.rs::form_fields_reports_which_of_two_options_with_one_export_value_is_selected", "crates/forms/src/tests.rs::a_single_select_list_given_several_values_shows_the_first", "crates/forms/src/tests.rs::picking_in_a_single_select_list_given_several_values_writes_one", "crates/ui-egui/tests/it/forms.rs::a_single_select_list_box_given_two_values_shows_and_takes_one", "crates/automation/tests/it/list_selection.rs::form_fields_reports_one_value_for_a_single_select_list_given_two", "crates/ui-egui/tests/it/forms.rs::a_drop_downs_list_opens_as_wide_as_the_field_without_its_internal_name", "crates/ui-egui/tests/it/forms.rs::the_arrow_keys_move_through_a_drop_downs_list_and_enter_chooses"]
notes = "combo and list boxes, multi-select lists; an editable combo box (Edit flag) has a text box over the field as well as its list, and takes typed text on the page and through form_fill; a combo box without Edit takes only its options. a list box whose options share an export value shows and picks the one /I names (ISO 32000-2 Table 234): /I is used when it is integers, ascending, in range and names the same export values as /V, otherwise /V decides and each value selects the first option exporting it; a click or arrow key picks the row by position and writes its export value to /V and its position to /I, and form_fields reports selected (1-based positions); a list box without MultiSelect given an array /V or /DV holds, shows and resets to the first value only (Table 233), leaving the file as it is until the field is filled, when /V becomes one string and /I its position. A combo box shows its arrow on screen and opens its list under the field, as wide as the box, in its text size and alignment, black on white with a highlight that follows the pointer; more than nine items get a scroll bar with step buttons, the wheel scrolls it, and the arrow keys, Page Up/Down, Home and End move through it, Enter choosing (in an editable combo box the keys are its text box's, and the list takes the pointer). The list is drawn in the interface font, not the field's (no serif interface font ships yet). No type-ahead or spell check in the typed box; a combo box whose options share an export value still shows the first of them"
[[feature]]
id = "form.push-buttons"
@@ -6000,11 +6000,11 @@ title = "Add a suffix to redacted file names"
area = "G"
tier = "P3"
milestone = "M8"
status = "planned"
commands = []
tools = []
evidence = []
notes = ""
status = "shipped"
commands = ["redact.apply", "file.save"]
tools = ["redact_apply"]
evidence = ["crates/ui-egui/tests/it/redact.rs::saving_after_applying_redactions_asks_where", "crates/automation/tests/it/automation.rs::applying_redactions_proposes_the_name_with_redacted", "crates/redact/src/tests.rs::redacted_copies_are_named_with_redacted_before_the_extension"]
notes = "After Apply redactions, Save asks where and proposes the name with _Redacted before the extension (contract.pdf gives contract_Redacted.pdf; a name already ending in _Redacted keeps one); the web build downloads under that name. redact_apply returns the same name in save_as, for doc_save's path; doc_save without a path still writes in place. The suffix is fixed: there is no preference to change it or to use a prefix."
[[feature]]
id = "protect.redact-ai-suggestions"
@@ -6223,8 +6223,8 @@ milestone = "M9"
status = "shipped"
commands = ["sign.digital"]
tools = ["sign_document"]
evidence = ["crates/sign/tests/it/pdf.rs::signing_an_existing_field_and_counter_signing", "crates/ui-egui/tests/it/signing.rs::clicking_an_empty_signature_field_signs_it"]
notes = ""
evidence = ["crates/sign/tests/it/pdf.rs::signing_an_existing_field_and_counter_signing", "crates/ui-egui/tests/it/signing.rs::clicking_an_empty_signature_field_signs_it", "crates/ui-egui/src/canvas/sign_tab_tests.rs::empty_signature_fields_show_a_sign_tab_that_signs_them", "crates/ui-egui/src/canvas/sign_tab_tests.rs::sign_tabs_skip_fields_that_a_click_cannot_sign"]
notes = "Clicking an empty signature field signs it (Use a certificate for that field). With the Select tool, each empty field a click would sign (filling allowed, the field not read-only, its widget shown) carries a small accent tab in its top-left corner, sized to the field (0.4 of its height on screen, from 10 to 18 pt): the signature icon and Sign from 14 pt up, the icon alone below that or when the label would take more than half the field's width, and no tab on a field too small for the 10 pt chip. The tab is screen-only chrome, never written into the file, exports or printing, and is hidden while preparing a form. Headless, the fields it marks are the ones sign_list reports unsigned and visible on a page, with their rect, that form_fields doesn't report read-only. Missing: the tab is painted only, with no accessibility node or keyboard focus of its own"
[[feature]]
id = "sign.invisible-signature"