Layer Management
Relevant source files
The following files were used as context for generating this wiki page:
- src/app/script/app/services/layer-service.ts
- src/app/script/klecks/ui/tool-tabs/layers-ui/layers-ui.ts
- src/app/script/klecks/canvas/kl-canvas.ts
- src/app/script/app/kl-app.ts
- src/app/script/klecks/ui/tool-tabs/layers-ui/layer-item.ts
- src/app/script/klecks/ui/components/procreate/utility-side-bar.ts
- src/app/script/canvaskit/canvaskit-compositor.ts
Layer Management is a core system in Rocreate responsible for handling the lifecycle, organization, and visual compositing of image layers. It enables non-destructive editing by stacking multiple independent canvases that support individual properties such as opacity, visibility, and blending modes. The system coordinates between low-level canvas manipulation, historical state tracking (Undo/Redo), and complex UI representations.
The architecture follows a modular approach where the KlCanvas class serves as the central data structure, while the LayersUi and specialized Procreate-style components provide interactive controls. Integration with CanvasKit allows for GPU-accelerated compositing of these layers, significantly improving performance on high-resolution projects.
Core Architecture and Data Structures
The system represents layers as objects containing both metadata and rendering contexts. Every layer is associated with a unique ID and a 2D canvas context for pixel data.
Layer Data Model
Each layer is defined by the TKlCanvasLayer type, which includes parameters for compositing and state management.
| Field | Type | Description |
|---|---|---|
id | TLayerId | Unique identifier used for history tracking and mapping. |
name | string | User-defined label for the layer. |
canvas | HTMLCanvasElement | The actual buffer holding pixel data. |
opacity | number | Alpha value ranging from 0 to 1. |
isVisible | boolean | Determines if the layer is rendered in the stack. |
mixModeStr | TMixMode | The blending mode (e.g., 'multiply', 'screen'). |
isClippingMask | boolean | If true, restricts rendering to the alpha channel of the layer below. |
Sources: src/app/script/klecks/canvas/kl-canvas.ts:71-82, src/app/script/klecks/kl-types.ts
Component Relationships
The following diagram illustrates how the layer management components interact within the application.
The relationship between the application controller, the data management layer, and the rendering engine.
Sources: src/app/script/app/kl-app.ts:241-280, src/app/script/klecks/ui/tool-tabs/layers-ui/layers-ui.ts:165-200
Layer Operations and History Integration
Operations on layers are mediated through the KlCanvas class. To ensure data consistency across Undo/Redo actions, every mutation (adding, removing, or reordering) is recorded in KlHistory.
Dynamic Layer Limits
Unlike legacy systems with fixed limits, Rocreate calculates the maximum number of layers dynamically based on the available memory budget (defaulting to 1.5GB) and the canvas dimensions.
export function calculateMaxLayers(width: number, height: number): number {
const bytesPerLayer = width * height * 4;
const availableForLayers = LAYER_MEMORY_BUDGET * 0.7;
const calculatedMax = Math.floor(availableForLayers / bytesPerLayer);
return Math.max(MIN_LAYERS, Math.min(ABSOLUTE_MAX_LAYERS, calculatedMax));
}
Sources: src/app/script/klecks/canvas/kl-canvas.ts:50-65
History-Aware Transformations
When a layer is moved or modified, KlCanvas pushes a THistoryEntryDataComposed object to the history stack. This includes a layerMap that updates indices or pixel tiles.
Sequence of events during a layer reordering operation.
Sources: src/app/script/klecks/canvas/kl-canvas.ts:404-418, src/app/script/klecks/ui/tool-tabs/layers-ui/layers-ui.ts:474-479
Rendering and Compositing
Rocreate utilizes a dual-rendering approach. While individual layers are drawn using standard Canvas 2D contexts for compatibility, the final compositing of the stack is handled by CanvasKitCompositor for GPU acceleration.
Clipping Masks and Blending
The compositor handles complex Procreate-style clipping masks. If a layer is marked as a clipping mask, it renders only within the alpha boundaries of the layer immediately beneath it in the stack.
- Standard Layers: Drawn using the specified
mixModeStr. - Clipping Stacks: The compositor groups the base layer and all subsequent clipping masks, applying
SrcATopblending to the masks within the group. - Opacity Handling: Opacity is applied at the group level or individual layer level depending on the stack structure.
Sources: src/app/script/canvaskit/canvaskit-compositor.ts:155-205, src/app/script/klecks/canvas/kl-canvas.ts:79-81
User Interface and Interaction
The UI is split between a standard "Classic" sidebar and a "Procreate-style" minimalist interface.
Layers UI Component
The LayersUi class manages the main layer list, supporting:
- Multi-Selection: Users can select multiple layers using Shift or Ctrl keys for bulk operations like merging or deletion.
- Drag-and-Drop Reordering: Handled by the
LayerDragControllerto update the visual stack and the underlying data model. - Thumbnail Previews: Real-time generation of layer content previews, including a "large thumb" preview on hover or drag.
Sources: src/app/script/klecks/ui/tool-tabs/layers-ui/layers-ui.ts:285-340, src/app/script/klecks/ui/tool-tabs/layers-ui/layers-ui.ts:510-530
Utility Side Bar (Procreate Mode)
In Procreate mode, the UtilitySideBar provides a condensed view of the layers, showing alpha lock indicators and quick-action buttons for adding or duplicating layers.
| Feature | Implementation | Source |
|---|---|---|
| Alpha Lock | alphaLockManager.isLocked(id) | src/app/script/klecks/ui/components/procreate/utility-side-bar.ts:145 |
| Layer Addition | klCanvas.addLayer(activeLayerIndex) | src/app/script/app/kl-app.ts:1175 |
| Quick Thumbnails | 32x32 canvas render of layer context | src/app/script/klecks/ui/components/procreate/utility-side-bar.ts:160 |
Summary
Layer Management in Rocreate is a high-performance system that bridges the gap between flexible UI interactions and robust graphics rendering. By integrating a dynamic memory-based layer limit and GPU-accelerated compositing via CanvasKit, it provides a professional-grade environment for digital painting. All state changes are strictly tracked through a tile-based history system, ensuring that complex layer stacks remain performant and fully reversible.