* pdf: keep a CID font's /W2 table past an out-of-range first CID; vendor hayro-cmap from PdfCraft
- hayro-interpret: a /W2 run whose first CID is past 65535 is skipped, as in
/W. A run starting at 4294967295 overflowed the CID counter and discarded
the whole table. Unit test in font::cid.
- hayro-cmap 0.1.0 is vendored from PdfCraft a2ec27b47 with its malformed-CMap
patch (PdfCraft #3177): bad bfchar/bfrange entries, an unresolvable usecmap
and an unparseable tail are skipped instead of failing the whole CMap. The
crate's tests come with it. Wired up like the other vendored Hayro crates
(workspace exclude, patch entry, SOURCE.json, backend test script); NOTICE,
ATTRIBUTION.md and vendor/README.craft-reader.md record the source.
* hayro-syntax: refuse an xref-stream subsection that runs past object number u32::MAX
The object number was start + i in unchecked u32: a subsection starting near
u32::MAX overflowed (a panic in debug builds, a wrong object number in
release). Covered in xref::tests::xref_stream_entries_need_backing_bytes.
* hayro-cmap: a binary usecmap counts against the nesting limit; /W2 checks the CID first
- hayro-cmap: a binary CMap's usecmap passed its own depth to the nested
parse, so a self-referencing binary CMap recursed until the stack
overflowed. It now counts like a text usecmap. Test:
self_referencing_binary_usecmap_stops_at_the_nesting_limit.
- hayro-interpret: the /W2 first-CID check runs before the run's metrics
are read, so an incomplete run past CID 65535 no longer discards the
rest of the table.
* hayro-syntax: refuse xref-stream object numbers past i32::MAX
ObjectIdentifier stores an i32; a number between i32::MAX and u32::MAX
was cast to a negative object number.
- hayro-syntax ascii_85.rs: main's decode-limit version (same bound as
the pdfcraft ec0a965 copy, plus its test).
- hayro-interpret and krilla SOURCE.json: source fields from pdfcraft
ec0a965 / krilla 0.8.2, sha256 recomputed for merged files.
- krilla PNG decode cap from main recorded as patches/11-png-decode-cap.patch
with its ledger row and README section.
* i18n: scripts, direction and regional Han per language tag
scripts(tag) lists the ISO 15924 scripts a language's interface text is
written in, direction(tag) follows the main script, and han(tag) gives
the regional Han forms (SC, TC, HK, JP, KR) for picking a CJK face.
I18n::rtl uses direction.
* i18n: non_exhaustive Script and Han; regions that imply a script
pa-PK, uz-AF and az-IR are written in Arabic and sd-IN in Devanagari, as
CLDR's likely subtags give them. A script subtag still wins.
* i18n: han and catalog matching follow region-implied scripts
han(zh-US), zh-AU and the other regions CLDR writes in Traditional
characters give Traditional, and pa-PK picks a pa-arab catalog, never
Gurmukhi pa, as pa-Arab-PK does.
* i18n: Hani and yue-Hant pick Han forms by region; usual scripts for kk, ky, tg, ku, ms, ug
* i18n: base_direction of a paragraph from its first strong character
Each of these languages accepted every word in capitals of up to six letters and every word
with a digit on its own, so turning off Ignore words in UPPERCASE or Ignore words that contain
numbers had no effect on them for short words. The check now takes the options, as the Spanish
one does; the direct is_correct/is_correct_with keep the defaults.
Co-authored-by: Federico Olivares <FedeOlivares@users.noreply.github.com>
Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
* craft-ui: match guard for a stack's hit test (clippy 1.95 collapsible_match)
* Update egui to 0.37
egui 0.37 replaces WidgetType with accesskit's Role and renames a few
methods. Mapped per egui's own table (WidgetType docs): Checkbox is
CheckBox, SelectableLabel is Button, Other is Unknown; UiBuilder::id and
Ui::id are scope_id; Id::new is Id::unique (the same hash). No behaviour
change.
egui's test harness now panics on a glyph no installed font has, and its
bundled fonts dropped U+22EE, so the docking fixture's group header draws
an ellipsis instead of a vertical ellipsis.
* craft-ui: README says egui 0.37
---------
Co-authored-by: Davis Brief <davisbrief@gmail.com>
A frame's side zones reach DockStyle::zone_depth (40 pt) into the body below
the tab strip, or a third of a smaller body, so a frame keeps its center.
drop_zone, zone_shape and resolve_drop take the depth. In the Frame style a
drag over a frame outlines every zone a drop there would change something in
and fills the one under the pointer, without the outline of the resulting rect.
Maintainer review on storytold/wordcraft#3562: opening_marks reverse-scans the characters before a
question or exclamation mark, and ends_clause asked in_address for each one,
which scanned every address range, so a paragraph of thousands of addresses
followed by a question took quadratic time (about 99 KB: hundreds of ms).
address_at() finds the range a byte is in with a binary search over the
sorted, disjoint ranges, and also gives ends_clause the range's end without
another scan. Behaviour is unchanged (the URL and punctuation regressions
still pass).
- address_lookup_finds_the_range_a_byte_is_in: boundaries of the lookup
- many_addresses_before_a_question_stay_linear: 99 KB of addresses before a
question or exclamation (the review's reproducer and two variants), checked
for the right issue range and for taking under 75 ms (about 1 to 5 ms now,
about 300 ms with a scan per character)
Upstream merged storytold/wordcraft#3177 (dictionary hints for every Hunspell language) and storytold/wordcraft#3480.
Resolve the conflicts in crates/proof/src/lib.rs by taking storytold/wordcraft#3177's
dictionary_loaded/dictionary_needed structure and adding the four Spanish
varieties to it, and in docs/spelling-dictionaries.md keeping both sides.
I18n::new keeps the embedded text and parses nothing; a locale's rows
are parsed on the first lookup that reaches it (also as a fallback) and
its bad rows logged with log::warn!. new returns only the locale-level
problems. check_all parses every locale and returns all problems.
name() scans for the language.name row instead of parsing the locale.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* media: reject NAL length prefix widths outside 1 to 4
length_prefixed_nals returns BitError::InvalidNalLengthSize for any other
width before scanning, empty data included. A width of 5 or more was
accepted and shifted bytes out of the length; a zero width returned Eof
only for non-empty data. Width 3 still splits, since
(lengthSizeMinusOne & 3) + 1 can be 3.
From filmcraft#2953.
* media: find the RBSP stop bit once per BitReader
BitReader::new records the position of the last set bit, and
more_rbsp_data compares against it instead of scanning back over the
data's zero suffix on every call (once per macroblock in a slice
parser). FilmCraft caches it in a Cell on first use; computing it in
new keeps BitReader Sync.
From filmcraft#2880.
* media: test the order CodecPrivate stripped headers are restored in
Header-stripping encodings with private-data scope prepend their bytes in
list order, so the last one listed ends up first. Empty prefixes and
frame-only scopes leave CodecPrivate as it is.
From filmcraft#2911.
* media: look up the track of each traf in a hash map
* media: bound Matroska indexing by a file-wide frame budget
Every indexed frame claims its stored bytes and at least one, so fixed-size
laces of empty frames cannot describe more frames than the file has bytes.
The frame count across tracks is capped at 2^26, the TrackEntry count at
2^16, and blocks find their track through a hash map.
* media: keep the spec spellings of Colour, ColourSpace and colourPrimaries
* media: PCM chunks stay bounded in MOV and MP4
The writer ends a PCM chunk at 1 MiB or half a second, and returns an
error past 2^32 - 1 samples in a track instead of clamping the stsz count.
The reader splits a PCM chunk above 16 MiB into several samples, so files
from writers without chunk limits read whole past 4 GiB. A sparse output
lets the tests write past 4 GiB, which also exercises the writer's co64
path.
* media: clamp max_lace_frames to 256 and round BlockDuration
* media: level-1 Matroska elements read at most the file's length in all
SeekHead entries pointing at nested elements made each one read the rest
of the file.
* media: set_sample_entry rejects a codec change
* media: the mux oracle compares stream counts before streams
* ci: media checkout does not persist credentials
* media: README lists the renames from FilmCraft and the output that differs on valid input
* media: rustfmt
* media: the stream count comparison leaves out timecode streams
* media: PCM chunks end at 1 MiB only, as ffmpeg's do
ffmpeg's PCM chunks run past half a second, so a duration limit split
remuxed chunks the source kept whole.
* media: frames and samples indexed scale with the file's length
Matroska indexes at most one frame per 8 bytes of file and ISO BMFF at most
one sample per 4 bytes, beyond the first 2^20 of each, so the sample tables
stay within about ten times the file's size. Empty fixed-size laces and
one-byte constant-size samples could make them 40 to 76 times its size.
* media: clamp the frame and sample allowances
- A bar drag reads this frame's pointer moves only. egui keeps the last
pointer position, measured against where the window was then; reused
after the window moved, it crept the window on.
- Escape pressed in any of the application's windows cancels a drag a
native window owns.
- DockContent::allow_native defaults to true: the feature is the opt-in.
- DockOutput::forwarded_modifiers tells Cmd/Ctrl+C, X and V, which
egui-winit sends as Copy, Cut and Paste, from those keys.
- A window made this session opens at its computed rect; only windows of a
loaded layout are restored onto a connected monitor.
- The content (inner rect) is each native window's desktop origin; only
OuterPosition converts to the outer position.
- A bar drag places the window from its reported position, so late moves
do not overshoot. The layout follows once the drag ends, and a window
left with its bar off every monitor goes back onto the nearest.
- A changed Floating::native (undo, reset, reload) moves the OS window
instead of being overwritten by its next report.
- Dragging a native window's only tab or group docks it whatever
title_bar_docks says.
- Escape that cancels a drag is consumed; nothing is forwarded while a
widget of the window has focus.
- A bar drag whose window goes away ends.
- An embedded fallback keeps its drop targets; floating windows get no
taskbar entry.
- The test host can give windows a frame inset and land moves a frame late.