Skip to content

fix(crop-rotate): honor initAspectRatio for the initial oval cropper (#828)#839

Merged
hm21 merged 1 commit into
stablefrom
fix/828-oval-init-aspect-ratio
Jun 27, 2026
Merged

fix(crop-rotate): honor initAspectRatio for the initial oval cropper (#828)#839
hm21 merged 1 commit into
stablefrom
fix/828-oval-init-aspect-ratio

Conversation

@hm21

@hm21 hm21 commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Fixes #828

Problem

Opening ProImageEditor directly in the oval cropper with a fixed initAspectRatio (e.g. 1.0) renders and exports an ellipse stretched to the full image bounds for any non-square image, instead of a circle.

Root cause

The main editor initializes its history with an empty transform that only carries the crop mode:

transformConfigs: TransformConfigs.empty().copyWith(
  cropMode: cropRotateEditorConfigs.initialCropMode,
),

initAspectRatio is never consulted for the initial state, so every consumer that derives the oval mask falls back to the full image aspect ratio:

  • the main editor capture overlay (main_editor_interactive_content.dart)
  • the shared layer-stack overlay (layer_stack.dart)
  • the export clip (CutOutsideArea in transformed_content_generator.dart)

If the user exports without first entering the crop sub-editor, the result is an ellipse.

Fix

Add CropRotateEditorConfigs.initialOvalCropAspectRatio, which returns the fixed ratio for the initial oval state and null when the full image should be used (free -1, original 0.0, or a non-oval initial crop mode). All three consumers now use it as the fallback before the full-image aspect ratio, and CutOutsideArea builds a centered crop rect of that ratio for the initial oval mask.

Result: a 1.0 ratio renders/exports a circle; free (-1) and original (0.0) ratios keep the previous full-image behavior. The fix is scoped to the oval cropper so rectangular crops are unaffected (they still only crop once the user confirms in the crop sub-editor).

Tests

Added cut_outside_area_test.dart covering the new getter (oval+fixed ratio → ratio; free/original/rectangular → null) and CutOutsideArea.getClip (non-square image → centered square for 1:1, full bounds without a fixed ratio, width-fit for a wide ratio).

…828)

Opening the editor directly in CropMode.oval with a fixed initAspectRatio
(e.g. 1.0) rendered and exported an ellipse stretched to the full image
bounds for non-square images. The main editor initializes its history with
an empty transform that only carries the crop mode, so the initial state
never consulted initAspectRatio and every consumer fell back to the full
image aspect ratio.

Add CropRotateEditorConfigs.initialOvalCropAspectRatio, which exposes the
fixed ratio for the initial oval state (null for free/original/non-oval),
and use it in the three places that derive the initial mask: the main
editor capture overlay, the shared layer-stack overlay and the export clip
(CutOutsideArea). A 1:1 ratio now produces a circle; free (-1) and original
(0.0) ratios keep the previous full-image behavior.
@hm21 hm21 merged commit 5517554 into stable Jun 27, 2026
1 check passed
@hm21 hm21 deleted the fix/828-oval-init-aspect-ratio branch June 27, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: initAspectRatio: 1.0 with initialCropMode: CropMode.oval renders/exports an ellipse instead of a circle in the main editor

1 participant