* Share shape gallery choices and procedural previews
* Clip shape previews to their supplied rectangles
* Discard texture updates explicitly in headless rendering tests
* Honor fill colors across complete star and heart contours
* Make heart contour collection type explicit
* Use fixed-size triangle chunks in fill regression
---------
Co-authored-by: Fluorine <joseph.anglada92@gmail.com>
Co-authored-by: Joseph Anglada Muñiz <janglada@nd-soft.com>
* craft-window: frame policy v2: integrated title bar by default, desktop and backend detection
Add the policy module: Backend, Desktop::detect, TitleBarPref, Os, Frame
{Native, Inset, Integrated}, pure decide, decide_for and apply. Caption
layouts come from GNOME gsettings, kwinrc and GTK settings.ini parsers.
Choice::probe, the root Frame and decorate keep their behaviour.
* craft-window: review fixes for the frame policy
Desktop gains icon_theme, Decision gains desktop, Backend::from_env,
GNOME layout falls back to settings.ini, compositor socket variables mark
tiling, GTK_THEME wins over settings.ini, layout is read only for an
integrated frame, Layout::mirrored.
* craft-window: CRAFT_TITLEBAR applies when the app's own variable is unset
---------
Co-authored-by: aiongg <aiongtaigi@gmail.com>
* platform: GNOME's light setting reads as light, and Watcher::wait_first for the first frame
GNOME 42-46 writes color-scheme 'default' for Settings > Appearance > Light and the portal
reports 0. Both now decode as Light on GNOME (XDG_CURRENT_DESKTOP, read once at start);
0 stays no preference on other desktops.
Watcher::wait_first(timeout) blocks until the first answer, a known-absent portal with an
empty fallback, a no-preference answer, worker exit or drop, or the timeout.
* platform: GNOME's 'default' is light only on a GNOME desktop
---------
Co-authored-by: aiongg <aiongtaigi@gmail.com>
* ci: run craft-menu's fmt, clippy (Linux, macOS and wasm targets) and tests when menu, keymap or quit change
---------
Co-authored-by: aiongg <aiongtaigi@gmail.com>
In "Vado. ‘poi’ torno." the capital-letter check skipped poi, because ends_sentence didn't count ‘ among the characters that may open the next sentence. This is the last part of storytold/wordcraft#3675; the rest came with #484.
---------
Co-authored-by: VoiceLessQ <t12kaem@gmail.com>
* krilla: TrueType subsets keep the font's OS/2 table (embedding permissions)
The subsetter writes only the tables it subsets, so a FontFile2 program
had no OS/2 table and the font's embedding permissions (OS/2.fsType)
never reached the PDF: a Preview & Print or Restricted font looked
unrestricted to anything reading the file later (designcraft#1781).
Patch 18 adds the source font's OS/2 table, byte for byte, to a
TrueType subset that lacks one, rewriting the table directory with its
checksums and head.checkSumAdjustment. CFF programs are still embedded
bare. Ledger, patch file and SOURCE.json updated; craft-pdf's new
font_tables test checks the table, its fsType and the font's checksums.
* krilla: the OS/2 test checks the embedded program is a subset
Its sfnt and re-read checks also pass for the source font embedded whole. A subset has fewer glyphs than the fixture's 11, and a shorter glyf.
---------
Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
* update: offer Save and Update in the prompt when the app can save (#586)
With unsaved work the prompt only said to save or close first. An app can now pass can_save to show_with_save: the button then reads Save and Update, a click asks the app to save through take_save_request, and the install starts once nothing is unsaved. save_stopped reports a save that did not get there. show and show_if are unchanged, so other apps see no difference.
* update: test that a second click during the save leaves the prompt open
The saving prompt test only read the painted text. This one clicks where Save and Update was, where a Dismiss would catch the second click of a double click.
* update: Save and Update follows the ready update (#586)
A ready update whose close was canceled now offers Save and Update in place of Restart to Update while the app can save. Once the save ends with nothing unsaved, the app is asked to close in that same frame, once. Tests cover both prompts and the close order.
---------
Co-authored-by: Marc <184940552+marcwgls@users.noreply.github.com>
craft-prepress depends on linesweeper, and #633 adds a copy of it in
vendor/linesweeper and runs its tests from scripts/test-pdf-backends.sh.
Without this path, a pull request that changes only that folder runs
SonarCloud and none of these tests.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
Drop the residual_ prefix from four tests in language_packs/tests.rs.
The two cleanup tests become committed_cleanup_*, matching the
committed removal receipts they exercise. Test bodies are unchanged.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
* prepress: one wide curve no longer slows region cleanup for every other curve
The flattener's region cleanup looks up the input curves whose bounds hold
both ends of an output piece. The lookup searched back from a point by the
width of the widest input curve, so one curve as wide as the page made every
lookup scan nearly every input curve, and the cleanup grew quadratically with
the number of curves.
The curves are now grouped by bounds width, each group within a factor of two,
and each group is searched within its own widest bounds. The lookup returns
the same curves in the same order as before, so the regions are unchanged.
* prepress: region cleanup keeps a curve held just inside its right edge
Far from the origin, `x - width` can round above the left edge of a curve
whose bounds hold `x`, and the width-group search then skipped that curve.
The search's left edge is now rounded outward.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
macOS returns EILSEQ when a file name is not UTF-8, so the test panicked while creating its checkout. The test now ends at that step on macOS for that error. Any other error, and the same error on another platform, still fails the test.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
* web-api: refuse calls beyond an in-flight limit, and say who can call window.<app>
At most 64 calls (PageApi::with_max_in_flight) may wait for the app at once. A call made while that many wait rejects at once with a busy error and never reaches the app, so a page script that calls in a loop without awaiting cannot grow the app queue without bound, as the desktop control server already answers busy when its queue is full. The README also says the API is a property of the page global with no key: any script in the page origin has the same command control as the desktop control server.
* web-api: turn a busy call away before converting its params, and say a same-origin parent or opener can call window.<app>
A call over the in-flight limit used to stringify and convert its params before the busy check, so a large payload still cost the work it was being refused for. The params are now built by a closure the call runs only once it holds a slot.
The README said a parent, a child or an opener cannot reach window.<app>. That holds across origins only: a same-origin parent, child or opener with a window reference calls it directly, and the craft-web-host origin and source checks do not apply to that call.
---------
Co-authored-by: Helen Kwok <107752876+helenkwok@users.noreply.github.com>
A segment that exits at a sweep line keeps its position until the sweep advances, and segment_range leaves it out.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
Plates::composite converts through sRGB, which clips the press gamut
before a print profile sees it. Output converts press CMYK straight into
a gray, RGB or CMYK output profile (CMYK -> PCS -> output) at a chosen
intent and black point compensation, and Plates::composite_to combines
spot inks in that space: a multiply in gray or RGB, a multiply of the
complements in CMYK. CmsConversion::profile exposes the press profile.
The spot ramps move into shared helpers, used by composite and output;
the Lab encoding moves into one used by cms and output.
Part of #838 (item 2). The printer-leg semantics are adapted from pdfcer
(MIT, same author), crates/pdfcer-print/src/icc_proof.rs at 0a249a73;
the code is new, on craft-cms.
---------
Co-authored-by: KenM76 <KenM76>
* update: read whether the copy installs itself on the check's thread
When a check found a release, Updater::tick opened the startup prompt, and
StartupPrompt::new read the installed program, share, doc and icon trees
to decide whether to offer Update and Restart. On slow or stalled storage
that froze the frame loop.
The check's thread now makes that inspection after the release is found
and sends its answer with the release. The prompt is built with the new
StartupPrompt::with_self_update, so tick reads no installed file. A
prompt that a failed installation reopens keeps the answer of the prompt
that started it. StartupPrompt::new and Updater::offer still inspect on
the calling thread.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
* print: driver_settings_dialog sets a Windows driver's own options for one job
A Windows print job could take a driver's own options, such as media type
and print quality, only from the printer's saved Printing Preferences
(open_printer_preferences), so choosing them for one job changed the
printer's defaults for every later job.
driver_settings_dialog(&mut job, parent) shows the driver's dialog
(DocumentProperties) for the job's printer. It opens on the job's earlier
choices for that printer, without the ones the job decides, when the
driver still reads them, else on the settings the driver gives a new job,
with the job's copies and collation. OK stores the settings in the new
Job::driver_settings. Cancel leaves the job as it was, and so do settings
the dialog returns exactly as it opened on them, since some drivers
return OK from Cancel with the settings they were given. craft-print does
not save the settings as the printer's defaults.
When the job prints, Windows converts the settings to a PrintTicket
(PrintTicket::from_dev_mode). craft-print removes the features the job's
own ticket decides: copies, collation, paper, orientation and scaling,
pages per sheet, binding and posters, two-sided when the job sets it, and
color when it asks for grayscale. It then merges the job's ticket after
the rest. The driver's private settings are kept, so a driver that also
keeps pages per sheet there can still apply it. The existing paper,
orientation and option checks run on the ticket the driver validates.
Settings are used only on the printer whose name they were chosen for,
and command_preview marks them as not used when the job, or the default
printer, is another one. Other platforms return an error, and CUPS jobs
ignore the settings.
winprint is pinned to dotCooCoo/winprint.rs 72951d7, which adds
from_dev_mode on top of storytold/winprint.rs main, until that change is
merged there. examples/driver_settings_dialog.rs opens the dialog and
prints a test sheet.
* print: the hand-run driver test accepts zeroed settings read as defaults
the_driver_dialogs_settings_leave_the_jobs_own_options expected every
driver to refuse a DEVMODE of zeros. Two drivers read it as the settings
they give a new job instead. The test now accepts either outcome: settings
the driver refuses are replaced by the dialog, settings it reads are kept,
and either way the dialog opens as if the job had no settings. The README
says such settings stay on the job after Cancel and print as the driver's
defaults.
* print: the README and hand-run test describe settings with no fields set
The hand-run Windows test compares the seed's replaces_unreadable with
whether the driver refused the settings, in place of a branch whose
check always passed, and describes its input as a DEVMODE with only its
size set. The README says such settings stay on the job after Cancel
and after OK with nothing changed, links the DEVMODE dmFields
description, and no longer says how the job prints with them.
* print: refuse a job whose driver replaced the dialog's media type, resolution or quality
A driver that validates the job's ticket can replace a media type, resolution or
print quality chosen in its dialog when it conflicts with the job's paper, and
Windows reports that as a success. The validated ticket is now compared with the
dialog's settings, by option name and scored values, and the job is refused when
one of them changed.
The Windows preview lists two-sided printing and color that the job leaves open as
"driver settings or queue default" and "driver settings or driver default": it
matches the settings to the printer by name and does not ask the driver to read them.
* print: the driver dialog opens without earlier settings the driver reads but refuses to merge
Earlier settings that a driver still converts to a ticket but then refuses to merge, or to convert back to its DEVMODE, are left out, as unreadable ones already are, so the dialog opens and can replace them.
---------
Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
* ui: resize iconic flyouts from their top edge and free top corner (#1094)
A flyout's top edge and its canvas-side top corner now resize it; the
column-side edge and its corners stay anchored. A top-edge resize keeps
the bottom and saves the top as `Group::flyout_offset`, its distance from
the group's icons, through the new `Action::MoveFlyoutTop`. The offset is
serde-defaulted and kept in close/restore locations, so older workspaces
align flyouts with their icons as before. Saved offsets are finite and
bounded, and placement clamps them inside the float bounds.
* ui: test flyout top drags past the minimum, short viewports and older workspaces (#1094)
* ui: give the flyout's top resize handle a 4 pt band (#1094)
A one-pixel top handle was hard to grab with a real mouse. Frames
whose contents supply their own header can now set
`FloatingFrame::top_handle_height`; the default stays one physical
pixel. Iconic flyouts use the stock resize band's 4 pt, over the top of
the tab strip, and the strip below it still drags the group.
---------
Co-authored-by: ruchirguitar <113586074+ruchirguitar@users.noreply.github.com>
craft-flags keeps one per-user file, ArtCraft/flags.toml beside the AI
layer's ArtCraft/ai, that the launcher and every app read; CRAFT_FLAGS
overrides it for one run. Every flag is off by default. The first two:
AI-MCP (AI agents through MCP) and AI-MODELS (AI models and services).
Loading never fails: a missing or damaged file means defaults, with the
reason in Flags::problems. set() changes one flag atomically and keeps
everything else in the file, and never overwrites a file it can't read.
In the browser every flag is at its default.
Closes#1118
---------
Co-authored-by: David Mann <daaavid.mann@gmail.com>
* print: bound the printer XML parse; respell values where they are
Every non-test parse of the driver's PrintTicket and PrintCapabilities in
ticket.rs goes through one bounded parse (new xml.rs): at most 16 MiB,
1,000,000 nodes, 256 attributes and 64 namespace declarations on an
element, and 256 levels of nesting. roxmltree's work grows with the square
of an element's attributes and namespaces, so a broken or hostile driver
document could stall Print. The attribute, namespace and depth limits are
checked by a scan that skips comments, CDATA, processing instructions and
quoted values; the node limit is roxmltree's own nodes_limit. A document
past a limit is refused the way an unparseable one already was.
The PrintTicket respell now finds each attribute's value from the
attribute's full range (the quote after its `=`) instead of
`range_value()`, which roxmltree computes from a name length kept in 16
bits and a space count kept in 8, so it pointed elsewhere past a 64 KiB
name or 255 spaces around `=`.
Closes#630. Closes#631.
* print: bound the two parses #411 added
---------
Co-authored-by: KenM76 <KenM76>
* Add craft-pkcs7: DER, X.509, CMS SignedData, PKCS #12, RFC 3161 and revocation from PdfCraft
Moved from PdfCraft's crates/sign at 1d7a9f9f: der, x509, cms, pkcs12, timestamp,
revocation, keys, rsa_pad and ec512, with their unit tests, the integration tests
that need no PDF, and the test keys.
x509 no longer returns PdfCraft's worded sentences: signing_problem gives a
SigningProblem and build_chain_noted a Refused (reason and the two certificates).
The checks behind them are unchanged. Error is SignError without its PDF variants.
* craft-pkcs7: write the certificate serial verbatim in SignerInfo and ESSCertIDv2
A serial with its high bit set and no leading zero was written with one added, so
the signer identifier and the signing-certificate attribute named a different
number than the certificate has.
Ported from storytold/pdfcraft#6868. The test uses a certificate that really has
such a serial and also checks that the signer's certificate is found.
* craft-pkcs7: note why RIPEMD-160 is supported
---------
Co-authored-by: jonathanwxh-cell <jonathanwxh@gmail.com>
* craft-audio: native MP3 (Layer III) decoder (feature `mp3-decode`)
A clean-room Layer III decoder written from ISO/IEC 11172-3 and 13818-3:
MPEG-1, MPEG-2 and MPEG-2.5 (8-48 kHz), CBR and VBR, mono, stereo, dual
channel and joint stereo (mid/side and intensity), long, short and mixed
blocks, and the bit reservoir. It shares the encoder's Huffman and
scalefactor band tables and the MP1/MP2 synthesis filter.
`decode`, `Decoder` and `TrackDecoder` now read raw .mp3 files and MP3 in
MP4 and Matroska natively instead of through symphonia. A Xing / Info / VBRI
frame is not a packet, and the LAME tag's encoder delay and padding are
applied, so a file decodes to its exact presented length. The seek
pre-roll covers how far back the bit reservoir can reach, so a seek is
bit-exact. symphonia stays the fallback for free-format MP3.
The encoder moves to mp3/encoder.rs so that each half builds without the
other.
* craft-audio: MP3 review and CI fixes
- Huffman: big values stop at the granule's part2_3_length. A damaged
granule no longer reads the next granule's bits, as ffmpeg does.
- Joint stereo runs on the lines in coded order, before short blocks are
reordered, as ffmpeg and libmad do. Where the two channels' block layouts
differ, against the specification, each channel is then reordered by its
own layout.
- Seek pre-roll: sized from the smallest frame the stream can hold (the
lowest bit rate for its version, rate, mode and CRC), not the last frame,
so a seek into a VBR stream's small frames still has the reservoir. The
decoder learns the stream's format from its first frame.
- Mixed-block oracle test: edit only granules whose scalefactors take no
bits, so the edited streams stay valid, and not before a pure short
block. ffmpeg's short-block IMDCT drops overlap that a mixed block's long
subbands carry, where the specification adds it. Use 16 kHz instead of
12 kHz.
- Routing oracle: ffmpeg before 9 decodes the 1105 samples of the MP3
Matroska CodecDelay.
* craft-audio: MPEG audio packets of several frames keep their length
An MP4 or Matroska packet may hold several MP1/MP2/MP3 frames.
TrackDecoder now counts the frames each packet holds from their headers:
- frames_per_packet is None once a packet in the lookahead or a decoded
packet has held several frames, so an MP4 track's length is no longer
capped at one frame per sample and the container's timing decides.
- Concealment is the length of the frames a damaged packet holds. For MP3
a packet lost whole is as long as the last packet, and one frame before
any is decoded.
Also corrects the Huffman doc comment: a big-value pair that starts
before the granule's end is kept whole, as ffmpeg does.
* craft-audio: MPEG audio concealment after partial packets and before the first
- A packet whose later frame fails decodes only in part: like AC-3, it no
longer replaces the length of the last whole packet that concealment
uses.
- MP1/MP2: a packet lost before any has decoded, or right after a seek, is
one frame (384 or 1152 samples) of silence rather than none, as MP3's
already is.
---------
Co-authored-by: alehel <git@ornumhelgaker.no>
* craft-video: MPEG-4 Part 2 Simple profile encoder
Adds a clean-room MPEG-4 Visual (ISO/IEC 14496-2) encoder behind the new
`mpeg4` / `mpeg4-encode` features: the stream type Xvid and DivX write,
which craft-media already identifies (CodecId::Mpeg4Video) in MP4, Matroska,
AVI and MXF but which no crate could produce.
- I- and P-VOPs, 4:2:0 8-bit, H.263 quantisation, half-sample motion with a
predictor-seeded diamond search, skipped and intra macroblocks in P-VOPs,
intra refresh within the 132 codings of §7.4.5.
- Constant quantiser or 1-pass average bitrate.
- Headers in band (raw .m4v, AVI) or as extradata / CodecParams (MP4, Matroska).
Tests use ffmpeg/ffprobe as external decoders: every coefficient table entry
and escape mode 1/2 event decodes like the fixed-length escape, and encoded
streams decode without diagnostics, close to the encoder's reconstruction.
---------
Co-authored-by: alehel <git@ornumhelgaker.no>
Moved from MailCraft's crates/openpgp at a44a45013d1c. Built on rPGP 0.21.0 as
there. The one code change: the Unicode format-character test the From address
check used from mailcraft-names is now a private function here, with a test.
`Composition::aaf_mob_id` is documented as a read identity: writers generate
fresh format identifiers and never preserve it. The roundtrip test compared
whole compositions after the second write, so it broke as soon as #1098
exposed the field. Compare them with the id cleared, as the surrounding
comment already described.
craft-tiff caps chunk descriptors at the file's length (storytold/craft-libs#827), so a grid of tiles sharing one payload lists fewer chunks than the image declares. Comparing that capped list against the grid refused a file shorter than its tile count for "missing chunks" instead of for the data it actually holds. Compare the offsets table, which is the source of truth, and cover the short-file case.
* craft-drawingml preset: the extra outlines dispatch on a Name enum
Ported from storytold/deckcraft#739 by @Bryson14.
* craft-drawingml preset: the 3- and 4-bend elbow and the curved connectors follow presetShapeDefinitions
Ported from storytold/deckcraft#1851 by @Hamza0101.
* craft-drawingml warp: text on a guide sets each glyph down whole
Ported from storytold/deckcraft#1799 by @leobasilio.
* craft-drawingml preset: the Name dispatch test's digests as this repository builds the outlines
The digests in storytold/deckcraft#739 were taken on DeckCraft's fc35ad67. Here two curved arrows
digest differently both before and after the refactor (the preset sources are identical), so the
test now holds the values from craft-libs 2b35d243, before the refactor.
* craft-drawingml preset: every preset's text rectangle from presetShapeDefinitions
Ported from storytold/deckcraft#650 by @NikitkaRa. Its preset::defaults is #1851's
adjust_defaults, which this repository already has.
* craft-drawingml custgeom: connection sites (a:cxnLst) read in the shape space and written back
Ported from the format part of storytold/deckcraft#1748 by @jagjordi.
* craft-drawingml color: behaviour-preserving cleanups
Ported from storytold/deckcraft#1610 by Cédric Legrand.
* craft-drawingml: resolve current-main API and test conflicts
* craft-pptx: use DrawingML writer defaults for custom paths
* craft-drawingml: strengthen geometry regression checks
---------
Co-authored-by: Bryson Meiling <bryson.meiling@gmail.com>
Co-authored-by: Hamza <mail.hamzanaveed@gmail.com>
Co-authored-by: Leonardo <leobasilio@gmail.com>
Co-authored-by: Nikita Rakitin <nnnrrr93@gmail.com>
Co-authored-by: Jordi <jordiag@kth.se>
Co-authored-by: Cédric Legrand <cedric@legrand-tech.fr>
* prepress: printer's marks
Marks::new lays out crop marks, bleed marks, registration targets and
process color bars around a trim box, with the sheet that holds them and
room for a page-information line. Marks::draw paints them onto a krilla
surface: lines in the registration color (Separation /All), bars in
DeviceCMYK. ISO 32000-2 14.11.3, 14.11.2, 8.6.6.4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* prepress: keep the info line clear of the bottom target
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* prepress: clear targets only when drawn; cap line width at a third of the mark
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: KenM76 <KenM76>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Port of storytold/filmcraft#1952, reviewed and approved there before the
decoder moved to craft-libs. 4:2:2 streams that use no range-extension
coding tools (what cameras and libx265 write) now decode:
- chroma geometry from the SPS chroma format (ChromaFormat shifts) in the
picture store, intra, inter, transform tree, deblocking and SAO;
- Table 8-3 IntraPredModeC mapping for ChromaArrayType 2;
- stacked chroma transform blocks with their second cbf flags;
- chroma QP = Min(qPi, 51) for non-4:2:0 (Table 8-10 applies to 4:2:0 only);
- chroma motion vectors scaled per axis;
- a PPS that scales SAO offsets (a RExt tool) is refused as unsupported.
Tests: 22 libx265 4:2:2 fixtures (8- and 10-bit) compared sample-exactly
with ffmpeg, the Table 8-3 derivation, and the SAO offset scale check.
craft-rtf gained craft-flow, craft-metafile, craft-wordmodel and image in
its manifest, but Cargo.lock was not regenerated. Every --locked cargo
command then tried to rewrite the lock and failed, so all crate workflows
on main stopped during dependency resolution.
Regenerated with cargo metadata.
craft-pdf: the PDF object layer from PdfCraft (`cos`), on filters and crypt
* hayro-jbig2: bound a stream's total decode work and what a page retains; no i32 overflow
Port of pdfcraft 85c10051 (patches 5-9), 82439525 (patch 10) and 10107d94 (patch 12).
* hayro-jbig2: PdfCraft's JBIG2 follow-ups (refinement fixes, file header, work accounting, dictionary pixel cap)
Ports pdfcraft 72e763ad, b7ec3669, e3bc4e85, 01d3479f, b9e068aa, 858ce960, 07f44038, e38b9d18, 8717a085, 58c30af3 and the hayro-jbig2 part of e2464e14 (with the hayro-jbig2 part of 0ed33990 they build on).
* Add craft-stream-codecs: the codec modules of PdfCraft's stream filters
LZW, ASCII85, ASCIIHex, RunLength, the TIFF and PNG predictors, bounded CCITT
fax decoding (through hayro-ccitt) with Group 4 encoding (through fax), and
the lossless JBIG2 encoder with its MQ coder, from pdfcraft-filters at
PdfCraft revision 80e26e674d1aa33078e83c8139875047f3289eb6.
The crate sits below craft-pdf and craft-tiff: it knows no container. The
PDF filter chain, Flate and the bounded JBIG2 decoding entry are not part of
it.
* craft-pdf: the PDF filter chain from PdfCraft (`filters`)
Adds the `filters` feature: the /Filter chain of pdfcraft-filters (PdfCraft
revision 80e26e674d1aa33078e83c8139875047f3289eb6) as craft_pdf::filters,
over the codecs in craft-stream-codecs. It adds Flate, strict and tolerant
chain decoding, byte accounting and a shared work allowance, and encoding,
with the chain's unit tests, its property tests and its fuzz target.
The code is unchanged apart from the imports of the moved codecs; FilterError
is craft-stream-codecs' CodecError under its old name.
* craft-stream-codecs: bounded JBIG2 decoding (decode_jbig2_within)
The JBIG2 decoding entry of pdfcraft-filters (PdfCraft revision
80e26e674d1aa33078e83c8139875047f3289eb6, src/jbig2/decode.rs) with its tests.
It spends from the caller's work allowance through hayro-jbig2's
Image::decode_within and charge_reading, which come with
fix/sec-hayro-jbig2-followups (#886).
* vendor/README.craft-reader.md: one #831 paragraph, the follow-ups after it
* craft-pdf: filters re-exports decode_jbig2_within (and lib.rs module order)
* craft-pdf: the object layer from PdfCraft (`cos`)
Adds the `cos` feature: PdfCraft's pdfcraft-cos crate (revision
1d2af9907ba772b368f6b54811359805fa5428e9) as craft_pdf::cos, on crypt and
filters, with its unit tests, integration tests and examples. Its test helpers
come with it: pdfcraft-testkit as src/cos/testkit.rs (cfg(test)) and the qpdf
runner of pdfcraft-oracle as tests/cos/oracle.rs.
The code is unchanged apart from module paths and doc comments. The child test
of file_identifier is named by its module path, since the integration tests
are one binary.
* craft-pdf: cos unit tests build for wasm
The property tests in src/cos/writer.rs need proptest, a dev-dependency of
the non-wasm targets only, and one test in src/cos/document/tests.rs times a
load on a thread, which wasm32-unknown-unknown does not have. Both are
compiled for non-wasm targets only; the other unit tests still build for wasm.
craft-xlsx: pictures in cells and dynamic-array metadata
* craft-xlsx: read parts with canonical prefixes so kept trees can be written back
The part layer read every part by local name, so extLst children (x14:, xr:, xm:),
mc:AlternateContent and r:id lost their namespaces and could not be written back.
Parts are now read with one fixed prefix per namespace (the main namespace unprefixed),
mc:Ignorable and mc:Choice/@Requires are rewritten to match, and ns::declare prepares a
kept tree for writing. craft-xml: a namespace listed with the empty prefix reads unprefixed.
* craft-xlsx: write SpreadsheetML workbooks (Document read and write)
Document holds a whole workbook: the workbook part, shared strings, styles, each worksheet's
rows and the rest of its part, and every other part kept as bytes. write regenerates the
workbook part, worksheets, shared strings and styles from the model, keeps unknown children
in place (schema order for regenerated ones), keeps part names and relationship ids, and
writes kept parts unchanged. Writers: Styles::to_xml and to_el for each table entry,
StringItem::to_el (phonetic runs checked as on reading), SheetPart::to_xml with rows
streamed, Workbook::to_el, XlsxKind. Row and DefinedName keep their other attributes;
CellStyle reads iLevel. craft-opc: LazyPackage::canonical gives a part's stored name.
* craft-xlsx: typed worksheet features and comments, written back
SheetPart::features lifts sheet views, print setup, data validation, conditional formats,
hyperlinks and the legacy drawing into types that mirror their elements (optional attributes,
unnamed ones kept) and writes them in schema order. Comments come from the comments part,
note shapes from the VML drawing; a sheet that gains comments without a VML drawing gets one.
A hyperlink to a new URL gets its own relationship. craft-sheet: Range derives Default.
* craft-xlsx: drawings, charts and the theme on craft-drawingml
Drawing reads a sheet's xdr:wsDr into anchors with typed placements and objects kept as
written; Anchor gives the object's kind, properties, chart or image relationship and xfrm.
Package::drawing, Package::chart (c: and cx: parts through craft-drawingml) and
Package::theme. Document worksheets hold their drawing part, regenerated with its
relationships kept by id; add_chart and add_picture add new chart parts (chartEx behind
mc:AlternateContent) and images with their anchors. More drawing namespaces get prefixes
(a16, asvg, aink, am3d, cx1-cx4, dgm).
* craft-xlsx: tables (ListObjects) read and written back
Table mirrors CT_Table: every attribute, columns with calculated and totals formulas, the
style info, autoFilter/sortState/extensions kept as written. Package::tables reads a sheet's
table parts; Document worksheets hold them as TableParts, regenerated with their
relationships and tableParts entries. Part names a document keeps are reserved before new
parts are named, so a new part never takes a name a later sheet keeps.
* craft-xlsx: PivotTables (caches, records, tables) read and written
Typed pivot cache definitions (source, fields, shared items, grouping),
streamed cache records and PivotTable definitions (location, fields and
items, axes, page and data fields, style), with every unmodelled child
and attribute kept. Workbook::pivot_caches lifts pivotCaches. A Document
holds caches and tables and regenerates their parts, relationships and
pivotCaches entries; an OLAP cache or a table on one stays a kept part.
SharedItems::describe gives Excel's shared-item flags and records_xml
writes a records part, after GridCraft's pivot writer.
* craft-xlsx: pictures in cells and dynamic-array metadata
Package::cell_pictures follows a cell's vm through the value and future
metadata to its _localImage rich value and image, bounded and lenient as
GridCraft's richdata.rs reads it. Document::add_cell_metadata writes the
metadata part (XLDAPR for dynamic arrays, XLRICHVALUE for pictures), the
rich-value parts and the images as GridCraft writes them.