WIP - Add circle crop mask support#79393
Draft
ramonjd wants to merge 7 commits into
Draft
Conversation
|
Size Change: +1.07 kB (+0.01%) Total Size: 7.61 MB 📦 View Changed
|
ramonjd
commented
Jun 22, 2026
3486e5e to
a63aeb2
Compare
ramonjd
commented
Jun 22, 2026
509d976 to
236386f
Compare
ramonjd
commented
Jun 23, 2026
|
Flaky tests detected in aa3ae8a. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/28421361712
|
21c22f7 to
792717d
Compare
ramonjd
commented
Jun 26, 2026
76 tasks
Contributor
There was a problem hiding this comment.
Pull request overview
Adds MVP/POC support for circular image crops in the Media Editor, spanning UI/state updates in packages/media-editor and a WordPress REST /edit compatibility layer that can apply a circular mask and output PNG to preserve transparency.
Changes:
- Introduces a
cropShapeoption (rectangle/circle) with undo/history integration and “dirty” tracking. - Adds a circular stencil UI (edge handles + circular overlay styling) and exposes shape selection in the Crop panel and mobile/toolbar controls.
- Extends the attachments
/editflow with an experimentalmaskmodifier and registers mask-capable image editors (Imagick/GD) to produce circular PNG outputs.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/media-editor/src/state/use-media-editor-state.ts | Adds setCropShape controller API and includes crop shape in dirty tracking. |
| packages/media-editor/src/state/types.ts | Defines CropShape and adds cropShape to CropOptionsSlice + action types. |
| packages/media-editor/src/state/test/use-media-editor-state.ts | Adds coverage for undo/dirty behavior when switching crop shape. |
| packages/media-editor/src/state/index.ts | Re-exports CropShape type. |
| packages/media-editor/src/state/composite-reducer.ts | Implements SET_CROP_SHAPE handling and includes crop shape in equality checks. |
| packages/media-editor/src/image-editor/react/components/stencils/test/circle-stencil.tsx | Adds unit test ensuring circle stencil uses edge handles (not corners). |
| packages/media-editor/src/image-editor/react/components/stencils/rectangle-stencil.tsx | Adds internal props to support circle styling and edge-handle locking. |
| packages/media-editor/src/image-editor/react/components/stencils/circle-stencil.tsx | Implements circle stencil by composing RectangleStencil with square constraints. |
| packages/media-editor/src/image-editor/react/components/index.ts | Exports CircleStencil. |
| packages/media-editor/src/image-editor/react/components/cropper.tsx | Adds stencilShape support and enforces square constraints for circle crops. |
| packages/media-editor/src/image-editor/react/components/cropper.scss | Adds circular overlay styling (grid/dimming/stencil border radius). |
| packages/media-editor/src/image-editor/index.ts | Re-exports CircleStencil from the package surface. |
| packages/media-editor/src/image-editor/core/test/stencil-math.ts | Adds test coverage for locked edge-handle resizing behavior. |
| packages/media-editor/src/image-editor/core/stencil-math.ts | Adds computeLockedEdgeResizeRect and routes edge handles through it. |
| packages/media-editor/src/components/media-editor/use-save-media-editor.ts | Appends mask modifier when cropShape is circle. |
| packages/media-editor/src/components/media-editor/use-crop-options.ts | Exposes cropShape setters and resolves circle to a square aspect ratio. |
| packages/media-editor/src/components/media-editor/test/use-crop-options.tsx | Adds coverage for circle resolved aspect ratio and reset behavior. |
| packages/media-editor/src/components/media-editor/style.scss | Tweaks sidebar padding on small breakpoints. |
| packages/media-editor/src/components/media-editor/index.tsx | Wires crop shape into Crop panel and hides aspect ratio controls for circles. |
| packages/media-editor/src/components/media-editor-modal/build-modifiers.ts | Extends modifier union type to include mask. |
| packages/media-editor/src/components/media-editor-image-controls/test/index.tsx | Adds test coverage for toolbar crop-shape dropdown and circle behavior. |
| packages/media-editor/src/components/media-editor-image-controls/style.scss | Adjusts toolbar layout wrapping/centering for added controls. |
| packages/media-editor/src/components/media-editor-image-controls/index.tsx | Adds crop-shape dropdown and hides aspect ratio dropdown for circle crops. |
| packages/media-editor/src/components/media-editor-crop-panel/test/index.tsx | Adds test coverage for crop shape selection and circle-specific UI behavior. |
| packages/media-editor/src/components/media-editor-crop-panel/index.tsx | Adds shape toggle group and conditionally renders aspect ratio selector. |
| packages/media-editor/src/components/media-editor-canvas/index.tsx | Passes circle stencil + stencilShape to the Cropper when shape is circle. |
| lib/media/class-gutenberg-rest-attachments-controller.php | Switches controller base to a mask-capable attachments controller. |
| lib/compat/wordpress-7.1/image-editor-mask.php | Registers mask-capable Gutenberg image editors via wp_image_editors filter. |
| lib/compat/wordpress-7.1/image-editor-mask-validation.php | Adds validation/normalization helper for mask arguments. |
| lib/compat/wordpress-7.1/class-gutenberg-rest-attachments-controller-with-mask.php | Adds mask modifier schema and custom /edit flow to apply mask + PNG output. |
| lib/compat/wordpress-7.1/class-gutenberg-rest-attachments-controller-7-1.php | Updates 7.1 controller to inherit mask-capable base. |
| lib/compat/wordpress-7.1/class-gutenberg-image-editor-imagick.php | Adds Imagick editor subclass implementing mask() for circle cropping. |
| lib/compat/wordpress-7.1/class-gutenberg-image-editor-gd.php | Adds GD editor subclass implementing mask() for circle cropping. |
2c159e3 to
c8cd436
Compare
- Scope the mask image-editor filter to the edit request instead of swapping the global editor site-wide; load its helper from load.php. - Remove the dead legacy-modifier branch and inline the circle-mask request check. - Use a scanline fill for the GD circle mask (O(height) instead of O(width*height) per-pixel writes). - Return a status array from the Imagick mask error. - Let Cropper own the circle 1:1 ratio; drop the redundant canvas branch. - Clarify the circle crop help text. - Add PHP tests for mask validation, edit schema, GD masking, and the mask/non-mask edit routing.
Instead of unconditionally forcing PNG, honor the site's image_editor_output_format choice when it can hold an alpha channel (WebP/AVIF) and fall back to PNG otherwise. The format is forced for the save so a site filter cannot remap it back to an opaque format and discard the mask. - Move the format decision out of the editor mask() methods, which now mutate pixels only like the other transforms. - Drop the redundant Imagick setImageFormat and its test() gate entry. - Add a test covering the alpha-capable (WebP) negotiation path.
Comment on lines
+42
to
+66
| $args['modifiers']['items']['oneOf'][] = array( | ||
| 'title' => __( 'Mask', 'gutenberg' ), | ||
| 'type' => 'object', | ||
| 'properties' => array( | ||
| 'type' => array( | ||
| 'description' => __( 'Mask type.', 'gutenberg' ), | ||
| 'type' => 'string', | ||
| 'enum' => array( 'mask' ), | ||
| ), | ||
| 'args' => array( | ||
| 'description' => __( 'Mask arguments.', 'gutenberg' ), | ||
| 'type' => 'object', | ||
| 'required' => array( | ||
| 'shape', | ||
| ), | ||
| 'properties' => array( | ||
| 'shape' => array( | ||
| 'description' => __( 'Mask shape.', 'gutenberg' ), | ||
| 'type' => 'string', | ||
| 'enum' => array( 'circle' ), | ||
| ), | ||
| ), | ||
| ), | ||
| ), | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Adds MVP support for circular crops in the media editor. At the moment its state is MVP/POC to guide direction.
Kapture.2026-06-26.at.14.26.45.mp4
Backport PR here: WordPress/wordpress-develop#12327
Testing Instructions