commit
22aace7a5e
11 changed files with 86 additions and 118 deletions
|
@ -190,7 +190,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
|
||||||
elif fill == "none":
|
elif fill == "none":
|
||||||
result.fill = ColorRGBA()
|
result.fill = ColorRGBA()
|
||||||
else:
|
else:
|
||||||
result.fill = parseHtmlColor(fill).rgba.toPremultipliedAlpha()
|
result.fill = parseHtmlColor(fill).rgba
|
||||||
|
|
||||||
if stroke == "":
|
if stroke == "":
|
||||||
discard # Inherit
|
discard # Inherit
|
||||||
|
@ -199,7 +199,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
|
||||||
elif stroke == "none":
|
elif stroke == "none":
|
||||||
result.stroke = ColorRGBA()
|
result.stroke = ColorRGBA()
|
||||||
else:
|
else:
|
||||||
result.stroke = parseHtmlColor(stroke).rgba.toPremultipliedAlpha()
|
result.stroke = parseHtmlColor(stroke).rgba
|
||||||
result.shouldStroke = true
|
result.shouldStroke = true
|
||||||
|
|
||||||
if strokeWidth == "":
|
if strokeWidth == "":
|
||||||
|
|
|
@ -35,7 +35,7 @@ type
|
||||||
bmIntersectMask
|
bmIntersectMask
|
||||||
bmExcludeMask
|
bmExcludeMask
|
||||||
|
|
||||||
Blender* = proc(backdrop, source: ColorRGBA): ColorRGBA
|
Blender* = proc(backdrop, source: ColorRGBX): ColorRGBX
|
||||||
## Function signature returned by blender.
|
## Function signature returned by blender.
|
||||||
Masker* = proc(backdrop, source: uint8): uint8
|
Masker* = proc(backdrop, source: uint8): uint8
|
||||||
## Function signature returned by masker.
|
## Function signature returned by masker.
|
||||||
|
@ -166,7 +166,7 @@ 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 blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendNormal(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
if backdrop.a == 0:
|
if backdrop.a == 0:
|
||||||
return source
|
return source
|
||||||
if source.a == 255:
|
if source.a == 255:
|
||||||
|
@ -180,7 +180,7 @@ proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
|
result.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDarken(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
proc blend(
|
proc blend(
|
||||||
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
): uint8 {.inline.} =
|
): uint8 {.inline.} =
|
||||||
|
@ -194,7 +194,7 @@ proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendMultiply(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
proc blend(
|
proc blend(
|
||||||
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
): uint8 {.inline.} =
|
): uint8 {.inline.} =
|
||||||
|
@ -209,7 +209,7 @@ proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
# proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
# proc blendLinearBurn(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
# let
|
# let
|
||||||
# backdrop = backdrop.toStraightAlpha()
|
# backdrop = backdrop.toStraightAlpha()
|
||||||
# source = source.toStraightAlpha()
|
# source = source.toStraightAlpha()
|
||||||
|
@ -219,7 +219,7 @@ proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
# result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
# result = result.toPremultipliedAlpha()
|
# result = result.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColorBurn(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdrop = backdrop.toStraightAlpha()
|
||||||
source = source.toStraightAlpha()
|
source = source.toStraightAlpha()
|
||||||
|
@ -230,13 +230,13 @@ proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
0
|
0
|
||||||
else:
|
else:
|
||||||
255 - min(255, (255 * (255 - backdrop)) div source).uint8
|
255 - min(255, (255 * (255 - backdrop)) div source).uint8
|
||||||
result.r = blend(backdrop.r, source.r)
|
var blended: ColorRGBA
|
||||||
result.g = blend(backdrop.g, source.g)
|
blended.r = blend(backdrop.r, source.r)
|
||||||
result.b = blend(backdrop.b, source.b)
|
blended.g = blend(backdrop.g, source.g)
|
||||||
result = alphaFix(backdrop, source, result)
|
blended.b = blend(backdrop.b, source.b)
|
||||||
result = result.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLighten(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
proc blend(
|
proc blend(
|
||||||
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
): uint8 {.inline.} =
|
): uint8 {.inline.} =
|
||||||
|
@ -250,13 +250,13 @@ proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendScreen(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
result.r = screen(backdrop.r, source.r)
|
result.r = screen(backdrop.r, source.r)
|
||||||
result.g = screen(backdrop.g, source.g)
|
result.g = screen(backdrop.g, source.g)
|
||||||
result.b = screen(backdrop.b, source.b)
|
result.b = screen(backdrop.b, source.b)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
# proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
# proc blendLinearDodge(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
# let
|
# let
|
||||||
# backdrop = backdrop.toStraightAlpha()
|
# backdrop = backdrop.toStraightAlpha()
|
||||||
# source = source.toStraightAlpha()
|
# source = source.toStraightAlpha()
|
||||||
|
@ -266,7 +266,7 @@ proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
# result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
# result = result.toPremultipliedAlpha()
|
# result = result.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColorDodge(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdrop = backdrop.toStraightAlpha()
|
||||||
source = source.toStraightAlpha()
|
source = source.toStraightAlpha()
|
||||||
|
@ -277,19 +277,19 @@ proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
255
|
255
|
||||||
else:
|
else:
|
||||||
min(255, (255 * backdrop) div (255 - source)).uint8
|
min(255, (255 * backdrop) div (255 - source)).uint8
|
||||||
result.r = blend(backdrop.r, source.r)
|
var blended: ColorRGBA
|
||||||
result.g = blend(backdrop.g, source.g)
|
blended.r = blend(backdrop.r, source.r)
|
||||||
result.b = blend(backdrop.b, source.b)
|
blended.g = blend(backdrop.g, source.g)
|
||||||
result = alphaFix(backdrop, source, result)
|
blended.b = blend(backdrop.b, source.b)
|
||||||
result = result.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendOverlay(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
result.r = hardLight(source.r, source.a, backdrop.r, backdrop.a)
|
result.r = hardLight(source.r, source.a, backdrop.r, backdrop.a)
|
||||||
result.g = hardLight(source.g, source.a, backdrop.g, backdrop.a)
|
result.g = hardLight(source.g, source.a, backdrop.g, backdrop.a)
|
||||||
result.b = hardLight(source.b, source.a, backdrop.b, backdrop.a)
|
result.b = hardLight(source.b, source.a, backdrop.b, backdrop.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendSoftLight(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
|
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
|
||||||
# ## Pegtop
|
# ## Pegtop
|
||||||
# (
|
# (
|
||||||
|
@ -301,6 +301,7 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdrop = backdrop.toStraightAlpha()
|
||||||
source = source.toStraightAlpha()
|
source = source.toStraightAlpha()
|
||||||
|
|
||||||
|
var rgba: ColorRGBA
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
let
|
let
|
||||||
vb = mm_setr_ps(
|
vb = mm_setr_ps(
|
||||||
|
@ -316,11 +317,11 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
vm = ((v255 - v2 * vs) * vb * vb) / v255sq + (v2 * vs * vb) / v255
|
vm = ((v255 - v2 * vs) * vb * vb) / v255sq + (v2 * vs * vb) / v255
|
||||||
values = cast[array[4, uint32]](mm_cvtps_epi32(vm))
|
values = cast[array[4, uint32]](mm_cvtps_epi32(vm))
|
||||||
|
|
||||||
result.r = values[0].uint8
|
rgba.r = values[0].uint8
|
||||||
result.g = values[1].uint8
|
rgba.g = values[1].uint8
|
||||||
result.b = values[2].uint8
|
rgba.b = values[2].uint8
|
||||||
|
|
||||||
# proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA {.inline.} =
|
# proc alphaFix(backdrop, source, mixed: ColorRGBX): ColorRGBX {.inline.} =
|
||||||
# if backdrop.a == 0 and source.a == 0:
|
# if backdrop.a == 0 and source.a == 0:
|
||||||
# return
|
# return
|
||||||
# let
|
# let
|
||||||
|
@ -345,10 +346,10 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
mm_cvtps_epi32((t0 * vs + t1 * vm + t2 * vb) / va / v255)
|
mm_cvtps_epi32((t0 * vs + t1 * vm + t2 * vb) / va / v255)
|
||||||
)
|
)
|
||||||
|
|
||||||
result.r = final[0].uint8
|
rgba.r = final[0].uint8
|
||||||
result.g = final[1].uint8
|
rgba.g = final[1].uint8
|
||||||
result.b = final[2].uint8
|
rgba.b = final[2].uint8
|
||||||
result.a = a.uint8
|
rgba.a = a.uint8
|
||||||
else:
|
else:
|
||||||
let
|
let
|
||||||
b = backdrop.color
|
b = backdrop.color
|
||||||
|
@ -358,17 +359,17 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
blended.g = softLight(b.g, s.g)
|
blended.g = softLight(b.g, s.g)
|
||||||
blended.b = softLight(b.b, s.b)
|
blended.b = softLight(b.b, s.b)
|
||||||
blended = alphaFix(b, s, blended)
|
blended = alphaFix(b, s, blended)
|
||||||
result = blended.rgba
|
rgba = blended.rgba
|
||||||
|
|
||||||
result = result.toPremultipliedAlpha()
|
result = rgba
|
||||||
|
|
||||||
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendHardLight(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
result.r = hardLight(backdrop.r, backdrop.a, source.r, source.a)
|
result.r = hardLight(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
result.g = hardLight(backdrop.g, backdrop.a, source.g, source.a)
|
result.g = hardLight(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
result.b = hardLight(backdrop.b, backdrop.a, source.b, source.a)
|
result.b = hardLight(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDifference(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
proc blend(
|
proc blend(
|
||||||
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
): uint8 {.inline.} =
|
): uint8 {.inline.} =
|
||||||
|
@ -384,7 +385,7 @@ proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendExclusion(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
let v = (backdrop + source).int32 - ((2 * backdrop * source) div 255).int32
|
let v = (backdrop + source).int32 - ((2 * backdrop * source) div 255).int32
|
||||||
max(0, v).uint8
|
max(0, v).uint8
|
||||||
|
@ -393,62 +394,62 @@ proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.b = blend(backdrop.b.uint32, source.b.uint32)
|
result.b = blend(backdrop.b.uint32, source.b.uint32)
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendColor(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColor(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha().color
|
backdrop = backdrop.toStraightAlpha().color
|
||||||
source = source.toStraightAlpha().color
|
source = source.toStraightAlpha().color
|
||||||
blended = SetLum(source, Lum(backdrop))
|
blended = SetLum(source, Lum(backdrop))
|
||||||
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendLuminosity(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLuminosity(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha().color
|
backdrop = backdrop.toStraightAlpha().color
|
||||||
source = source.toStraightAlpha().color
|
source = source.toStraightAlpha().color
|
||||||
blended = SetLum(backdrop, Lum(source))
|
blended = SetLum(backdrop, Lum(source))
|
||||||
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendHue(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendHue(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha().color
|
backdrop = backdrop.toStraightAlpha().color
|
||||||
source = source.toStraightAlpha().color
|
source = source.toStraightAlpha().color
|
||||||
blended = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop))
|
blended = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop))
|
||||||
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendSaturation(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendSaturation(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let
|
let
|
||||||
backdrop = backdrop.toStraightAlpha().color
|
backdrop = backdrop.toStraightAlpha().color
|
||||||
source = source.toStraightAlpha().color
|
source = source.toStraightAlpha().color
|
||||||
blended = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
|
blended = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
|
||||||
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendMask(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let k = source.a.uint32
|
let k = source.a.uint32
|
||||||
result.r = ((backdrop.r * k) div 255).uint8
|
result.r = ((backdrop.r * k) div 255).uint8
|
||||||
result.g = ((backdrop.g * k) div 255).uint8
|
result.g = ((backdrop.g * k) div 255).uint8
|
||||||
result.b = ((backdrop.b * k) div 255).uint8
|
result.b = ((backdrop.b * k) div 255).uint8
|
||||||
result.a = ((backdrop.a * k) div 255).uint8
|
result.a = ((backdrop.a * k) div 255).uint8
|
||||||
|
|
||||||
proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendSubtractMask(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let a = (backdrop.a.uint32 * (255 - source.a)) div 255
|
let a = (backdrop.a.uint32 * (255 - source.a)) div 255
|
||||||
result.r = ((backdrop.r * a) div 255).uint8
|
result.r = ((backdrop.r * a) div 255).uint8
|
||||||
result.g = ((backdrop.g * a) div 255).uint8
|
result.g = ((backdrop.g * a) div 255).uint8
|
||||||
result.b = ((backdrop.b * a) div 255).uint8
|
result.b = ((backdrop.b * a) div 255).uint8
|
||||||
result.a = a.uint8
|
result.a = a.uint8
|
||||||
|
|
||||||
proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendIntersectMask(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
blendMask(backdrop, source)
|
blendMask(backdrop, source)
|
||||||
|
|
||||||
proc blendExcludeMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendExcludeMask(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
let a = max(backdrop.a, source.a).uint32 - min(backdrop.a, source.a)
|
let a = max(backdrop.a, source.a).uint32 - min(backdrop.a, source.a)
|
||||||
result.r = ((backdrop.r * a) div 255).uint8
|
result.r = ((backdrop.r * a) div 255).uint8
|
||||||
result.g = ((backdrop.g * a) div 255).uint8
|
result.g = ((backdrop.g * a) div 255).uint8
|
||||||
result.b = ((backdrop.b * a) div 255).uint8
|
result.b = ((backdrop.b * a) div 255).uint8
|
||||||
result.a = a.uint8
|
result.a = a.uint8
|
||||||
|
|
||||||
proc blendOverwrite(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendOverwrite(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
source
|
source
|
||||||
|
|
||||||
# proc blendWhite(backdrop, source: ColorRGBA): ColorRGBA =
|
# proc blendWhite(backdrop, source: ColorRGBX): ColorRGBX =
|
||||||
# ## For testing
|
# ## For testing
|
||||||
# rgba(255, 255, 255, 255)
|
# rgba(255, 255, 255, 255)
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ proc lerp*(a, b: uint8, t: float32): uint8 {.inline.} =
|
||||||
let t = round(t * 255).uint32
|
let t = round(t * 255).uint32
|
||||||
((a * (255 - t) + b * t) div 255).uint8
|
((a * (255 - t) + b * t) div 255).uint8
|
||||||
|
|
||||||
proc lerp*(a, b: ColorRGBA, t: float32): ColorRGBA {.inline.} =
|
proc lerp*(a, b: ColorRGBX, t: float32): ColorRGBX {.inline.} =
|
||||||
## Linearly interpolate between a and b using t.
|
## Linearly interpolate between a and b using t.
|
||||||
let x = round(t * 255).uint32
|
let x = round(t * 255).uint32
|
||||||
result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x) div 255).uint8
|
result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x) div 255).uint8
|
||||||
|
@ -28,36 +28,3 @@ func lerp*(a, b: Color, v: float32): Color {.inline.} =
|
||||||
result.g = lerp(a.g, b.g, v)
|
result.g = lerp(a.g, b.g, v)
|
||||||
result.b = lerp(a.b, b.b, v)
|
result.b = lerp(a.b, b.b, v)
|
||||||
result.a = lerp(a.a, b.a, v)
|
result.a = lerp(a.a, b.a, v)
|
||||||
|
|
||||||
proc toPremultipliedAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
|
||||||
## Converts a color to premultiplied alpha from straight alpha.
|
|
||||||
result.r = ((c.r.uint32 * c.a.uint32) div 255).uint8
|
|
||||||
result.g = ((c.g.uint32 * c.a.uint32) div 255).uint8
|
|
||||||
result.b = ((c.b.uint32 * c.a.uint32) div 255).uint8
|
|
||||||
result.a = c.a
|
|
||||||
|
|
||||||
proc toStraightAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
|
||||||
## Converts a color from premultiplied alpha to straight alpha.
|
|
||||||
result = c
|
|
||||||
if result.a != 0 and result.a != 255:
|
|
||||||
let multiplier = ((255 / c.a.float32) * 255).uint32
|
|
||||||
result.r = ((result.r.uint32 * multiplier) div 255).uint8
|
|
||||||
result.g = ((result.g.uint32 * multiplier) div 255).uint8
|
|
||||||
result.b = ((result.b.uint32 * multiplier) div 255).uint8
|
|
||||||
|
|
||||||
proc toPremultipliedAlpha*(c: Color): Color {.inline.} =
|
|
||||||
## Converts a color to premultiplied alpha from straight alpha.
|
|
||||||
result.r = c.r * c.a
|
|
||||||
result.g = c.g * c.a
|
|
||||||
result.b = c.b * c.a
|
|
||||||
result.a = c.a
|
|
||||||
|
|
||||||
proc toStraightAlpha*(c: Color): Color {.inline.} =
|
|
||||||
## Converts a color from premultiplied alpha to straight alpha.
|
|
||||||
if c.a != 0 and c.a != 1:
|
|
||||||
result = c
|
|
||||||
else:
|
|
||||||
result.r = c.r / c.a
|
|
||||||
result.g = c.g / c.a
|
|
||||||
result.b = c.b / c.a
|
|
||||||
result.a = c.a
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import chroma, flatty/binny, pixie/common, pixie/images, pixie/internal
|
import chroma, flatty/binny, pixie/common, pixie/images
|
||||||
|
|
||||||
# See: https://en.wikipedia.org/wiki/BMP_file_format
|
# See: https://en.wikipedia.org/wiki/BMP_file_format
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@ proc decodeBmp*(data: string): Image =
|
||||||
offset += 3
|
offset += 3
|
||||||
result[x, result.height - y - 1] = rgba
|
result[x, result.height - y - 1] = rgba
|
||||||
|
|
||||||
result.data.toPremultipliedAlpha()
|
|
||||||
|
|
||||||
proc decodeBmp*(data: seq[uint8]): Image {.inline.} =
|
proc decodeBmp*(data: seq[uint8]): Image {.inline.} =
|
||||||
## Decodes bitmap data into an Image.
|
## Decodes bitmap data into an Image.
|
||||||
decodeBmp(cast[string](data))
|
decodeBmp(cast[string](data))
|
||||||
|
|
|
@ -407,11 +407,13 @@ proc decodePng*(data: seq[uint8]): Image =
|
||||||
if prevChunkType != "IEND":
|
if prevChunkType != "IEND":
|
||||||
failInvalid()
|
failInvalid()
|
||||||
|
|
||||||
|
var pixels = decodeImageData(header, palette, transparency, imageData)
|
||||||
|
pixels.toPremultipliedAlpha()
|
||||||
|
|
||||||
result = Image()
|
result = Image()
|
||||||
result.width = header.width
|
result.width = header.width
|
||||||
result.height = header.height
|
result.height = header.height
|
||||||
result.data = decodeImageData(header, palette, transparency, imageData)
|
result.data = cast[seq[ColorRGBX]](pixels)
|
||||||
result.data.toPremultipliedAlpha()
|
|
||||||
|
|
||||||
proc decodePng*(data: string): Image {.inline.} =
|
proc decodePng*(data: string): Image {.inline.} =
|
||||||
## Decodes the PNG data into an Image.
|
## Decodes the PNG data into an Image.
|
||||||
|
|
|
@ -81,7 +81,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
|
||||||
elif fill == "none":
|
elif fill == "none":
|
||||||
result.fill = ColorRGBA()
|
result.fill = ColorRGBA()
|
||||||
else:
|
else:
|
||||||
result.fill = parseHtmlColor(fill).rgba.toPremultipliedAlpha()
|
result.fill = parseHtmlColor(fill).rgba
|
||||||
|
|
||||||
if stroke == "":
|
if stroke == "":
|
||||||
discard # Inherit
|
discard # Inherit
|
||||||
|
@ -90,7 +90,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
|
||||||
elif stroke == "none":
|
elif stroke == "none":
|
||||||
result.stroke = ColorRGBA()
|
result.stroke = ColorRGBA()
|
||||||
else:
|
else:
|
||||||
result.stroke = parseHtmlColor(stroke).rgba.toPremultipliedAlpha()
|
result.stroke = parseHtmlColor(stroke).rgba
|
||||||
result.shouldStroke = true
|
result.shouldStroke = true
|
||||||
|
|
||||||
if strokeWidth == "":
|
if strokeWidth == "":
|
||||||
|
|
|
@ -9,7 +9,7 @@ type
|
||||||
Image* = ref object
|
Image* = ref object
|
||||||
## Image object that holds bitmap data in RGBA format.
|
## Image object that holds bitmap data in RGBA format.
|
||||||
width*, height*: int
|
width*, height*: int
|
||||||
data*: seq[ColorRGBA]
|
data*: seq[ColorRGBX]
|
||||||
|
|
||||||
when defined(release):
|
when defined(release):
|
||||||
{.push checks: off.}
|
{.push checks: off.}
|
||||||
|
@ -22,7 +22,7 @@ proc newImage*(width, height: int): Image =
|
||||||
result = Image()
|
result = Image()
|
||||||
result.width = width
|
result.width = width
|
||||||
result.height = height
|
result.height = height
|
||||||
result.data = newSeq[ColorRGBA](width * height)
|
result.data = newSeq[ColorRGBX](width * height)
|
||||||
|
|
||||||
proc wh*(image: Image): Vec2 {.inline.} =
|
proc wh*(image: Image): Vec2 {.inline.} =
|
||||||
## Return with and height as a size vector.
|
## Return with and height as a size vector.
|
||||||
|
@ -44,31 +44,31 @@ proc inside*(image: Image, x, y: int): bool {.inline.} =
|
||||||
proc dataIndex*(image: Image, x, y: int): int {.inline.} =
|
proc dataIndex*(image: Image, x, y: int): int {.inline.} =
|
||||||
image.width * y + x
|
image.width * y + x
|
||||||
|
|
||||||
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBA {.inline.} =
|
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBX {.inline.} =
|
||||||
## Gets a color from (x, y) coordinates.
|
## Gets a color from (x, y) coordinates.
|
||||||
## * No bounds checking *
|
## * No bounds checking *
|
||||||
## Make sure that x, y are in bounds.
|
## Make sure that x, y are in bounds.
|
||||||
## Failure in the assumptions will case unsafe memory reads.
|
## Failure in the assumptions will case unsafe memory reads.
|
||||||
result = image.data[image.width * y + x]
|
result = image.data[image.width * y + x]
|
||||||
|
|
||||||
proc `[]`*(image: Image, x, y: int): ColorRGBA {.inline.} =
|
proc `[]`*(image: Image, x, y: int): ColorRGBX {.inline.} =
|
||||||
## Gets a pixel at (x, y) or returns transparent black if outside of bounds.
|
## Gets a pixel at (x, y) or returns transparent black if outside of bounds.
|
||||||
if image.inside(x, y):
|
if image.inside(x, y):
|
||||||
return image.getRgbaUnsafe(x, y)
|
return image.getRgbaUnsafe(x, y)
|
||||||
|
|
||||||
proc setRgbaUnsafe*(image: Image, x, y: int, rgba: ColorRGBA) {.inline.} =
|
proc setRgbaUnsafe*(image: Image, x, y: int, rgba: ColorRGBX) {.inline.} =
|
||||||
## Sets a color from (x, y) coordinates.
|
## Sets a color from (x, y) coordinates.
|
||||||
## * No bounds checking *
|
## * No bounds checking *
|
||||||
## Make sure that x, y are in bounds.
|
## Make sure that x, y are in bounds.
|
||||||
## Failure in the assumptions will case unsafe memory writes.
|
## Failure in the assumptions will case unsafe memory writes.
|
||||||
image.data[image.dataIndex(x, y)] = rgba
|
image.data[image.dataIndex(x, y)] = rgba
|
||||||
|
|
||||||
proc `[]=`*(image: Image, x, y: int, rgba: ColorRGBA) {.inline.} =
|
proc `[]=`*(image: Image, x, y: int, rgba: ColorRGBX) {.inline.} =
|
||||||
## Sets a pixel at (x, y) or does nothing if outside of bounds.
|
## Sets a pixel at (x, y) or does nothing if outside of bounds.
|
||||||
if image.inside(x, y):
|
if image.inside(x, y):
|
||||||
image.setRgbaUnsafe(x, y, rgba)
|
image.setRgbaUnsafe(x, y, rgba)
|
||||||
|
|
||||||
proc fillUnsafe*(data: var seq[ColorRGBA], rgba: ColorRGBA, start, len: int) =
|
proc fillUnsafe*(data: var seq[ColorRGBX], rgba: ColorRGBX, start, len: int) =
|
||||||
## Fills the image data with the parameter color starting at index start and
|
## Fills the image data with the parameter color starting at index start and
|
||||||
## continuing for len indices.
|
## continuing for len indices.
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ proc fillUnsafe*(data: var seq[ColorRGBA], rgba: ColorRGBA, start, len: int) =
|
||||||
for j in i ..< start + len:
|
for j in i ..< start + len:
|
||||||
data[j] = rgba
|
data[j] = rgba
|
||||||
|
|
||||||
proc fill*(image: Image, rgba: ColorRgba) {.inline.} =
|
proc fill*(image: Image, rgba: ColorRGBX) {.inline.} =
|
||||||
## Fills the image with the parameter color.
|
## Fills the image with the parameter color.
|
||||||
fillUnsafe(image.data, rgba, 0, image.data.len)
|
fillUnsafe(image.data, rgba, 0, image.data.len)
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ proc minifyBy2*(image: Image, power = 1): Image =
|
||||||
c = src.getRgbaUnsafe(x * 2 + 1, y * 2 + 1)
|
c = src.getRgbaUnsafe(x * 2 + 1, y * 2 + 1)
|
||||||
d = src.getRgbaUnsafe(x * 2 + 0, y * 2 + 1)
|
d = src.getRgbaUnsafe(x * 2 + 0, y * 2 + 1)
|
||||||
|
|
||||||
let color = rgba(
|
let color = rgbx(
|
||||||
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8,
|
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8,
|
||||||
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8,
|
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8,
|
||||||
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8,
|
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8,
|
||||||
|
@ -217,7 +217,7 @@ proc applyOpacity*(target: Image | Mask, opacity: float32) =
|
||||||
|
|
||||||
if opacity == 0:
|
if opacity == 0:
|
||||||
when type(target) is Image:
|
when type(target) is Image:
|
||||||
target.fill(rgba(0, 0, 0, 0))
|
target.fill(rgbx(0, 0, 0, 0))
|
||||||
else:
|
else:
|
||||||
target.fill(0)
|
target.fill(0)
|
||||||
return
|
return
|
||||||
|
@ -458,7 +458,7 @@ proc newMask*(image: Image): Mask =
|
||||||
for j in i ..< image.data.len:
|
for j in i ..< image.data.len:
|
||||||
result.data[j] = image.data[j].a
|
result.data[j] = image.data[j].a
|
||||||
|
|
||||||
proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBA =
|
proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBX =
|
||||||
## Gets a interpolated color with float point coordinates.
|
## Gets a interpolated color with float point coordinates.
|
||||||
## Pixes outside the image are transparent.
|
## Pixes outside the image are transparent.
|
||||||
let
|
let
|
||||||
|
@ -473,7 +473,7 @@ proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBA =
|
||||||
x1 = (x + 1)
|
x1 = (x + 1)
|
||||||
y1 = (y + 1)
|
y1 = (y + 1)
|
||||||
|
|
||||||
var x0y0, x1y0, x0y1, x1y1: ColorRGBA
|
var x0y0, x1y0, x0y1, x1y1: ColorRGBX
|
||||||
if wrapped:
|
if wrapped:
|
||||||
x0y0 = image.getRgbaUnsafe(x0 mod image.width, y0 mod image.height)
|
x0y0 = image.getRgbaUnsafe(x0 mod image.width, y0 mod image.height)
|
||||||
x1y0 = image.getRgbaUnsafe(x1 mod image.width, y0 mod image.height)
|
x1y0 = image.getRgbaUnsafe(x1 mod image.width, y0 mod image.height)
|
||||||
|
@ -642,7 +642,7 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) =
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let
|
let
|
||||||
sample = b.getValueSmooth(xFloat, yFloat)
|
sample = b.getValueSmooth(xFloat, yFloat)
|
||||||
blended = blender(backdrop, rgba(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.setRgbaUnsafe(x, y, blended)
|
a.setRgbaUnsafe(x, y, blended)
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.getValueUnsafe(x, y)
|
||||||
|
@ -729,7 +729,7 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) =
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let
|
let
|
||||||
sample = b.getValueUnsafe(xFloat.int, yFloat.int)
|
sample = b.getValueUnsafe(xFloat.int, yFloat.int)
|
||||||
blended = blender(backdrop, rgba(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.setRgbaUnsafe(x, y, blended)
|
a.setRgbaUnsafe(x, y, blended)
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.getValueUnsafe(x, y)
|
||||||
|
@ -812,7 +812,7 @@ proc shift*(target: Image | Mask, offset: Vec2) =
|
||||||
target.draw(copy, offset, bmOverwrite) # Draw copy at offset
|
target.draw(copy, offset, bmOverwrite) # Draw copy at offset
|
||||||
|
|
||||||
proc shadow*(
|
proc shadow*(
|
||||||
image: Image, offset: Vec2, spread, blur: float32, color: ColorRGBA
|
image: Image, offset: Vec2, spread, blur: float32, color: ColorRGBX
|
||||||
): Image =
|
): Image =
|
||||||
## Create a shadow of the image with the offset, spread and blur.
|
## Create a shadow of the image with the offset, spread and blur.
|
||||||
let mask = image.newMask()
|
let mask = image.newMask()
|
||||||
|
|
|
@ -3,7 +3,7 @@ import chroma
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
import nimsimd/sse2
|
import nimsimd/sse2
|
||||||
|
|
||||||
proc toStraightAlpha*(data: var seq[ColorRGBA]) =
|
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
|
||||||
## Converts an image from premultiplied alpha to straight alpha.
|
## Converts an image from premultiplied alpha to straight alpha.
|
||||||
## This is expensive for large images.
|
## This is expensive for large images.
|
||||||
for c in data.mitems:
|
for c in data.mitems:
|
||||||
|
@ -14,7 +14,7 @@ proc toStraightAlpha*(data: var seq[ColorRGBA]) =
|
||||||
c.g = ((c.g.uint32 * multiplier) div 255).uint8
|
c.g = ((c.g.uint32 * multiplier) div 255).uint8
|
||||||
c.b = ((c.b.uint32 * multiplier) div 255).uint8
|
c.b = ((c.b.uint32 * multiplier) div 255).uint8
|
||||||
|
|
||||||
proc toPremultipliedAlpha*(data: var seq[ColorRGBA]) =
|
proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
|
||||||
## Converts an image to premultiplied alpha from straight alpha.
|
## Converts an image to premultiplied alpha from straight alpha.
|
||||||
var i: int
|
var i: int
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import blends, chroma, common, images, vmath
|
import blends, chroma, images, vmath
|
||||||
|
|
||||||
type
|
type
|
||||||
PaintKind* = enum
|
PaintKind* = enum
|
||||||
|
@ -13,7 +13,7 @@ type
|
||||||
## Paint used to fill paths.
|
## Paint used to fill paths.
|
||||||
case kind*: PaintKind
|
case kind*: PaintKind
|
||||||
of pkSolid:
|
of pkSolid:
|
||||||
color*: ColorRGBA ## Color to fill with.
|
color*: ColorRGBX ## Color to fill with.
|
||||||
of pkImage, pkImageTiled:
|
of pkImage, pkImageTiled:
|
||||||
image*: Image ## Image to fill with.
|
image*: Image ## Image to fill with.
|
||||||
imageMat*: Mat3 ## Matrix of the filled image.
|
imageMat*: Mat3 ## Matrix of the filled image.
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ template computeCoverages(
|
||||||
proc fillShapes(
|
proc fillShapes(
|
||||||
image: Image,
|
image: Image,
|
||||||
shapes: seq[seq[Vec2]],
|
shapes: seq[seq[Vec2]],
|
||||||
color: ColorRGBA,
|
color: ColorRGBX,
|
||||||
windingRule: WindingRule,
|
windingRule: WindingRule,
|
||||||
blendMode: BlendMode
|
blendMode: BlendMode
|
||||||
) =
|
) =
|
||||||
|
@ -1418,7 +1418,7 @@ proc parseSomePath(
|
||||||
proc fillPath*(
|
proc fillPath*(
|
||||||
image: Image,
|
image: Image,
|
||||||
path: SomePath,
|
path: SomePath,
|
||||||
color: ColorRGBA,
|
color: ColorRGBX,
|
||||||
windingRule = wrNonZero,
|
windingRule = wrNonZero,
|
||||||
blendMode = bmNormal
|
blendMode = bmNormal
|
||||||
) {.inline.} =
|
) {.inline.} =
|
||||||
|
@ -1428,7 +1428,7 @@ proc fillPath*(
|
||||||
proc fillPath*(
|
proc fillPath*(
|
||||||
image: Image,
|
image: Image,
|
||||||
path: SomePath,
|
path: SomePath,
|
||||||
color: ColorRGBA,
|
color: ColorRGBX,
|
||||||
transform: Vec2 | Mat3,
|
transform: Vec2 | Mat3,
|
||||||
windingRule = wrNonZero,
|
windingRule = wrNonZero,
|
||||||
blendMode = bmNormal
|
blendMode = bmNormal
|
||||||
|
@ -1488,7 +1488,7 @@ proc fillPath*(
|
||||||
|
|
||||||
case paint.kind:
|
case paint.kind:
|
||||||
of pkSolid:
|
of pkSolid:
|
||||||
fill.fill(paint.color.toPremultipliedAlpha())
|
fill.fill(paint.color)
|
||||||
of pkImage:
|
of pkImage:
|
||||||
fill.draw(paint.image, paint.imageMat)
|
fill.draw(paint.image, paint.imageMat)
|
||||||
of pkImageTiled:
|
of pkImageTiled:
|
||||||
|
@ -1520,7 +1520,7 @@ proc fillPath*(
|
||||||
proc strokePath*(
|
proc strokePath*(
|
||||||
image: Image,
|
image: Image,
|
||||||
path: SomePath,
|
path: SomePath,
|
||||||
color: ColorRGBA,
|
color: ColorRGBX,
|
||||||
strokeWidth = 1.0,
|
strokeWidth = 1.0,
|
||||||
lineCap = lcButt,
|
lineCap = lcButt,
|
||||||
lineJoin = ljMiter,
|
lineJoin = ljMiter,
|
||||||
|
@ -1535,7 +1535,7 @@ proc strokePath*(
|
||||||
proc strokePath*(
|
proc strokePath*(
|
||||||
image: Image,
|
image: Image,
|
||||||
path: SomePath,
|
path: SomePath,
|
||||||
color: ColorRGBA,
|
color: ColorRGBX,
|
||||||
transform: Vec2 | Mat3,
|
transform: Vec2 | Mat3,
|
||||||
strokeWidth = 1.0,
|
strokeWidth = 1.0,
|
||||||
lineCap = lcButt,
|
lineCap = lcButt,
|
||||||
|
|
|
@ -30,10 +30,10 @@ block:
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let image = newImage(100, 100)
|
let image = newImage(100, 100)
|
||||||
image.fill(rgba(200, 200, 200, 200))
|
image.fill(rgbx(200, 200, 200, 200))
|
||||||
image.applyOpacity(0.5)
|
image.applyOpacity(0.5)
|
||||||
doAssert image[0, 0] == rgba(100, 100, 100, 100)
|
doAssert image[0, 0] == rgbx(100, 100, 100, 100)
|
||||||
doAssert image[88, 88] == rgba(100, 100, 100, 100)
|
doAssert image[88, 88] == rgbx(100, 100, 100, 100)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let
|
let
|
||||||
|
@ -101,6 +101,6 @@ block:
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let a = newImage(100, 100)
|
let a = newImage(100, 100)
|
||||||
a.fill(rgba(50, 100, 150, 200))
|
a.fill(rgbx(50, 100, 150, 200))
|
||||||
a.invert()
|
a.invert()
|
||||||
doAssert a[0, 0] == rgba(44, 33, 22, 55)
|
doAssert a[0, 0] == rgbx(44, 33, 22, 55)
|
||||||
|
|
Loading…
Reference in a new issue