Commit Graph
117 Commits
Author SHA1 Message Date
FredApps a62b9ee217 Merge approved PhotoCraft PR #8347: Type: Roman Hanging Punctuation (trailing marks hang, don't steer the alignment)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported hanging punctuation into current line placement and kerning modules, preserving forced breaks, bounded edge-tip row merging, justified-last-line behavior, area exclusions and independent Roman orientation shaping; kept PSD/engine/UI regression coverage.
2026-10-29 05:22:57 +01:00
FredApps 2e2eec3a43 Merge approved PhotoCraft PR #9478: fix(text): vertical type sets roman letters upright, one per em, as Photoshop does (#9470)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported upright Roman classification, independent unkerned/unligated em advances and tab reflow into current Para/VerticalPiece shaping modules; preserved area and paragraph flow; retained vertical geometry and PSD BaselineDirection regressions.
2026-10-29 05:18:29 +01:00
aiongg 6e9fb30dbc Merge #6723: Color Lookup: PSD save keeps a .3dl/.look LUT file as loaded (#6544) 2026-10-27 17:44:05 +00:00
Hector VillarrealandClaude Opus 5.5 026f9aae34 fix(text): vertical type sets roman letters upright, one per em, as Photoshop does (#9470)
Vertical type laid Latin letters and digits on their side (the word
turned 90°), and called that Photoshop's default. Photoshop's Vertical
Type tool stacks them upright, one character per em down the column:
the run's BaselineDirection is 1 (withStream); 2 (rotated) turns them.

- doc: CharStyle::rotate_roman (false = upright, the default).
- text/psd: BaselineDirection is read (a run without one takes the
  style sheet's, which Photoshop writes as 2) and written back.
- text/layout: in vertical type, roman characters take the upright
  path unless their run rotates them. Each is given one em down the
  column (a second shaping pass sets its letter spacing from the shaped
  advance), with pair kerning off between the stacked letters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:53:07 -06:00
VladimirPozdnyakov d16841f2fb Merge remote-tracking branch 'upstream/main' into qol-type-hanging
# Conflicts:
#	crates/text/src/layout.rs
#	docs/scorecard.md
#	docs/ui-parity.md
#	scorecard/type.toml
2026-10-24 22:05:31 +03:00
David Mann 23d8f053cb Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/compose/src/shape_split.rs
2026-10-24 03:12:55 +02:00
David Mann feb20ebc60 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/gpu/src/plan.rs
#	crates/io/src/adjust_map.rs
2026-10-24 02:59:10 +02:00
aiongg 7aaa59712a Merge main into integration-batch-7 2026-10-23 20:37:05 +00:00
Dylan M. Taylor 3729c3f664 security(raster,doc): count tile grids without walking them; share rebuilt tiles; index slice merges
Rect::tile_count counts a rect's tiles in u64; try_take_tiles uses it (no usize overflow on 32-bit). Surface::translated reuses one rebuilt tile for equal source-tile windows. auto_slices merges vertically adjacent runs through a hash index instead of searching the output.
2026-10-23 14:41:44 -04:00
David Mann c16f899467 Merge origin/main into fix/6544-lut-format-roundtrip
# Conflicts:
#	crates/format/tests/it/roundtrip.rs
2026-10-23 00:06:48 +02:00
David Mann fff01d8918 Integration: stack #7335 (its merge onto main, conflicts resolved) 2026-10-22 23:40:11 +02:00
David MannandClaude Opus 5.5 6c7e920d5a Merge PR #7335: Gradient Overlay: add Method selector and retain editable source stops
- crates/ui-egui/src/layer_style.rs: values_of keeps the PR's method/smoothness keys and source-stop ends, and main's (#7072) unconditional From/To and geometry fields.
- crates/compose/src/cmyk_tests.rs (no textual conflict): add the PR's new `interpolation: None` field to main's CMYK test GradientOverlay literal.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 23:39:14 +02:00
David MannandClaude Opus 5.5 cab3ef6191 Merge PR #5815: perf(doc): share the XMP packet, Duotone PSD data and unsupported adjustment bytes between snapshots
- crates/engine/src/tests.rs: kept both tests (main's restore_layer_selection test and the PR's history_states_share_large_document_payloads).
- crates/io/src/psd_import.rs: kept main's parsed Duotone inks (duotone_map) with the PR's Arc<[u8]> psd_raw; also main's unknown-adjustment-key import (#6575) now builds Arc<[u8]> raw.
- crates/io/tests/adjust_warnings.rs: moved to tests/it/adjust_warnings.rs on main; PR's .into() edits applied there, plus #6322's Color Lookup test (raw.as_slice().into()).
- docs/architecture.md: union; status line names both changes, both revision-history rows kept.
- Adapted main-new sites to the PR's types: psd_export.rs (Duotone write-back via as_deref/to_vec, Unsupported block compare by slice), inspect.rs and ui-egui unsupported_marker_tests.rs (raw .into()), io tests/it/psd_unknown_adjustment.rs (slice compare).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 23:38:56 +02:00
David MannandClaude Opus 5.5 95e0848332 Merge main into fix/4381-psd-frame-stroke
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:09:11 +02:00
David MannandClaude Opus 5.5 f5533e5d82 Integration: merge main into batch 6
Main merged #5940, #6472, #7838 and #7922 directly. Kept from the batch:
the snapshot/History-follow identity at the history limit (#5940,
c7ef3676a; main still had the 3-tuple HistorySpot) and the strokeless
shape at a 0 px width step (#6472, 962539607; main still added the
stroke). Main already carries the other two fix-ups (34c9d0ea4, dff8bfd0e).

Overlaps with main resolved:
- #5842 vs main's #5568: one path, apply_color, tool-gated as #5842
  has it, with #5568's float fill, kept fill opacity and lock skip;
  shape_fill_ui's duplicate foreground_changed/gesture dropped; #5568's
  tests run with a shape tool.
- #6230 vs main's #5180: one Type tool path click (path_target), no
  second type.attachToPath; vertical type does not start type on a path,
  as main has it; main's path_at/path_cursor and canvas arm dropped.
- #5452 moved the shape swatch to shape_paint_ui.rs: main's hex field
  (#6201) ported there.
- type_extra_cmds::with_text takes main's dpi form, pub(crate) for
  type_area_cmds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 19:20:26 +02:00
aiongg 934eb71d84 Integration: merge main
crates/engine/src/file_cmds.rs: batch keeps the save-point closure (takes the output path) and also copies the session's authorize hook into each scratch session, as main now does.
crates/raw/src/sensor.rs: both sides cap the memory of retained tiles; kept the existing retained_segment_bytes check (checked multiplication, same limit) and dropped main's duplicate inline loop.
2026-10-22 15:39:51 +00:00
aiongg 576ba0e02b Integration: track t12
# Conflicts:
#	contributors/people.toml
#	crates/compose/src/lib.rs
#	crates/compose/src/tests.rs
#	crates/engine/src/print_cmds.rs
#	crates/engine/src/print_cmds/tests.rs
#	docs/target-app-parity.md
2026-10-22 15:38:33 +00:00
aiongg ba120dc48e Integration: track t06
# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/i18n/tr.tsv
#	docs/gaps.md
#	docs/ui-parity.md
2026-10-22 15:38:19 +00:00
aiongg 26dbd7953b Merge PR #5834: Shapes: rounded corners on live triangles, polygons and stars (TOOL-214-12)
docs/scorecard.md: ours (regenerated at combine).
docs/ui-parity.md: kept main's header and added the PR's change entry once.
2026-10-22 15:37:29 +00:00
Dylan M. Taylor 58cd22d4ff security(doc): compute auto-slice coverage per band, not per cell
auto_slices tested every grid cell against the full slice-rectangle list
(covered(x, y) = taken.iter().any(...)). With slice edges forming the
grid, that is cubic in the slice count, so a crafted document's slice
arrangement could stall ordinary canvas drawing on the UI thread.

For each row band, mark covered x-cells in a single pass over the rects
that span the band, then scan the precomputed cells. This drops the inner
work from O(rects) per cell to O(1), while producing the same tiling.

Finding: 9fbea43b-3096-4cdc-b005-86d44a8fe57e (CWE-400)
2026-10-22 07:11:06 -04:00
David MannandClaude Opus 5.5 7a54fa9c77 Integration: merge main into batch 6
Conflicts, both sides kept: main's .act swatches next to the batch's .asl
styles (Open filters, preset extensions), main's Render smart filters next
to the batch's Distort ones (53 mapped), parity doc status lines.
docs/scorecard.md regenerated.

Follow-ups the merge needed: the Distort smart filter readers pass their
enum type to main's stricter enum_name (the type their writers use), and
the CMYK effect tests set main's new StrokeFx overprint and Bevel
gloss_anti_alias.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 12:09:25 +02:00
Yonghyuk Choi bea003acd8 Rebuild unrecorded Gradient Overlays from their end colours 2026-10-22 12:38:20 +09:00
Yonghyuk Choi dc029b93c5 Merge main into Gradient Overlay method branch 2026-10-22 12:38:20 +09:00
aiongg bf1000302d Merge PR #8367: Layers: per-layer XMP metadata (layer.xmpMetadata), stored as the reference app stores it
docs/file-format-parity.md: kept main's PSD row (45 smart filters) and added the PR's layer XMP packet phrase.
2026-10-22 02:23:45 +00:00
aiongg 8c92678a30 Merge PR #7815: PNG: correct sTER eye-order names without changing stored bytes 2026-10-22 02:22:43 +00:00
David Mann a8f91f54ad Merge PR #6230: feat(type): area type, text that wraps inside a closed path or shape
Integration: resolve with main for area type (#6230)

- Image Size with a new resolution (#7124, canvas_geom::set_resolution) now scales an area type's
  path with the text space like a box or a type path, so the same words wrap onto the same lines;
  test a_resolution_change_keeps_area_type_wrapping_where_it_was fails without it.
- The Paragraph panel's justify buttons (#7713) stay available on area type, which is paragraph
  text in Photoshop; test justify_buttons_work_on_area_type.
- Test files: main's tests plus #6230's; layout.rs imports joined; docs and scorecard regenerated.
2026-10-21 23:46:05 +02:00
Tom InglingandClaude Opus 5.5 052c1c3ab7 Layers: per-layer XMP metadata, as Photoshop's layer.xmpMetadata
A layer keeps its own XMP packet (Layer::xmp), where scripts and embedding
apps store data about the layer under their own namespaces.

- PSD/PSB/layered TIFF: read from and written to shmd > cust > layerXMP
  (UTF-16, NUL-terminated, after layerTime), laid out as Photoshop 2026
  writes it; an unchanged Photoshop block round-trips byte for byte.
- .pcraft: optional `xmp` on each layer.
- layer.xmpMetadata {layer?, rawData?}: read, set (one undo step) or
  remove with null; refuses malformed XML, DTDs, NUL and > 4 MiB.
- Duplicate Layer copies the packet; document.inspect reports hasXmp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 17:03:02 -04:00
VladimirPozdnyakov 0dfac5081f Roman Hanging Punctuation: trailing marks hang and don't steer the alignment
Photoshop's Paragraph panel checkbox, per paragraph style:

- doc: ParagraphStyle.hanging (serde default off; .pcraft keeps it).
- layout: a trailing run of closing marks (. , : ; ! ? and fullwidth
  twins, ellipsis) trims out of the aligned width on center/right lines,
  so a centered line ending in an ellipsis stays centered; a wrapped row
  of nothing but marks steps back onto the line above and hangs past the
  box edge (contiguous ranges, merged-row baseline, manual kerning; no
  RTL, vertical or tabs).
- PSD: /Hanging bool in the paragraph sheet, right after /LeadingType as
  the corpus files show; read defaults off.
- engine: type.setStyle takes "hanging":bool, params doc updated.
- UI: checkbox in the Paragraph section, a Paragraph Styles editor row,
  Character dock group grows one row; translations for the new label.
- tests: layout hang runs (trim, merge-back, plain no-op), PSD write and
  paragraph-sheet read round trips, engine setStyle, panel harness.
2026-10-21 22:45:10 +03:00
bazmarth 4573037531 Merge remote-tracking branch 'origin/main' into feat/polygon-corner-radius
# Conflicts:
#	docs/scorecard.md
#	docs/ui-parity.md
#	scorecard/tools.toml
2026-10-21 16:49:42 +00:00
aiongg 77557d75f1 Merge PR #8229: Integration batch: 8 PRs on main
# Conflicts:
#	crates/engine/src/layer_style.rs
#	crates/io/src/psd_export.rs
#	crates/io/src/smart_map.rs
#	docs/file-format-parity.md
2026-10-21 15:45:07 +00:00
David Mann 86811ddeee Merge PR #6002: Stroke: keep Overprint (overprint)
# Conflicts:
#	crates/engine/src/layer_style.rs
#	crates/ui-egui/src/layer_style.rs
#	docs/file-format-parity.md
2026-10-21 11:36:58 +02:00
David Mann a492716367 Merge PR #5990: Bevel & Emboss: keep the Gloss Contour's Anti-aliased (antialiasGloss) 2026-10-21 11:29:05 +02:00
David Mann 14b928e8a8 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-21 10:56:06 +02:00
David Mann d25387a459 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-21 09:35:08 +02:00
aiongg fc371711e6 Merge PR #5847: Shapes: Density and Feather on shape layers (#5846)
# Conflicts:
#	docs/scorecard.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-21 05:04:03 +00:00
aiongg 40895532aa Merge PR #5840: Export As: Resample menu, incl. Nearest Neighbor (#5838)
# Conflicts:
#	docs/scorecard.md
2026-10-21 05:04:01 +00:00
aiongg 5ec2b90f1b Merge PR #7771: Save for Web: later slices cover earlier ones, covered slices split into pieces (#7770) 2026-10-21 05:03:49 +00:00
David MannandClaude Opus 5.5 627bb8f1bf Integration: merge main, resolve conflicts (#6002)
docs/file-format-parity.md: both sides added revision-history rows; keep both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:11:01 +02:00
0073b395d4 Integration: merge main, resolve conflicts (#5990)
docs/file-format-parity.md: main added three 2026-10-15 revision rows
(DDS save, PNG sTER, PSD guides) where the PR added its own; keep all four.

Co-authored-by: varanus-salvator <262257003+varanus-salvator@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 23:50:13 +02:00
f44e8e4be8 Integration: merge main, resolve conflicts (#6230)
docs/scorecard.md was the only conflict: regenerated with `cargo xtask scorecard`
on the merged tree.

Co-authored-by: Silly Silk <31193727+SillySilk@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 23:08:25 +02:00
David Mann 2adfe0c4e2 Merge PR #5807: Type: keep superscript and subscript when a text layer is re-rendered (#5645) 2026-10-20 22:39:12 +02:00
David Mann 0b39361076 Merge main into feat/tool-214-12-shape-feather 2026-10-20 17:12:29 +02:00
David Mann 8aaf526108 Merge main into feat/file-215-18-export-resample 2026-10-20 16:36:25 +02:00
Daniel Campos RamosandOpenAI Codex 0689608619 PNG: name sTER modes by their specified eye order
Both sTER modes describe side-by-side subimages: mode 0 is cross-fuse (right eye first), and mode 1 is diverging-fuse (left eye first). Correct the enum and document comments without changing their serialized byte values. Add a labelled-pixel check against the literal mode bytes in PNG Extensions 1.4.0 section 3.6.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-10-19 14:08:44 -03:00
640873de7b PNG: keep a stereo file's sTER pairing on save (#6063) (#6285)
* PNG: keep a stereo file's sTER pairing on save (#6063)

Read the sTER chunk (PNG Extensions 1.4.0 §3.6) when a PNG opens, store it
on the document's FileEncoding, and write it back when saving, so a stereo
PNG still says it is a stereo pair. Covers the ordinary and the palette
PNG encoders, including interlaced output.

* io tests: pass the new sTER argument to encode_png_indexed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: highperfocused <highperfocused@pm.me>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:02:18 -04:00
David MannandClaude Opus 5.5 ebfe3d98da Save for Web: later slices cover earlier ones, covered slices split into pieces (#7770)
`slices::resolve()` only clipped each stored slice to the canvas, so a slice under a later
one was numbered and exported in full and Save for Web wrote the overlap twice (the HTML
path cut pieces itself, named `<name>_01`, `_02`). As Photoshop does, resolve() now cuts a
covered slice into its visible pieces: the first piece in reading order keeps the name,
every further piece is `<name>-NN` with its own slice number, and auto slices count the
pieces in their numbering (measured in Photoshop: sliceA, <doc>_02, sliceA-03, sliceB,
<doc>_05).

- Save for Web exports resolve()'s pieces as they are, with or without HTML; a no-image
  cell's text goes into its first piece only.
- Slice Options and slice.list show the slice's own name for every piece; slice.set accepts
  a slice that ends up wholly under later ones (number null) instead of calling it off the
  canvas.
- Slice Select drags the whole slice, not the piece that was hit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:02:32 +02:00
Finn Newick d8053570c7 Merge remote-tracking branch 'origin/main' into perf/doc-shared-blobs 2026-10-18 21:21:26 +01:00
oRE-o 8fb5d94d2b Gradient Overlay: expose interpolation methods and retain source stops 2026-10-18 18:36:30 +09:00
PanPDX 52fb67edde Merge upstream/main into area-type 2026-10-18 00:47:41 -07:00
PanPDXandClaude Opus 5.5 6ed536ce34 Merge upstream/main into area-type
Conflicts: upstream's horizontal-scale line breaking (#5565) touched the
same break and alignment code as area type. Box text keeps breaking at
the scaled width; area rows break at their span widths as before, with
the scale fixed at 1, since area spans are already in layout space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V5GRiHVR8XvTrbL1j8y9jW
2026-10-18 00:16:17 -07:00