Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
brush_profile.h
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21#include "iop/drawlayer/brush.h"
22
23#include <math.h>
24
30static inline float dt_drawlayer_brush_profile_clamp01(const float v)
31{
32 return fminf(fmaxf(v, 0.0f), 1.0f);
33}
34
36static inline float dt_drawlayer_brush_transition_profile_eval(const int shape, const float t, const float inv_t)
37{
38 switch(shape)
39 {
41 return inv_t * inv_t;
43 {
44 const float smooth = t * t * (3.0f - 2.0f * t);
45 return 1.0f - smooth;
46 }
48 default:
49 return inv_t;
50 }
51}
52
54static inline float dt_drawlayer_brush_transition_mass_primitive_eval(const int shape, const float u,
55 const float inner, const float w,
56 const float base)
57{
58 switch(shape)
59 {
61 {
62 const float q_u = 0.5f * u * u - (2.0f / 3.0f) * u * u * u + 0.25f * u * u * u * u;
63 const float q_i = 0.5f * inner * inner - (2.0f / 3.0f) * inner * inner * inner
64 + 0.25f * inner * inner * inner * inner;
65 return base + (q_u - q_i) / (w * w);
66 }
68 {
69 const float s = dt_drawlayer_brush_profile_clamp01((u - inner) / w);
70 const float s2 = s * s;
71 const float s3 = s2 * s;
72 const float s4 = s2 * s2;
73 const float s5 = s4 * s;
74 const float delta = w * (inner * (s - s3 + 0.5f * s4)
75 + w * (0.5f * s2 - 0.75f * s4 + 0.4f * s5));
76 return base + delta;
77 }
79 default:
80 {
81 const float l_u = 0.5f * u * u - (1.0f / 3.0f) * u * u * u;
82 const float l_i = 0.5f * inner * inner - (1.0f / 3.0f) * inner * inner * inner;
83 return base + (l_u - l_i) / w;
84 }
85 }
86}
87
93static inline float dt_drawlayer_brush_profile_eval(const dt_drawlayer_brush_dab_t *dab, const float norm2)
94{
95 if(!dab || norm2 >= 1.0f) return 0.0f;
96
98 {
99 const float radius = sqrtf(norm2);
100 if(radius < 0.5f) return 1.0f - 6.0f * norm2 + 6.0f * norm2 * radius;
101 const float inv_r = 1.0f - radius;
102 return 2.0f * inv_r * inv_r * inv_r;
103 }
104
105 const float hardness = dt_drawlayer_brush_profile_clamp01(dab->hardness);
106 if(hardness >= 1.0f - 1e-6f) return 1.0f;
107
108 const float min_inner = 0.5f / fmaxf(dab->radius, 0.5f);
109 const float inner = fmaxf(hardness, dt_drawlayer_brush_profile_clamp01(min_inner));
110 const float radius = sqrtf(norm2);
111 if(radius <= inner) return 1.0f;
112
113 const float t = dt_drawlayer_brush_profile_clamp01((radius - inner) / fmaxf(1.0f - inner, 1e-6f));
115}
116
121static inline float dt_drawlayer_brush_mass_primitive_eval(const dt_drawlayer_brush_dab_t *dab, const float u_in)
122{
123 if(!dab) return 0.0f;
124 const float u = dt_drawlayer_brush_profile_clamp01(u_in);
125 if(u <= 0.0f) return 0.0f;
126
128 {
129 if(u <= 0.5f) return 0.5f * u * u - 1.5f * u * u * u * u + 1.2f * u * u * u * u * u;
130 const float u2 = u * u;
131 const float u3 = u2 * u;
132 const float u4 = u2 * u2;
133 const float u5 = u4 * u;
134 return u2 - 2.0f * u3 + 1.5f * u4 - 0.4f * u5 - 0.0125f;
135 }
136
137 const float hardness = dt_drawlayer_brush_profile_clamp01(dab->hardness);
138 if(hardness >= 1.0f - 1e-6f) return 0.5f * u * u;
139 const float min_inner = 0.5f / fmaxf(dab->radius, 0.5f);
140 const float inner = fmaxf(hardness, dt_drawlayer_brush_profile_clamp01(min_inner));
141 if(u <= inner) return 0.5f * u * u;
142 const float w = fmaxf(1.0f - inner, 1e-6f);
143 const float base = 0.5f * inner * inner;
144 return dt_drawlayer_brush_transition_mass_primitive_eval(dab->shape, u, inner, w, base);
145}
Dab-level brush rasterization API for drawlayer.
@ DT_DRAWLAYER_BRUSH_SHAPE_SIGMOIDAL
Definition brush.h:44
@ DT_DRAWLAYER_BRUSH_SHAPE_GAUSSIAN
Definition brush.h:42
@ DT_DRAWLAYER_BRUSH_SHAPE_LINEAR
Definition brush.h:41
@ DT_DRAWLAYER_BRUSH_SHAPE_QUADRATIC
Definition brush.h:43
static float dt_drawlayer_brush_profile_eval(const dt_drawlayer_brush_dab_t *dab, const float norm2)
Evaluate normalized brush profile at squared normalized radius.
Definition brush_profile.h:93
static float dt_drawlayer_brush_mass_primitive_eval(const dt_drawlayer_brush_dab_t *dab, const float u_in)
Evaluate radial mass primitive from center to normalized radius u_in.
Definition brush_profile.h:121
static float dt_drawlayer_brush_profile_clamp01(const float v)
Clamp scalar value to [0, 1].
Definition brush_profile.h:30
static float dt_drawlayer_brush_transition_mass_primitive_eval(const int shape, const float u, const float inner, const float w, const float base)
Evaluate integrated mass primitive of transition zone by shape.
Definition brush_profile.h:54
static float dt_drawlayer_brush_transition_profile_eval(const int shape, const float t, const float inv_t)
Evaluate normalized edge-falloff transition profile by shape.
Definition brush_profile.h:36
const float delta
Definition colorspaces_inline_conversions.h:722
const int t
Definition iop_profile.h:227
static const float v
Definition iop_profile.h:223
Fully resolved input dab descriptor.
Definition brush.h:66
float radius
Definition brush.h:71
int shape
Definition brush.h:84
float hardness
Definition brush.h:81