Port behavior and regression coverage into current modules; preserve current upstream behavior.
Preserve current attribution exclusions and credit the mirrored Lucide Twirl Counterclockwise icon; keep both Liquify regressions.
Twirl Counterclockwise used Lucide's undo-2 arrow, which reads as Undo.
It now uses rotate-ccw, Twirl Clockwise's rotate-cw mirrored (path data
mirrored about x = 12), registered in icon_data and listed in
ATTRIBUTION.md with the other Lucide icons.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: the batch's wheel reads (#5547 Animated Zoom) keep their extra
argument with main's ids (`Id::unique`, `ui.scope_id()`); crop presets keep
#6620's `apply_choice` with main's accessible name; Bevel & Emboss keeps
#9370's per-mode id with main's name argument; the Stroke field keeps
#7203's gradients with main's name; tone.rs keeps #9139's move of the
Histogram panel to histogram_panel.rs (main only renamed ids there);
translation catalogs as unions.
Not flagged by git, the batch's new code follows egui 0.37 too: dropdowns
take an accessible name (Histogram Channel/Source #9139, tool Mode #5504,
Art History Style #1610, New Snapshot From #3567), MouseWheel events carry
`source`, `WidgetType` is `Role` (ColorButton is ColorWell, #7203),
`Id::new`/`Ui::id` are `Id::unique`/`Ui::scope_id`.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* egui037: name each control for what it sets, and order the eager fonts for the UI
CodeRabbit review follow-ups on the migration: the Artboard X/Y fields, the CAF
dropdowns, the channel Solidity field, the GPU backend/adapter dropdowns, the
corner radius fields and the canvas extension colour all had an accessible name
that named another control (or was shared by four). The eager craft-fonts
registration now puts the UI Japanese face first, as the lazy loader does, so
Japanese UI is not drawn in the manifest's Mincho face and shared Han characters
do not take Japanese forms.
Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* egui037: rustfmt the eager craft-font order
---------
Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
Merged with our fix-up d5139d177 (pr-1199-fixup), which merged main as of 8f09d122d.
Conflicts with main since then and with batch 8:
- photocraft-cli: main split the CLI into clap modules (#7071); the model wiring
(local_headless, configure_cli_models, batch's shared backend, droplet) is re-applied there.
- Cargo.lock regenerated: crates/ml pins ureq =3.4.2, so the app's ureq goes 3.5.0 -> 3.4.2.
- cutout_cmds: main's subject area (#8235) kept for the classical path beside the model path.
- file_cmds batch: main's per-input closure takes `s` later, so the backend and
integrations prefs are read before the closure instead of inside it.
- prefs_ui: model-choice filter with #4573's pref_choice_label; Integrations stays visible
(#4097) with the model choices only where models run; the translation-coverage test main
deleted (c3aa3f9e5) stays deleted; old section_fields test calls take PreferenceFieldOptions.
- Semantic clashes git did not flag: #4097's Integrations test literals in
apps/photocraft take ..Default::default() for the new model fields; main's and #4573's
section_fields test calls pass PreferenceFieldOptions.
- engine lib.rs, prefs.rs, smartselect tests, snapshot example, jobs_ui_tests, people.toml,
docs and i18n catalogs merged as unions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/file-format-parity.md: main's PSD row with the round-trip count
258/258. docs/scorecard.md: regenerated with `cargo xtask scorecard`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PR fixes the stale Photoshop corpus count (256 -> 258, the pinned
manifest xtask/photoshop-corpus.sha256 lists 258 PSDs) in
docs/development.md and docs/scorecard.md. The same stale number was
left in the io corpus test comment, docs/file-format-parity.md,
docs/roadmap.md ("258/256" round-trip floor) and ATTRIBUTION.md.
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main now has its own Recent Fonts (#3559), so this branch drops its separate
recent list (prefs `recentFontList`, `type.font.noteRecent`, `type.font.clearRecent`,
the five-font cap) and its font menu uses main's: the list is
`PhotocraftApp::note_recent_font`'s, the rows and arrow keys main's `font_menu_rows`,
and every applied family is recorded, as main does. Favourites, the class and
similar/variable filters, the style expander, format badges and the live preview
stay. Faux Bold keeps the one-pass thickened outline on main's fallible coverage
buffers (#6001), budgeted as a plain pass. Both sides' strings and icon credits are kept;
the scorecard is regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 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>
Main moved about 2100 commits since the branch's last merge. Resolved:
- smartselect_cmds.rs: main's empty-layer check for Object Selection
(check_sampled_pixels, #5246) now runs before the SAM branch, which
returned before it in a plain merge.
- cutout_cmds.rs: the classical path keeps main's cancellable stage;
the BiRefNet path is unchanged.
- prefs_ui.rs: main split section_fields into field_visible/field_rows;
the model labels, the filtered model choices and the options struct
move into that structure.
- apps: main's trusted_local() CLI session, Linux print spooler and frame
cap kept beside the local-model setup.
- channel_view.rs: main's version (#4915); the branch's change there was
unrelated to local models.
- i18n, people.toml, SOURCES.md, architecture.md, gaps.md: both sides.
Cargo.lock and docs/scorecard.md from main, then regenerated.
Co-authored-by: mighty-programmer <83077551+mighty-programmer@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
crates/ui-egui/src/i18n/ru.tsv: both sides added rows at two places; kept both (union).
docs/gaps.md: header from main, change-log lines of both.
docs/localization-parity.md: change-log lines of both.
PhotoCraft reads GIMP's .xcf (and .xcf.gz) files, read only, through a new
reader in photocraft-io written from the public XCF specification: versions
0 to 26, uncompressed, RLE and zlib tiles, 8/16/32-bit integer and
16/32/64-bit float precisions (linear precisions get a linear profile),
pixel layers at any position, groups by item path with pass-through,
layer masks applied or disabled, opacity, visibility, locks, colour tags,
the 2.10 and legacy blend modes mapped to Photoshop's (modes without an
equivalent open as Normal with a note), the ICC profile, resolution,
guides, the comment, extra channels and the saved selection; indexed
images open as RGB. Text, vector and link layers open as their pixels;
layer effects, paths and floating selections are reported.
Fixtures are written by GIMP 3.2 itself (scripts/xcf_fixtures.py), each
with GIMP's merged rendering as a PNG. In gamma-encoded blend and
composite spaces our composite matches GIMP within 0.5/255; GIMP's
linear-light default, its Clip to backdrop and its clamp-after-alpha
for unbounded modes are documented and measured in docs/xcf.md.
fill_to (Paint Bucket export): keep main's `source` alias and explicit
colour (`Usng` = `Clr ` plus `Clr `, #7199) together with the PR's
optional `Tlrn`/`AntA`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Pen, Freeform Pen and Curvature Pen options bar gets Photoshop's Path
Operations button: New Layer (Shape mode), Combine Shapes, Subtract Front
Shape, Intersect Shape Areas, Exclude Overlapping Shapes and Merge Shape
Components. In Shape mode a new path is added to the selected shape layer
with the chosen operation, so a hole can be cut in a shape (#7533); in Path
mode the operation applies to the subpath added to a targeted vector mask,
the selected path or the Work Path.
- engine: path.mergeShapeComponents for work, saved and layer paths, sharing
bake_path with the shape-layer command
- control/MCP: ui.set penMode and penPathOp
- original path-op icons, tooltip translated in every catalog
Closes#1397. Closes#7533.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Elliptical Marquee used a dashed circle and Quick Selection a brush
inside a dashed circular arc, so the two read alike. Photoshop draws the
marquee as a horizontal ellipse and Quick Selection as a brush in an
upright dashed rounded C. New original ellipse-dashed.svg; quick-selection.svg
redrawn; tests check the ellipse is wider than tall and the C runs down
the left edge.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The Russian catalog passed `cargo xtask i18n-coverage` (100% of measured keys)
but lacked the runtime-only labels the other catalogs already carry, so they
showed in English: filter and adjustment parameter names and choices, gallery
names, Camera Raw panels (Balance/Clarity/Dehaze/Color Mixer/Texture/…),
History/Layers/paths/channels menu labels, metadata and File Info fields,
System Info and hardware status lines, rasterize prompts, composed status
templates and dialog text.
All of them are translated (1,229 keys added; the catalog is now 4,227 keys
against upstream's 2,998), written from the meaning of the English labels and
reusing the vocabulary the catalog already uses (Highlights → Света,
Midtones → Полутона, Feather → Растушёвка, Pattern → узор). Filter and gallery
names are aligned with the menu labels already in the catalog so a filter never
reads two ways (Texturizer → Текстуризатор, Unsharp Mask → Нерезкое
маскирование, Shape Blur → Размытие по фигуре, …).
Tests: `russian_covers_generated_filter_options_and_gallery_names`
(filter_dialog.rs, the Italian/Korean/Spanish check) and
`russian_dynamic_status_hardware_and_dialog_labels_are_translated` (i18n/mod.rs).
Docs: docs/localization-ru.md (terminology), localization-parity, gaps G13,
ROADMAP, ATTRIBUTION and LICENSE-translations.
Validated on a rebase onto upstream/main: `cargo test -p photocraft-ui-egui
--lib` 2,998 passed / 0 failed; clippy clean (the only lint is a pre-existing
`nonminimal_bool` in canvas.rs, untouched here and present on upstream main);
`xtask layers` OK; `xtask wasm` OK; `xtask i18n-coverage` ru 1,863 / 1,863;
offscreen `snapshot` in Russian checked.
photocraft_algo::faces::detect finds faces in an RGBA image with a score, a box and five landmarks, through a pure-Rust port of libfacedetection's YuNet network (Shiqi Yu, BSD-3-Clause; licence, NOTICE and ATTRIBUTION rows included). The weights are the library's, converted to half precision (107 KB), parsed defensively. image.detectFaces reports the document's faces to scripts and agents; it is read-only with no history step and no menu entry. The network is compiled out of the browser build, where the command reports itself unavailable. Head outputs are pinned against the C++ reference.
Part of #3603.
The font menu gains Photoshop's local font library and filters (everything but
Adobe Fonts):
- Favourites: a star on every row (never picks the font) and a favourites-only
filter. Kept in the preferences (type.favoriteFonts).
- Recent fonts: up to five, most recent first, above a divider. Wires the dead
Preferences > Type > Recent Fonts (now 0..5, default 5; older saved values
are capped on load).
- Class list: All Classes, Serif, Slab Serif, Sans Serif, Script, Monospace,
Handwritten, Blackletter, Decorative, read from each font's OS/2
sFamilyClass, PANOSE and post tables (photocraft_text::font_class), else its
name. Fonts that state nothing stay unclassified.
- Show Variable Fonts, Show Similar Fonts (PANOSE/class/weight distance to the
current font) and Clear All; the class list collapses with «.
- Each row: style expander (">") that picks a family in a given style, and an
O / TT / VAR format badge.
- A preview at the top sets the type layer's own text (or the selection being
typed) in the font under the pointer.
- The search field and filters stay fixed while only the list scrolls, and the
search field lines up with the font list.
Commands: type.font.favorite, type.font.noteRecent, type.font.clearRecent,
type.font.library. Two original icons (font-similar, font-variable).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Type tool's options bar now has Photoshop's Create warped text button
after the text colour swatch. It opens the same Warp Text dialog as
Type > Warp Text... for the selected type layers (or the layer being
edited), and is greyed when there is no type layer to warp.
- assets/icons/text-warp.svg: original glyph (a T above a bowed arc) on
Lucide's 24 px grid and stroke; listed in ATTRIBUTION.md.
- The tooltip is translated in all 20 catalogs, reusing each language's
existing "Create Warped Text" wording (new for Russian).
Test: options_bar_warp_button_warps_the_selected_type_layers.
Co-Authored-By: Claude
Quick Selection reused the Ellipse Marquee's dashed circle. It now has a
distinct glyph: Lucide's brush with a dashed selection arc around the
bristles (Photoshop's Quick Selection mark). A rasterized test asserts
the two icons read as distinct and that the arc actually renders.
Co-authored-by: highperfocused <highperfocused@pm.me>