Commit Graph
6 Commits
Author SHA1 Message Date
dotCooCoo 1186d1f712 Affinity: pressure curves that can't be read count against the document's limit
A curve rejected for having more than 256 segments now counts the most points a curve may have against the document's pressure points, so linking it from many strokes reads it a bounded number of times. Once the points are used up, later strokes import as plain strokes with a warning.
2026-11-01 18:09:53 -08:00
dotCooCoo e441d3ba18 Affinity: pressure curves keep dips between samples and stay within a document-wide limit
- Each segment of a pressure curve is also sampled where its width stops
  rising or falling, so a dip between the regular samples of a long
  curve is kept. The segment's values are scaled into -1..1 before that
  is solved, so huge values in a file can't overflow it.
- A curve counts as full width only within 1e-9 of it, so a curve just
  under full width keeps its profile.
- The pressure points of all strokes in one read are limited to about a
  million, as for characters and table cells. Curves at full width count
  too, and once the limit is reached no more curves are read; the
  strokes past it are imported as plain strokes with a warning.
2026-11-01 16:21:57 -08:00
dotCooCoo b473716e3e Fix #2089: Affinity strokes keep their Width tool profile
An Affinity stroke shaped with the Width tool stores its pressure curve
(LDeP: position along the path against width). The importer warned and
drew the stroke at full width all along.

- The pressure curve is read and sampled into the stroke's width
  profile (2 to 8 points per segment, 256 segments at most, widths up
  to the full weight). A curve at full width all along stays a plain
  stroke; one that can't be read is warned about.
- Brush strokes keep their own warning.
- The pinned Affinity 3 signatures for the five corpus files with such
  strokes are updated.
2026-11-01 14:17:23 -08:00
Dylan M. Taylor 4c82749b08 Security: Affinity import and brush expansion bounds (#3887)
* Audit: Affinity import (spot colour chain, zero-width records, corner radii)

* Audit: Affinity layer names are cut at 1024 characters

* Audit: brush expansion bounds (masks, library parsing, flattening), pressure profile lookup

* Brush: reach a node's mask through its extras
2026-10-23 22:43:42 -04:00
Riccardo Balloch 79c5d673ff AF.4: validate and harden Affinity 3 artboards, text and images 2026-10-09 13:45:55 +00:00
callmeBallochandClaude Opus 5.5 297a01b6aa AF.3: native Affinity import with artboards, vectors, text and images
Open and Place read Affinity documents natively (.af from Affinity 3,
.afdesign/.afphoto/.afpub from Affinity 1 and 2): layers and sublayers,
groups, artboards with their names and backgrounds, Publisher pages side
by side, curves with live corners, parametric shapes, compound shapes,
clipping by nesting, vector and pixel masks, solid and gradient fills,
strokes, fill layers, artistic and frame text, placed images (their
original JPEG/PNG), pixel layers, embedded documents as their cached
picture, opacity, visibility, locking and blend modes, at the document's
resolution in points. Unsupported content (effects, adjustments, brushes,
master pages, special shapes, Affinity-only blend modes...) is listed in
the import warning, one line per kind. A file whose native data can't be
read opens as its embedded preview with the reason, and that preview
cannot be placed or used as a template or library. Save never writes back
over the Affinity file and there is no Affinity export.

The document semantics were fitted to the thumbnails Affinity embeds in
176 public documents. `cargo xtask corpus --affinity` fetches 22 public
CC0/MIT/Apache-2.0 documents at pinned commits, sha256-verified; the new
engine test renders each and compares it with Affinity's own thumbnail
(0-4.4 of 255 mean difference, per-file ceilings). import_fuzz mutates a
synthetic native document's stream and container through open, render
and export; the fuzz crate gains a stream target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GQPh8UDgMyARR5Hat9UchC
2026-10-08 17:58:11 +00:00