Skip to content

Comments

Add support for gradients with midpoints and add draggable diamonds to the color picker dialog#3813

Merged
Keavon merged 5 commits intomasterfrom
gradient-midpoints
Feb 24, 2026
Merged

Add support for gradients with midpoints and add draggable diamonds to the color picker dialog#3813
Keavon merged 5 commits intomasterfrom
gradient-midpoints

Conversation

@Keavon
Copy link
Member

@Keavon Keavon commented Feb 23, 2026

capture_39_.mp4

Closes #3815

@Keavon Keavon mentioned this pull request Feb 23, 2026
6 tasks
@Keavon Keavon requested a review from TrueDoctor February 23, 2026 14:01
@gemini-code-assist
Copy link

Summary of Changes

Hello @Keavon, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the gradient system by introducing support for midpoints, which allows for more nuanced and customizable color blending. The core data structures for gradients have been redesigned to accommodate this feature, alongside comprehensive updates to the frontend UI for interactive control. Backend rendering and interpolation logic have been adapted to correctly interpret and display these enhanced gradients, ensuring a consistent and powerful user experience.

Highlights

  • Gradient Midpoint Support: Introduced the concept of midpoints to gradients, allowing for non-linear color transitions between stops. This significantly enhances the expressiveness and control over gradient appearance.
  • Refactored GradientStops Structure: The GradientStops data structure was refactored to store position, midpoint, and color as separate vectors, improving data organization and enabling the new midpoint functionality. A migration path for old gradient data was also implemented.
  • Interactive Midpoint UI: Added new UI elements to the SpectrumInput component, allowing users to visually manipulate gradient midpoints directly within the color picker. This includes dragging midpoints and double-clicking to reset them.
  • WASM Integration for Gradient Interpolation: New WebAssembly functions (sampleInterpolatedGradient and evaluateGradientAtPosition) were added to efficiently calculate interpolated colors along a gradient, respecting the new midpoint values, for both rendering and UI feedback.
Changelog
  • .vscode/settings.json
    • Added 'a11y_no_static_element_interactions' to the ignored accessibility warnings.
  • editor/src/messages/layout/layout_message_handler.rs
    • Updated gradient parsing logic to correctly extract position, midpoint, and color data from incoming messages.
  • editor/src/messages/portfolio/document/data_panel/data_panel_message_handler.rs
    • Updated the identifier string for gradients to use the new len() method of GradientStops.
  • editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs
    • Imported the new GradientStop struct.
    • Modified USVG fill application to construct GradientStop objects with a default midpoint of 0.5.
  • editor/src/messages/tool/tool_messages/gradient_tool.rs
    • Imported GradientStops for use in the gradient tool.
    • Updated calculate_insertion to accept GradientStops directly.
    • Adjusted gradient stop manipulation logic to interact with the new position and color vectors.
    • Modified overlay rendering to correctly display gradient stops using the new structure.
    • Updated gradient fill setting to access color from the new color vector.
    • Adapted min/max position calculations to use the position vector.
    • Updated position remapping to modify the position vector directly.
    • Modified gradient stop iteration for dragging detection to use the new GradientStop iterator.
    • Updated test assertions to reflect the new GradientStop structure and access position and color fields.
  • frontend/src/components/floating-menus/ColorPicker.svelte
    • Imported MAX_MIDPOINT and MIN_MIDPOINT constants.
    • Added activeIndexIsMidpoint state to track if the active marker is a midpoint.
    • Updated selectedGradientColor to access color from the gradient.color array.
    • Modified setColor function to update the color array of the gradient.
    • Updated gradientActiveMarkerIndexChange to receive and set activeMarkerIsMidpoint.
    • Adjusted NumberInput for gradient stops to dynamically set value, min, and max based on whether the active marker is a position or a midpoint.
  • frontend/src/components/widgets/inputs/ColorInput.svelte
    • Updated transparency check for gradients to iterate over the color array.
  • frontend/src/components/widgets/inputs/SpectrumInput.svelte
    • Exported MIN_MIDPOINT and MAX_MIDPOINT constants.
    • Imported evaluateGradientAtPosition from WASM.
    • Updated event dispatcher type for activeMarkerIndexChange to include activeMarkerIsMidpoint.
    • Added activeMarkerIsMidpoint prop and internal state.
    • Added midpointRestore, activeMarkerIndexRestore, activeMarkerIsMidpointRestore, and midpointDragged states for midpoint interaction.
    • Modified markerPointerDown to set activeMarkerIsMidpoint to false and dispatch the new event type.
    • Added midpointPointerDown function to handle interaction with midpoint markers.
    • Added resetMidpoint function to reset a midpoint to 0.5.
    • Updated insertStop to use findLastIndex and findIndex on gradient.position, and to use evaluateGradientAtPosition for new stop color, inserting new midpoint and color values.
    • Modified deleteStop to handle midpoint resets or stop deletions based on activeMarkerIsMidpoint.
    • Updated deleteStopByIndex to remove elements from position, midpoint, and color arrays.
    • Added moveMidpoint function to handle dragging of midpoint markers.
    • Modified setPosition to accept an isMidpoint parameter and update the correct array (position or midpoint).
    • Added toMarkers and toMidpoints helper functions for rendering.
    • Updated abortDrag to restore midpoint values if a midpoint was being dragged.
    • Modified onPointerMove to call moveMidpoint or moveMarker based on activeMarkerIsMidpoint.
    • Added new midpoint-track layout row and SVG elements for rendering midpoint markers.
    • Updated marker rendering to conditionally apply active class based on activeMarkerIsMidpoint.
    • Added SCSS styling for the new midpoint track and markers.
  • frontend/src/messages.ts
    • Imported sampleInterpolatedGradient from WASM.
    • Refactored Gradient class to use separate position, midpoint, and color arrays.
    • Updated Gradient constructor to accept separate arrays.
    • Modified toLinearGradientCSS and toLinearGradientCSSNoAlpha to use sampleInterpolatedGradient WASM function.
    • Updated firstColor and lastColor to access colors from the color array.
    • Removed atIndex, colorAtIndex, and positionAtIndex methods from Gradient.
    • Removed lerp method from Color class.
    • Updated ColorInput transformation logic to correctly deserialize the new Gradient structure with separate position, midpoint, and color arrays.
  • frontend/vite.config.ts
    • Added 'a11y_no_static_element_interactions' to the list of suppressed accessibility warnings.
  • frontend/wasm/src/editor_api.rs
    • Imported GradientStops struct.
    • Added sample_interpolated_gradient WASM function to generate CSS gradient strings from gradient stops, including midpoints.
    • Added evaluate_gradient_at_position WASM function to evaluate a gradient's color at a specific position, considering midpoints.
  • node-graph/libraries/no-std-types/src/color/color_types.rs
    • Added to_rgba_hex_srgb_from_gamma method to Color for generating 8-character RGBA hex strings from gamma space colors.
  • node-graph/libraries/rendering/src/render_ext.rs
    • Updated gradient rendering to use interpolated_samples() from GradientStops for SVG stop generation.
  • node-graph/libraries/rendering/src/renderer.rs
    • Updated Peniko gradient rendering to use interpolated_samples() from GradientStops.
    • Updated SVG gradient rendering in Table<GradientStops> to use interpolated_samples().
    • Modified Table<GradientStops> rendering to access the first color from the color vector.
  • node-graph/libraries/vector-types/src/gradient.rs
    • Refactored GradientStops from a tuple vector to a struct containing separate position, midpoint, and color vectors.
    • Added GradientStop struct to represent individual gradient stops.
    • Implemented serde::Deserialize for GradientStops to handle both new and old data formats, providing a migration path.
    • Updated Hash implementation for GradientStops to include midpoint values.
    • Modified Default implementation for GradientStops to initialize with default position, midpoint, and color values.
    • Removed IntoIterator, Index, Deref, and DerefMut implementations for GradientStops's internal vector.
    • Added apply_midpoint helper function for non-linear interpolation.
    • Introduced GradientStopsIter for iterating over GradientStop objects.
    • Implemented IntoIterator for &GradientStops and GradientStops to return GradientStop iterators.
    • Added new, len, is_empty, remove, and pop methods to GradientStops.
    • Updated evaluate method in GradientStops to use apply_midpoint for color interpolation.
    • Modified sort method in GradientStops to sort all three vectors based on position.
    • Updated reversed method in GradientStops to correctly reverse positions, midpoints, and colors.
    • Modified map_colors in GradientStops to operate on the color vector.
    • Added interpolated_samples method to GradientStops to generate a series of samples for rendering, approximating midpoint curves.
  • node-graph/libraries/vector-types/src/lib.rs
    • Exported the new GradientStop struct.
  • node-graph/libraries/vector-types/src/vector/style.rs
    • Updated Fill::color() to access the first color from stops.color and handle empty stops.
    • Modified Fill::lerp() for gradient blending to iterate over GradientStop objects and construct new GradientStops.
    • Updated Fill::is_opaque() for gradients to check opacity of colors in the stops.color vector.
  • node-graph/nodes/gstd/src/lib.rs
    • Exported the new GradientStop struct in the gradient module.
  • node-graph/nodes/raster/src/adjust.rs
    • Updated GradientStops::adjust to modify colors directly in the color vector.
  • node-graph/nodes/raster/src/blending_nodes.rs
    • Imported the new GradientStop struct.
    • Updated GradientStops::blend to collect positions from the position vector and construct new GradientStop objects.
Activity
  • The pull request introduces a new feature and includes comprehensive changes across multiple modules (editor, frontend, WASM, node-graph libraries) to support it.
  • The author, Keavon, has provided a GIF in the PR description demonstrating the new functionality, which is helpful for understanding the visual impact of the changes.
  • The PR is part of issue Better gradient support #2304, indicating it's a planned feature development.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for gradient midpoints, allowing for non-linear color interpolation between stops. The implementation involves a significant refactoring of the GradientStops data structure from an Array-of-Structs (AoS) to a Structure-of-Arrays (SoA) format to accommodate the new midpoint data. The review identified a few issues regarding floating-point comparisons and potential UX confusion in the color picker when a midpoint is selected. Overall, the changes are well-integrated across the backend, WASM bindings, and frontend components.

…ition and show both axis lines

Make color picker saturation-value color picking snap to original position and show both axis lines
@Keavon Keavon changed the title Add support for gradient with midpoints Add support for gradients with midpoints and add draggable diamonds to the color picker dialog Feb 24, 2026
@Keavon Keavon enabled auto-merge February 24, 2026 03:21
@Keavon Keavon disabled auto-merge February 24, 2026 03:21
@Keavon Keavon merged commit 691d965 into master Feb 24, 2026
5 checks passed
@Keavon Keavon deleted the gradient-midpoints branch February 24, 2026 03:21
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.

Midpoint controls between gradient stop markers

1 participant