consistent names, alphaFix 80char

This commit is contained in:
Ryan Oldenburg 2020-12-09 04:09:22 -06:00
parent 78b1dbab03
commit 1ad2f3e05f

View file

@ -69,42 +69,38 @@ proc `-`*(c: Color, v: float32): Color {.inline.} =
result.b = c.b - v result.b = c.b - v
result.a = c.a - v result.a = c.a - v
proc screen(Cb, Cs: float32): float32 {.inline.} = proc screen(backdrop, source: float32): float32 {.inline.} =
1 - (1 - Cb) * (1 - Cs) 1 - (1 - backdrop) * (1 - source)
proc hardLight(Cb, Cs: float32): float32 {.inline.} = proc hardLight(backdrop, source: float32): float32 {.inline.} =
if Cs <= 0.5: if source <= 0.5:
Cb * 2 * Cs backdrop * 2 * source
else: else:
screen(Cb, 2 * Cs - 1) screen(backdrop, 2 * source - 1)
proc softLight(a, b: float32): float32 {.inline.} = proc softLight(backdrop, source: float32): float32 {.inline.} =
## Pegtop ## Pegtop
(1 - 2 * b) * a ^ 2 + 2 * b * a (1 - 2 * source) * backdrop ^ 2 + 2 * source * backdrop
proc Lum(C: Color): float32 {.inline.} = proc Lum(C: Color): float32 {.inline.} =
0.3 * C.r + 0.59 * C.g + 0.11 * C.b 0.3 * C.r + 0.59 * C.g + 0.11 * C.b
proc ClipColor(C: Color): Color {.inline.} = proc ClipColor(C: var Color) {.inline.} =
let let
L = Lum(C) L = Lum(C)
n = min([C.r, C.g, C.b]) n = min([C.r, C.g, C.b])
x = max([C.r, C.g, C.b]) x = max([C.r, C.g, C.b])
var
C = C
if n < 0: if n < 0:
C = L + (((C - L) * L) / (L - n)) C = L + (((C - L) * L) / (L - n))
if x > 1: if x > 1:
C = L + (((C - L) * (1 - L)) / (x - L)) C = L + (((C - L) * (1 - L)) / (x - L))
return C
proc SetLum(C: Color, l: float32): Color {.inline.} = proc SetLum(C: Color, l: float32): Color {.inline.} =
let let d = l - Lum(C)
d = l - Lum(C)
result.r = C.r + d result.r = C.r + d
result.g = C.g + d result.g = C.g + d
result.b = C.b + d result.b = C.b + d
return ClipColor(result) ClipColor(result)
proc Sat(C: Color): float32 {.inline.} = proc Sat(C: Color): float32 {.inline.} =
max([C.r, C.g, C.b]) - min([C.r, C.g, C.b]) max([C.r, C.g, C.b]) - min([C.r, C.g, C.b])
@ -114,266 +110,249 @@ proc SetSat(C: Color, s: float32): Color {.inline.} =
if satC > 0: if satC > 0:
result = (C - min([C.r, C.g, C.b])) * s / satC result = (C - min([C.r, C.g, C.b])) * s / satC
proc alphaFix(Cb, Cs, mixed: Color): Color {.inline.} = proc alphaFix(backdrop, source, mixed: Color): Color =
let ab = Cb.a let
let As = Cs.a t0 = source.a * (1 - backdrop.a)
result.r = As * (1 - ab) * Cs.r + As * ab * mixed.r + (1 - As) * ab * Cb.r t1 = source.a * backdrop.a
result.g = As * (1 - ab) * Cs.g + As * ab * mixed.g + (1 - As) * ab * Cb.g t2 = (1 - source.a) * backdrop.a
result.b = As * (1 - ab) * Cs.b + As * ab * mixed.b + (1 - As) * ab * Cb.b
result.a = (Cs.a + Cb.a * (1.0 - Cs.a)) result.r = t0 * source.r + t1 * mixed.r + t2 * backdrop.r
result.g = t0 * source.g + t1 * mixed.g + t2 * backdrop.g
result.b = t0 * source.b + t1 * mixed.b + t2 * backdrop.b
result.a = (source.a + backdrop.a * (1.0 - source.a))
result.r /= result.a result.r /= result.a
result.g /= result.a result.g /= result.a
result.b /= result.a result.b /= result.a
proc blendDarkenFloat(Cb, Cs: float32): float32 {.inline.} = proc blendNormalFloats(backdrop, source: Color): Color {.inline.} =
min(Cb, Cs) result = source
result = alphaFix(backdrop, source, result)
proc blendMultiplyFloat(Cb, Cs: float32): float32 {.inline.} = proc blendDarkenFloats(backdrop, source: Color): Color {.inline.} =
Cb * Cs result.r = min(backdrop.r, source.r)
result.g = min(backdrop.g, source.g)
result.b = min(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendLinearBurnFloat(Cb, Cs: float32): float32 {.inline.} = proc blendMultiplyFloats(backdrop, source: Color): Color {.inline.} =
Cb + Cs - 1 result.r = backdrop.r * source.r
result.g = backdrop.g * source.g
result.b = backdrop.b * source.b
result = alphaFix(backdrop, source, result)
proc blendColorBurnFloat(Cb, Cs: float32): float32 {.inline.} = proc blendLinearBurnFloats(backdrop, source: Color): Color {.inline.} =
if Cb == 1: 1.0 result.r = backdrop.r + source.r - 1
elif Cs == 0: 0.0 result.g = backdrop.g + source.g - 1
else: 1.0 - min(1, (1 - Cb) / Cs) result.b = backdrop.b + source.b - 1
result = alphaFix(backdrop, source, result)
proc blendLightenFloat(Cb, Cs: float32): float32 {.inline.} = proc blendColorBurnFloats(backdrop, source: Color): Color {.inline.} =
max(Cb, Cs) proc blend(backdrop, source: float32): float32 {.inline.} =
if backdrop == 1:
1.0
elif source == 0:
0.0
else:
1.0 - min(1, (1 - backdrop) / source)
result.r = blend(backdrop.r, source.r)
result.g = blend(backdrop.g, source.g)
result.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendScreenFloat(Cb, Cs: float32): float32 {.inline.} = proc blendLightenFloats(backdrop, source: Color): Color {.inline.} =
screen(Cb, Cs) result.r = max(backdrop.r, source.r)
result.g = max(backdrop.g, source.g)
result.b = max(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendLinearDodgeFloat(Cb, Cs: float32): float32 {.inline.} = proc blendScreenFloats(backdrop, source: Color): Color {.inline.} =
Cb + Cs result.r = screen(backdrop.r, source.r)
result.g = screen(backdrop.g, source.g)
result.b = screen(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendColorDodgeFloat(Cb, Cs: float32): float32 {.inline.} = proc blendLinearDodgeFloats(backdrop, source: Color): Color {.inline.} =
if Cb == 0: 0.0 result.r = backdrop.r + source.r
elif Cs == 1: 1.0 result.g = backdrop.g + source.g
else: min(1, Cb / (1 - Cs)) result.b = backdrop.b + source.b
result = alphaFix(backdrop, source, result)
proc blendOverlayFloat(Cb, Cs: float32): float32 {.inline.} = proc blendColorDodgeFloats(backdrop, source: Color): Color {.inline.} =
hardLight(Cs, Cb) proc blend(backdrop, source: float32): float32 {.inline.} =
if backdrop == 0:
0.0
elif source == 1:
1.0
else:
min(1, backdrop / (1 - source))
result.r = blend(backdrop.r, source.r)
result.g = blend(backdrop.g, source.g)
result.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendHardLightFloat(Cb, Cs: float32): float32 {.inline.} = proc blendOverlayFloats(backdrop, source: Color): Color {.inline.} =
hardLight(Cb, Cs) result.r = hardLight(source.r, backdrop.r)
result.g = hardLight(source.g, backdrop.g)
result.b = hardLight(source.b, backdrop.b)
result = alphaFix(backdrop, source, result)
proc blendSoftLightFloat(Cb, Cs: float32): float32 {.inline.} = proc blendHardLightFloats(backdrop, source: Color): Color {.inline.} =
softLight(Cb, Cs) result.r = hardLight(backdrop.r, source.r)
result.g = hardLight(backdrop.g, source.g)
result.b = hardLight(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendDifferenceFloat(Cb, Cs: float32): float32 {.inline.} = proc blendSoftLightFloats(backdrop, source: Color): Color {.inline.} =
abs(Cb - Cs) result.r = softLight(backdrop.r, source.r)
result.g = softLight(backdrop.g, source.g)
result.b = softLight(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendExclusionFloat(Cb, Cs: float32): float32 {.inline.} = proc blendDifferenceFloats(backdrop, source: Color): Color {.inline.} =
Cb + Cs - 2 * Cb * Cs result.r = abs(backdrop.r - source.r)
result.g = abs(backdrop.g - source.g)
result.b = abs(backdrop.b - source.b)
result = alphaFix(backdrop, source, result)
proc blendNormalFloats(Cb, Cs: Color): Color {.inline.} = proc blendExclusionFloats(backdrop, source: Color): Color {.inline.} =
result = Cs proc blend(backdrop, source: float32): float32 {.inline.} =
result = alphaFix(Cb, Cs, result) backdrop + source - 2 * backdrop * source
result.r = blend(backdrop.r, source.r)
result.g = blend(backdrop.g, source.g)
result.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
proc blendDarkenFloats(Cb, Cs: Color): Color {.inline.} = proc blendColorFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendDarkenFloat(Cb.r, Cs.r) result = SetLum(source, Lum(backdrop))
result.g = blendDarkenFloat(Cb.g, Cs.g) result = alphaFix(backdrop, source, result)
result.b = blendDarkenFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendMultiplyFloats(Cb, Cs: Color): Color {.inline.} = proc blendLuminosityFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendMultiplyFloat(Cb.r, Cs.r) result = SetLum(backdrop, Lum(source))
result.g = blendMultiplyFloat(Cb.g, Cs.g) result = alphaFix(backdrop, source, result)
result.b = blendMultiplyFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendLinearBurnFloats(Cb, Cs: Color): Color {.inline.} = proc blendHueFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendLinearBurnFloat(Cb.r, Cs.r) result = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop))
result.g = blendLinearBurnFloat(Cb.g, Cs.g) result = alphaFix(backdrop, source, result)
result.b = blendLinearBurnFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendColorBurnFloats(Cb, Cs: Color): Color {.inline.} = proc blendSaturationFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendColorBurnFloat(Cb.r, Cs.r) result = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
result.g = blendColorBurnFloat(Cb.g, Cs.g) result = alphaFix(backdrop, source, result)
result.b = blendColorBurnFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendLightenFloats(Cb, Cs: Color): Color {.inline.} = proc blendMaskFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendLightenFloat(Cb.r, Cs.r) result = backdrop
result.g = blendLightenFloat(Cb.g, Cs.g) result.a = min(backdrop.a, source.a)
result.b = blendLightenFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendScreenFloats(Cb, Cs: Color): Color {.inline.} = proc blendSubtractMaskFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendScreenFloat(Cb.r, Cs.r) result = backdrop
result.g = blendScreenFloat(Cb.g, Cs.g) result.a = backdrop.a * (1 - source.a)
result.b = blendScreenFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendLinearDodgeFloats(Cb, Cs: Color): Color {.inline.} = proc blendIntersectMaskFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendLinearDodgeFloat(Cb.r, Cs.r) result = backdrop
result.g = blendLinearDodgeFloat(Cb.g, Cs.g) result.a = backdrop.a * source.a
result.b = blendLinearDodgeFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendColorDodgeFloats(Cb, Cs: Color): Color {.inline.} = proc blendExcludeMaskFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendColorDodgeFloat(Cb.r, Cs.r) result = backdrop
result.g = blendColorDodgeFloat(Cb.g, Cs.g) result.a = abs(backdrop.a - source.a)
result.b = blendColorDodgeFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendOverlayFloats(Cb, Cs: Color): Color {.inline.} = proc blendOverwriteFloats(backdrop, source: Color): Color {.inline.} =
result.r = blendOverlayFloat(Cb.r, Cs.r) source
result.g = blendOverlayFloat(Cb.g, Cs.g)
result.b = blendOverlayFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendHardLightFloats(Cb, Cs: Color): Color {.inline.} = proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA {.inline.} =
result.r = blendHardLightFloat(Cb.r, Cs.r) let
result.g = blendHardLightFloat(Cb.g, Cs.g) sa = source.a.int32
result.b = blendHardLightFloat(Cb.b, Cs.b) ba = backdrop.a.int32
result = alphaFix(Cb, Cs, result) t0 = sa * (255 - ba)
t1 = sa * ba
t2 = (255 - sa) * ba
proc blendSoftLightFloats(Cb, Cs: Color): Color {.inline.} = let
result.r = blendSoftLightFloat(Cb.r, Cs.r) r = t0 * source.r.int32 + t1 * mixed.r.int32 + t2 * backdrop.r.int32
result.g = blendSoftLightFloat(Cb.g, Cs.g) g = t0 * source.g.int32 + t1 * mixed.g.int32 + t2 * backdrop.g.int32
result.b = blendSoftLightFloat(Cb.b, Cs.b) b = t0 * source.b.int32 + t1 * mixed.b.int32 + t2 * backdrop.b.int32
result = alphaFix(Cb, Cs, result) a = sa + ba * (255 - sa) div 255
proc blendDifferenceFloats(Cb, Cs: Color): Color {.inline.} =
result.r = blendDifferenceFloat(Cb.r, Cs.r)
result.g = blendDifferenceFloat(Cb.g, Cs.g)
result.b = blendDifferenceFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendExclusionFloats(Cb, Cs: Color): Color {.inline.} =
result.r = blendExclusionFloat(Cb.r, Cs.r)
result.g = blendExclusionFloat(Cb.g, Cs.g)
result.b = blendExclusionFloat(Cb.b, Cs.b)
result = alphaFix(Cb, Cs, result)
proc blendColorFloats(Cb, Cs: Color): Color {.inline.} =
let mixed = SetLum(Cs, Lum(Cb))
alphaFix(Cb, Cs, mixed)
proc blendLuminosityFloats(Cb, Cs: Color): Color {.inline.} =
let mixed = SetLum(Cb, Lum(Cs))
alphaFix(Cb, Cs, mixed)
proc blendHueFloats(Cb, Cs: Color): Color {.inline.} =
let mixed = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
alphaFix(Cb, Cs, mixed)
proc blendSaturationFloats(Cb, Cs: Color): Color {.inline.} =
let mixed = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
alphaFix(Cb, Cs, mixed)
proc blendMaskFloats(target, blend: Color): Color {.inline.} =
result = target
result.a = min(target.a, blend.a)
proc blendSubtractMaskFloats(target, blend: Color): Color {.inline.} =
result = target
result.a = target.a * (1 - blend.a)
proc blendIntersectMaskFloats(target, blend: Color): Color {.inline.} =
result = target
result.a = target.a * blend.a
proc blendExcludeMaskFloats(target, blend: Color): Color {.inline.} =
result = target
result.a = abs(target.a - blend.a)
proc blendOverwriteFloats(target, blend: Color): Color {.inline.} =
result = blend
proc alphaFix(Cb, Cs, mixed: ColorRGBA): ColorRGBA {.inline.} =
let ab = Cb.a.int32
let As = Cs.a.int32
let r = As * (255 - ab) * Cs.r.int32 + As * ab * mixed.r.int32 + (255 - As) * ab * Cb.r.int32
let g = As * (255 - ab) * Cs.g.int32 + As * ab * mixed.g.int32 + (255 - As) * ab * Cb.g.int32
let b = As * (255 - ab) * Cs.b.int32 + As * ab * mixed.b.int32 + (255 - As) * ab * Cb.b.int32
let a = Cs.a.int32 + Cb.a.int32 * (255 - Cs.a.int32) div 255
if a == 0: if a == 0:
return return
else:
result.r = (r div a div 255).uint8
result.g = (g div a div 255).uint8
result.b = (b div a div 255).uint8
result.a = a.uint8
proc blendNormal(a, b: ColorRGBA): ColorRGBA = result.r = (r div a div 255).uint8
blendNormalFloats(a.color, b.color).rgba result.g = (g div a div 255).uint8
result.b = (b div a div 255).uint8
result.a = a.uint8
proc blendDarken(a, b: ColorRGBA): ColorRGBA = proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
blendDarkenFloats(a.color, b.color).rgba result = source
result = alphaFix(backdrop, source, result)
proc blendMultiply(a, b: ColorRGBA): ColorRGBA = proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
blendMultiplyFloats(a.color, b.color).rgba blendDarkenFloats(backdrop.color, source.color).rgba
proc blendLinearBurn(a, b: ColorRGBA): ColorRGBA = proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
blendLinearBurnFloats(a.color, b.color).rgba blendMultiplyFloats(backdrop.color, source.color).rgba
proc blendColorBurn(a, b: ColorRGBA): ColorRGBA = proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
blendColorBurnFloats(a.color, b.color).rgba blendLinearBurnFloats(backdrop.color, source.color).rgba
proc blendLighten(a, b: ColorRGBA): ColorRGBA = proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
blendLightenFloats(a.color, b.color).rgba blendColorBurnFloats(backdrop.color, source.color).rgba
proc blendScreen(a, b: ColorRGBA): ColorRGBA = proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
blendScreenFloats(a.color, b.color).rgba blendLightenFloats(backdrop.color, source.color).rgba
proc blendLinearDodge(a, b: ColorRGBA): ColorRGBA = proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
blendLinearDodgeFloats(a.color, b.color).rgba blendScreenFloats(backdrop.color, source.color).rgba
proc blendColorDodge(a, b: ColorRGBA): ColorRGBA = proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
blendColorDodgeFloats(a.color, b.color).rgba blendLinearDodgeFloats(backdrop.color, source.color).rgba
proc blendOverlay(a, b: ColorRGBA): ColorRGBA = proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
blendOverlayFloats(a.color, b.color).rgba blendColorDodgeFloats(backdrop.color, source.color).rgba
proc blendHardLight(a, b: ColorRGBA): ColorRGBA = proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
blendHardLightFloats(a.color, b.color).rgba blendOverlayFloats(backdrop.color, source.color).rgba
proc blendSoftLight(a, b: ColorRGBA): ColorRGBA = proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
blendSoftLightFloats(a.color, b.color).rgba blendHardLightFloats(backdrop.color, source.color).rgba
proc blendDifference(a, b: ColorRGBA): ColorRGBA = proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
blendDifferenceFloats(a.color, b.color).rgba blendSoftLightFloats(backdrop.color, source.color).rgba
proc blendExclusion(a, b: ColorRGBA): ColorRGBA = proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
blendExclusionFloats(a.color, b.color).rgba blendDifferenceFloats(backdrop.color, source.color).rgba
proc blendColor(a, b: ColorRGBA): ColorRGBA = proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
blendColorFloats(a.color, b.color).rgba blendExclusionFloats(backdrop.color, source.color).rgba
proc blendLuminosity(a, b: ColorRGBA): ColorRGBA = proc blendColor(backdrop, source: ColorRGBA): ColorRGBA =
blendLuminosityFloats(a.color, b.color).rgba blendColorFloats(backdrop.color, source.color).rgba
proc blendHue(a, b: ColorRGBA): ColorRGBA = proc blendLuminosity(backdrop, source: ColorRGBA): ColorRGBA =
blendHueFloats(a.color, b.color).rgba blendLuminosityFloats(backdrop.color, source.color).rgba
proc blendSaturation(a, b: ColorRGBA): ColorRGBA = proc blendHue(backdrop, source: ColorRGBA): ColorRGBA =
blendSaturationFloats(a.color, b.color).rgba blendHueFloats(backdrop.color, source.color).rgba
proc blendMask(a, b: ColorRGBA): ColorRGBA = proc blendSaturation(backdrop, source: ColorRGBA): ColorRGBA =
result = a blendSaturationFloats(backdrop.color, source.color).rgba
result.a = min(a.a, b.a)
proc blendSubtractMask(a, b: ColorRGBA): ColorRGBA = proc blendMask(backdrop, source: ColorRGBA): ColorRGBA =
result = a result = backdrop
result.a = max(0, (a.a.int32 * (255 - b.a.int32)) div 255).uint8 result.a = min(backdrop.a, source.a)
proc blendIntersectMask(a, b: ColorRGBA): ColorRGBA = proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA =
result = a result = backdrop
result.a = ((a.a.uint32 * (b.a.uint32)) div 255).uint8 result.a = max(0, (backdrop.a.int32 * (255 - source.a.int32)) div 255).uint8
proc blendExcludeMask(a, b: ColorRGBA): ColorRGBA = proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
result = a result = backdrop
result.a = max(a.a, b.a) - min(a.a, b.a) result.a = ((backdrop.a.uint32 * (source.a.uint32)) div 255).uint8
proc blendOverwrite(a, b: ColorRGBA): ColorRGBA = proc blendExcludeMask(backdrop, source: ColorRGBA): ColorRGBA =
b result = backdrop
result.a = max(backdrop.a, source.a) - min(backdrop.a, source.a)
proc blendOverwrite(backdrop, source: ColorRGBA): ColorRGBA =
source
proc mixer*(blendMode: BlendMode): Mixer = proc mixer*(blendMode: BlendMode): Mixer =
case blendMode case blendMode