WIP - Add circle crop mask support#79393
Conversation
|
Size Change: +960 B (+0.01%) Total Size: 7.5 MB 📦 View Changed
|
| * | ||
| * @return array | ||
| */ | ||
| protected function get_edit_media_item_args() { |
There was a problem hiding this comment.
This is vibed coded as I wanted to test the flow first before doing it the right way. If it's a good direction, we'll do it with a more staggered approach.
3486e5e to
a63aeb2
Compare
| * @param WP_REST_Request $request Full details about the request. | ||
| * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. | ||
| */ | ||
| public function edit_media_item( $request ) { |
There was a problem hiding this comment.
non-mask request
→ parent::edit_media_item( original request )
→ done
circle mask request
→ strip mask modifier
→ parent::edit_media_item( request without mask )
→ Core creates unmasked edited attachment files
→ Gutenberg creates masked PNG replacement
→ delete Core-created unmasked files for that new attachment
→ regenerate metadata for PNG
509d976 to
236386f
Compare
| * @param WP_REST_Request $request Full details about the request. | ||
| * @return bool Whether the request has a circle mask modifier. | ||
| */ | ||
| protected function gutenberg_has_circle_mask_modifier( $request ) { |
There was a problem hiding this comment.
Maybe could be done inline too. Pretty chunky in there though.
|
Flaky tests detected in 236386f. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/28007715228
|
236386f to
21c22f7
Compare
21c22f7 to
792717d
Compare
| * @param array $args Test arguments. | ||
| * @return bool Whether this editor is supported. | ||
| */ | ||
| public static function test( $args = array() ) { |
There was a problem hiding this comment.
This function is oddly named for a public function.
I see there's a precendent: https://github.com/WordPress/wordpress-develop/blob/260fcbea3475459052c3ed3338c880a4d365ff5f/src/wp-includes/class-wp-image-editor-gd.php#L41
| /** | ||
| * Minimal disposable helper for mask argument validation. | ||
| */ | ||
| class Gutenberg_Image_Editor_Mask { |
There was a problem hiding this comment.
Just to confirm, this is a GB only helper. Maybe it could be a function, and named _gutenberg_something... and given a @private annotation?
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. |
| 'title' => __( 'Mask', 'gutenberg' ), | ||
| 'properties' => array( |
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