Binds Properties dialog drafts to the vendored edit-session crate (byte-identical to PerchAnton/edit-session@033f7c3a, ledger in vendor/README) and adds replayable UI scenarios. Includes a merge of main and a test covering the clean Properties inspection-tab live refresh.
* M10 #5130: resolve Windows printer-default duplex before spooling
* M10 #5130: document printer duplex resolution
* M10 #5130: adopt DocumentDuplex driver fix from craft-print
* M10 #5130: adopt two-sided capability selection fix
* M10 #5130: update documented craft-print revision
* M10 #5130: fall back when Windows duplex defaults cannot be read
* fix(print): satisfy duplex review formatting and refresh shared pin
* Repin craft-print to craft-libs main (#411 and #133 merged); ask only the picked printer's driver for two-sided support
craft-libs b6b8a55b has #411 (DocumentDuplex) and #133 (two_sided(name)). The
Printer default support check now reads that one driver instead of listing
every printer's capabilities at submit time (#2192).
---------
Co-authored-by: robertobulltech <341520377+robertobulltech@users.noreply.github.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
* fix(print): M10 — Windows ya no cambia las letras de las fuentes TrueType incrustadas (#3132)
Un subconjunto TrueType incrustado numera sus glifos de nuevo (en el
subconjunto de Arial de ReportLab el espacio es el glifo 11; en la Arial
instalada, el 3). Al imprimir en Windows, Windows.Data.Pdf → Direct2D →
XPS conservaba esos números de glifo pero los dibujaba con la fuente
instalada del mismo nombre: «Revisión» salía como «Wj{nxn» y la «z» en
negrita como «Ä», tanto en las colas Brother como en la impresora Adobe PDF.
La copia que va a la cola de Windows renombra ahora cada programa
TrueType/OpenType incrustado como PdfCraftPrint<n>, en su tabla name
y en el PDF (/BaseFont, /FontName; el subconjunto conserva su etiqueta),
para que ninguna fuente instalada responda a ese nombre. Glifos,
codificaciones y /ToUnicode no cambian. CUPS y Guardar como PDF reciben
el PDF tal cual.
Tests: extremo a extremo con impose (la página se renderiza idéntica
antes y después, y el test falla sin el arreglo), fuentes que comparten
programa, Type 0, reescritura por plataforma de la tabla name y programas
dañados sin pánico. Falta comprobarlo en una impresora física con Windows.
Fixes#3132
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(print): M10 — solo se renombran en el PDF las fuentes cuyo programa se reescribe (#3132)
Si PdfCraft no puede leer o reescribir un programa incrustado (no es un
sfnt, está dañado o pasa de 64 MiB), ahora conserva también su /BaseFont
y su /FontName. Un visor que tampoco pueda cargarlo seguirá eligiendo el
sustituto por el nombre original («Arial») en vez de por PdfCraftPrint<n>.
Si no queda ningún programa reescrito, el PDF va a la cola tal cual.
Lo señaló CodeRabbit en el PR #4098. Test nuevo:
a_program_that_cannot_be_rewritten_keeps_its_name_in_the_pdf_too (falla
con el comportamiento anterior).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(print): M10 — el renombrado de fuentes para Windows decodifica contra un presupuesto total (#3132)
Cada programa ya tenía un tope de 64 MiB, pero un PDF con muchos
programas distintos podía sumar mucho trabajo de descompresión al
imprimir. Ahora todo el renombrado comparte un DecodeBudget de 512 MiB,
el mecanismo que main acaba de introducir en print. Agotado el
presupuesto, los programas que faltan conservan su nombre, igual que uno
ilegible.
Test nuevo: programs_past_the_shared_decode_budget_keep_their_names
(falla si se decodifica sin presupuesto).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(print): M10 — también se renombran los CIDFont escritos dentro de su fuente Type 0 (#3132)
Si /DescendantFonts lleva el CIDFont como diccionario en línea (en el
propio Type 0 o en un objeto array aparte), el recorrido no llegaba a
él. Cuando compartía programa con otra fuente, el programa se renombraba,
pero el Type 0, el CIDFont y su descriptor seguían diciendo «Arial», y
Windows podía volver a cruzarlos con la Arial instalada. Ahora el Type 0
se trata en el mismo recorrido, sin el segundo que hacía type0_names: un
CIDFont en línea apunta su programa, y al renombrar se cambian el Type 0,
el CIDFont y su descriptor en línea.
Lo señaló CodeRabbit en el PR #4098. Test nuevo:
a_cidfont_written_inside_its_type0_font_is_renamed_with_it (falla sin el
arreglo).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(print): M10 — renamed_table ya no copia cada cadena de la tabla name (#3132)
renamed_table copiaba el texto de cada registro antes de comprobar el
tamaño del resultado: una tabla name de menos de 1 MB con 65.535
registros apuntando a una misma cadena de 65.535 bytes reservaba unos
4 GiB, y un fallo de reserva cierra el proceso al imprimir en Windows.
Ahora la tabla se lee entera sin copiar ningún texto (cada registro
guarda el offset y la longitud de origen) y después cada cadena distinta
se guarda una sola vez: los registros que compartían cadena la siguen
compartiendo y el almacén nunca pasa de lo que alcanzan los offsets de
16 bits. Una tabla que declara más registros de los que caben antes de
sus cadenas se rechaza de entrada.
Lo encontró RomanLis91 en el PR #4098. Tests nuevos:
records_that_share_one_string_keep_sharing_it (falla con el código
anterior) y a_name_table_claiming_more_records_than_fit_before_its_strings_is_refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* M10: the Print dialog remembers two-sided, grayscale, collate, sizing and comments & forms (#2001)
Persist the choices that describe how this computer prints and restore
them on the next launch, under the names doc_print takes; copies, pages,
layout, orientation and the printer still start fresh for each job.
Those names now live in one place, pdfcraft_print::names, used by the
tool and the settings file. Settings are untrusted: an unknown name or a
custom scale outside the dialog's 1..=1000 % keeps the default.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* M10: the Print dialog also remembers a booklet's binding side (#2707)
Acrobat keeps the booklet binding (left or right) between prints;
PdfCraft started at Left every time. It is now kept with the other
remembered print choices, named as doc_print names it, and an unknown
saved value keeps the default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M10: Print starts each job's copies, pages, layout and orientation afresh (#2001)
CodeRabbit on #2103: the README promised that copies, pages, layout and orientation
start fresh, but open_print carried them over through `..keep` within a session.
ISO 32000-2 Table 147 initialises these per document when the print dialog opens
(NumCopies "typically 1", PrintPageRange), so each opening now resets them to the
defaults (Selected pages still win when thumbnails are picked); two-sided,
grayscale, collate, sizing, Comments & forms, binding, the paper and the printer
picked last carry over as before. Two-sided names now include "printer" (leave it to
the printer, main's default since #2422), so that choice is remembered too.
main's paper-persistence test expected grayscale not to persist; it is one of the
remembered preferences.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M10: a new print job also resets its layout's own options and leaves Label (#2001)
CodeRabbit on #2103: resetting the layout to Size kept pages per sheet, order, borders,
booklet subset and the poster options through `..keep`, so choosing Multiple again
brought back, say, a cut-and-stack order; and a job printed on Label went back to Size
without giving back the paper Label replaced. open_print now leaves Label through
set_handling (#3564) and resets the layout's own options with the rest of the job's
choices; the binding and sizing stay remembered. The README now says what resets on
each opening and what carries over.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M10: the Print dialog also remembers Print as image and its resolution (#6392)
A printer that needs pictures keeps getting them after a restart: as_image and
dpi are saved with the other print preferences and restored, a resolution the
dialog doesn't offer keeping the default 300 dpi. The bad-settings checks move
to their own test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyDBXygTf7jcqdsjcfn
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: mtlcl410 <chuanlin@niar.org.tw>
Keeps main's recovery renewal after applying redactions alongside the
combined notification, and reads XMP and rich-text streams with their
/DecodeParms given by reference made direct, as main's stream readers do.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyCHD1R3rywQBPCHXZA
- XFDF export: the finished appearance XML is checked against the import limit;
a page whose /Type is a reference stays out; stream data with a carriage
return goes out as hex (XML 1.0 §2.11 end-of-line handling); where /AS selects
one of several states, the selected stream is written.
- XFDF import: dash arrays of any length come back; consecutive <br/> keep the
blank line in /Contents; rich text written as text on a comment with no
/Contents comes back as /RC; namespace prefixes rich text inherits are declared
on it; appearances share one budget over the import (now tested through it).
- Redaction marks: the file's /AP and a /BE (none in ISO 32000-2 Table 195) are
dropped and the mark is drawn by PdfCraft; one with an area it cannot draw is
refused rather than placed invisible.
- FDF import: /P is not copied (the page is /Page, §12.7.8.3.4 Table 254); a
comment nested past 256 levels refuses the file instead of nulling part of its
appearance (a chain of 60 forms comes back whole).
- Engine: appearances an import left out go to the repair log for Import and
Paste comments.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyCHD1R3rywQBPCHXZA