Merge pull request #263 from guzba/master

prune some raises
This commit is contained in:
treeform 2021-08-18 21:11:43 -07:00 committed by GitHub
commit eb805d0d75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 149 additions and 189 deletions

View file

@ -42,10 +42,10 @@ type
when defined(release): when defined(release):
{.push checks: off.} {.push checks: off.}
proc min(a, b: uint32): uint32 {.inline, raises: [].} = proc min(a, b: uint32): uint32 {.inline.} =
if a < b: a else: b if a < b: a else: b
proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA {.raises: [].} = proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA =
## After mixing an image, adjust its alpha value to be correct. ## After mixing an image, adjust its alpha value to be correct.
let let
sa = source.a.uint32 sa = source.a.uint32
@ -68,7 +68,7 @@ proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA {.raises: [].} =
result.b = (b div a div 255).uint8 result.b = (b div a div 255).uint8
result.a = a.uint8 result.a = a.uint8
proc alphaFix(backdrop, source, mixed: Color): Color {.raises: [].} = proc alphaFix(backdrop, source, mixed: Color): Color =
## After mixing an image, adjust its alpha value to be correct. ## After mixing an image, adjust its alpha value to be correct.
result.a = (source.a + backdrop.a * (1.0 - source.a)) result.a = (source.a + backdrop.a * (1.0 - source.a))
if result.a == 0: if result.a == 0:
@ -87,16 +87,16 @@ proc alphaFix(backdrop, source, mixed: Color): Color {.raises: [].} =
result.g /= result.a result.g /= result.a
result.b /= result.a result.b /= result.a
proc blendAlpha*(backdrop, source: uint8): uint8 {.inline, raises: [].} = proc blendAlpha*(backdrop, source: uint8): uint8 {.inline.} =
## Blends alphas of backdrop, source. ## Blends alphas of backdrop, source.
source + ((backdrop.uint32 * (255 - source)) div 255).uint8 source + ((backdrop.uint32 * (255 - source)) div 255).uint8
proc screen(backdrop, source: uint32): uint8 {.inline, raises: [].} = proc screen(backdrop, source: uint32): uint8 {.inline.} =
((backdrop + source).int32 - ((backdrop * source) div 255).int32).uint8 ((backdrop + source).int32 - ((backdrop * source) div 255).int32).uint8
proc hardLight( proc hardLight(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint32 backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint32
): uint8 {.inline, raises: [].} = ): uint8 {.inline.} =
if sourceColor * 2 <= sourceAlpha: if sourceColor * 2 <= sourceAlpha:
(( ((
2 * sourceColor * backdropColor + 2 * sourceColor * backdropColor +
@ -106,41 +106,41 @@ proc hardLight(
else: else:
screen(backdropColor, sourceColor) screen(backdropColor, sourceColor)
proc softLight(backdrop, source: float32): float32 {.inline, raises: [].} = proc softLight(backdrop, source: float32): float32 {.inline.} =
## Pegtop ## Pegtop
(1 - 2 * source) * backdrop ^ 2 + 2 * source * backdrop (1 - 2 * source) * backdrop ^ 2 + 2 * source * backdrop
proc `+`(c: Color, v: float32): Color {.inline, raises: [].} = proc `+`(c: Color, v: float32): Color {.inline.} =
result.r = c.r + v result.r = c.r + v
result.g = c.g + v result.g = c.g + v
result.b = c.b + v result.b = c.b + v
result.a = c.a + v result.a = c.a + v
proc `+`(v: float32, c: Color): Color {.inline, raises: [].} = proc `+`(v: float32, c: Color): Color {.inline.} =
c + v c + v
proc `*`(c: Color, v: float32): Color {.inline, raises: [].} = proc `*`(c: Color, v: float32): Color {.inline.} =
result.r = c.r * v result.r = c.r * v
result.g = c.g * v result.g = c.g * v
result.b = c.b * v result.b = c.b * v
result.a = c.a * v result.a = c.a * v
proc `/`(c: Color, v: float32): Color {.inline, raises: [].} = proc `/`(c: Color, v: float32): Color {.inline.} =
result.r = c.r / v result.r = c.r / v
result.g = c.g / v result.g = c.g / v
result.b = c.b / v result.b = c.b / v
result.a = c.a / v result.a = c.a / v
proc `-`(c: Color, v: float32): Color {.inline, raises: [].} = proc `-`(c: Color, v: float32): Color {.inline.} =
result.r = c.r - v result.r = c.r - v
result.g = c.g - v result.g = c.g - v
result.b = c.b - v result.b = c.b - v
result.a = c.a - v result.a = c.a - v
proc Lum(C: Color): float32 {.inline, raises: [].} = 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: var Color) {.inline, raises: [].} = 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])
@ -150,22 +150,22 @@ proc ClipColor(C: var Color) {.inline, raises: [].} =
if x > 1: if x > 1:
C = L + (((C - L) * (1 - L)) / (x - L)) C = L + (((C - L) * (1 - L)) / (x - L))
proc SetLum(C: Color, l: float32): Color {.inline, raises: [].} = proc SetLum(C: Color, l: float32): Color {.inline.} =
let d = l - Lum(C) let 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
ClipColor(result) ClipColor(result)
proc Sat(C: Color): float32 {.inline, raises: [].} = 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])
proc SetSat(C: Color, s: float32): Color {.inline, raises: [].} = proc SetSat(C: Color, s: float32): Color {.inline.} =
let satC = Sat(C) let satC = Sat(C)
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: ColorRGBX): ColorRGBX {.raises: [].} = 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:
@ -179,7 +179,7 @@ proc blendNormal(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
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: ColorRGBX): ColorRGBX {.raises: [].} = proc blendDarken(backdrop, source: ColorRGBX): ColorRGBX =
proc blend( proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8 backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} = ): uint8 {.inline.} =
@ -193,7 +193,7 @@ proc blendDarken(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
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: ColorRGBX): ColorRGBX {.raises: [].} = proc blendMultiply(backdrop, source: ColorRGBX): ColorRGBX =
proc blend( proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8 backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} = ): uint8 {.inline.} =
@ -218,7 +218,7 @@ proc blendMultiply(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
# result = alphaFix(backdrop, source, result) # result = alphaFix(backdrop, source, result)
# result = result.toPremultipliedAlpha() # result = result.toPremultipliedAlpha()
proc blendColorBurn(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendColorBurn(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba() backdrop = backdrop.rgba()
source = source.rgba() source = source.rgba()
@ -235,7 +235,7 @@ proc blendColorBurn(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
blended.b = blend(backdrop.b, source.b) blended.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, blended).rgbx() result = alphaFix(backdrop, source, blended).rgbx()
proc blendLighten(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendLighten(backdrop, source: ColorRGBX): ColorRGBX =
proc blend( proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8 backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} = ): uint8 {.inline.} =
@ -249,7 +249,7 @@ proc blendLighten(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
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: ColorRGBX): ColorRGBX {.raises: [].} = 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)
@ -265,7 +265,7 @@ proc blendScreen(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
# result = alphaFix(backdrop, source, result) # result = alphaFix(backdrop, source, result)
# result = result.toPremultipliedAlpha() # result = result.toPremultipliedAlpha()
proc blendColorDodge(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendColorDodge(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba() backdrop = backdrop.rgba()
source = source.rgba() source = source.rgba()
@ -282,13 +282,13 @@ proc blendColorDodge(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
blended.b = blend(backdrop.b, source.b) blended.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, blended).rgbx() result = alphaFix(backdrop, source, blended).rgbx()
proc blendOverlay(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = 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: ColorRGBX): ColorRGBX {.raises: [].} = proc blendSoftLight(backdrop, source: ColorRGBX): ColorRGBX =
# proc softLight(backdrop, source: int32): uint8 {.inline.} = # proc softLight(backdrop, source: int32): uint8 {.inline.} =
# ## Pegtop # ## Pegtop
# ( # (
@ -362,13 +362,13 @@ proc blendSoftLight(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
result = rgba.rgbx() result = rgba.rgbx()
proc blendHardLight(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = 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: ColorRGBX): ColorRGBX {.raises: [].} = 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 +384,7 @@ proc blendDifference(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
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: ColorRGBX): ColorRGBX {.raises: [].} = 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,56 +393,56 @@ proc blendExclusion(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} =
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: ColorRGBX): ColorRGBX {.raises: [].} = proc blendColor(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba().color backdrop = backdrop.rgba().color
source = source.rgba().color source = source.rgba().color
blended = SetLum(source, Lum(backdrop)) blended = SetLum(source, Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.rgbx() result = alphaFix(backdrop, source, blended).rgba.rgbx()
proc blendLuminosity(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendLuminosity(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba().color backdrop = backdrop.rgba().color
source = source.rgba().color source = source.rgba().color
blended = SetLum(backdrop, Lum(source)) blended = SetLum(backdrop, Lum(source))
result = alphaFix(backdrop, source, blended).rgba.rgbx() result = alphaFix(backdrop, source, blended).rgba.rgbx()
proc blendHue(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendHue(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba().color backdrop = backdrop.rgba().color
source = source.rgba().color source = source.rgba().color
blended = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop)) blended = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.rgbx() result = alphaFix(backdrop, source, blended).rgba.rgbx()
proc blendSaturation(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendSaturation(backdrop, source: ColorRGBX): ColorRGBX =
let let
backdrop = backdrop.rgba().color backdrop = backdrop.rgba().color
source = source.rgba().color source = source.rgba().color
blended = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop)) blended = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.rgbx() result = alphaFix(backdrop, source, blended).rgba.rgbx()
proc blendMask(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = 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: ColorRGBX): ColorRGBX {.raises: [].} = 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 blendExcludeMask(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = 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 = ((source.r * a) div 255).uint8 result.r = ((source.r * a) div 255).uint8
result.g = ((source.g * a) div 255).uint8 result.g = ((source.g * a) div 255).uint8
result.b = ((source.b * a) div 255).uint8 result.b = ((source.b * a) div 255).uint8
result.a = a.uint8 result.a = a.uint8
proc blendOverwrite(backdrop, source: ColorRGBX): ColorRGBX {.raises: [].} = proc blendOverwrite(backdrop, source: ColorRGBX): ColorRGBX =
source source
# proc blendWhite(backdrop, source: ColorRGBX): ColorRGBX = # proc blendWhite(backdrop, source: ColorRGBX): ColorRGBX =
@ -475,21 +475,21 @@ proc blender*(blendMode: BlendMode): Blender {.raises: [].} =
of bmSubtractMask: blendSubtractMask of bmSubtractMask: blendSubtractMask
of bmExcludeMask: blendExcludeMask of bmExcludeMask: blendExcludeMask
proc maskNormal(backdrop, source: uint8): uint8 {.raises: [].} = proc maskNormal(backdrop, source: uint8): uint8 =
## Blending masks ## Blending masks
blendAlpha(backdrop, source) blendAlpha(backdrop, source)
proc maskMask(backdrop, source: uint8): uint8 {.raises: [].} = proc maskMask(backdrop, source: uint8): uint8 =
## Masking masks ## Masking masks
((backdrop.uint32 * source) div 255).uint8 ((backdrop.uint32 * source) div 255).uint8
proc maskSubtract(backdrop, source: uint8): uint8 {.raises: [].} = proc maskSubtract(backdrop, source: uint8): uint8 =
((backdrop.uint32 * (255 - source)) div 255).uint8 ((backdrop.uint32 * (255 - source)) div 255).uint8
proc maskExclude(backdrop, source: uint8): uint8 {.raises: [].} = proc maskExclude(backdrop, source: uint8): uint8 =
max(backdrop, source) - min(backdrop, source) max(backdrop, source) - min(backdrop, source)
proc maskOverwrite(backdrop, source: uint8): uint8 {.raises: [].} = proc maskOverwrite(backdrop, source: uint8): uint8 =
source source
proc masker*(blendMode: BlendMode): Masker {.raises: [PixieError].} = proc masker*(blendMode: BlendMode): Masker {.raises: [PixieError].} =
@ -512,7 +512,7 @@ when defined(amd64) and not defined(pixieNoSimd):
MaskerSimd* = proc(blackdrop, source: M128i): M128i {.raises: [].} MaskerSimd* = proc(blackdrop, source: M128i): M128i {.raises: [].}
## Function signature returned by maskerSimd. ## Function signature returned by maskerSimd.
proc blendNormalSimd(backdrop, source: M128i): M128i {.raises: [].} = proc blendNormalSimd(backdrop, source: M128i): M128i =
let let
alphaMask = mm_set1_epi32(cast[int32](0xff000000)) alphaMask = mm_set1_epi32(cast[int32](0xff000000))
oddMask = mm_set1_epi16(cast[int16](0xff00)) oddMask = mm_set1_epi16(cast[int16](0xff00))
@ -541,7 +541,7 @@ when defined(amd64) and not defined(pixieNoSimd):
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8)) mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
) )
proc blendMaskSimd(backdrop, source: M128i): M128i {.raises: [].} = proc blendMaskSimd(backdrop, source: M128i): M128i =
let let
alphaMask = mm_set1_epi32(cast[int32](0xff000000)) alphaMask = mm_set1_epi32(cast[int32](0xff000000))
oddMask = mm_set1_epi16(cast[int16](0xff00)) oddMask = mm_set1_epi16(cast[int16](0xff00))
@ -562,7 +562,7 @@ when defined(amd64) and not defined(pixieNoSimd):
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8)) mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
proc blendOverwriteSimd(backdrop, source: M128i): M128i {.raises: [].} = proc blendOverwriteSimd(backdrop, source: M128i): M128i =
source source
proc blenderSimd*(blendMode: BlendMode): BlenderSimd {.raises: [PixieError].} = proc blenderSimd*(blendMode: BlendMode): BlenderSimd {.raises: [PixieError].} =
@ -578,7 +578,7 @@ when defined(amd64) and not defined(pixieNoSimd):
## Is there a blend function for a given blend mode with SIMD support? ## Is there a blend function for a given blend mode with SIMD support?
blendMode in {bmNormal, bmMask, bmOverwrite} blendMode in {bmNormal, bmMask, bmOverwrite}
proc maskNormalSimd(backdrop, source: M128i): M128i {.raises: [].} = proc maskNormalSimd(backdrop, source: M128i): M128i =
## Blending masks ## Blending masks
let let
oddMask = mm_set1_epi16(cast[int16](0xff00)) oddMask = mm_set1_epi16(cast[int16](0xff00))
@ -615,7 +615,7 @@ when defined(amd64) and not defined(pixieNoSimd):
mm_or_si128(blendedEven, mm_slli_epi16(blendedOdd, 8)) mm_or_si128(blendedEven, mm_slli_epi16(blendedOdd, 8))
proc maskMaskSimd(backdrop, source: M128i): M128i {.raises: [].} = proc maskMaskSimd(backdrop, source: M128i): M128i =
let let
oddMask = mm_set1_epi16(cast[int16](0xff00)) oddMask = mm_set1_epi16(cast[int16](0xff00))
div255 = mm_set1_epi16(cast[int16](0x8081)) div255 = mm_set1_epi16(cast[int16](0x8081))

View file

@ -63,7 +63,7 @@ proc newContext*(width, height: int): Context {.inline, raises: [PixieError].} =
## Create a new Context that will draw to a new image of width and height. ## Create a new Context that will draw to a new image of width and height.
newContext(newImage(width, height)) newContext(newImage(width, height))
proc state(ctx: Context): ContextState {.raises: [PixieError].} = proc state(ctx: Context): ContextState =
result.fillStyle = ctx.fillStyle result.fillStyle = ctx.fillStyle
result.strokeStyle = ctx.strokeStyle result.strokeStyle = ctx.strokeStyle
result.globalAlpha = ctx.globalAlpha result.globalAlpha = ctx.globalAlpha
@ -130,9 +130,7 @@ proc restore*(ctx: Context) {.raises: [PixieError].} =
else: # Otherwise draw to the root image else: # Otherwise draw to the root image
ctx.image.draw(poppedLayer) ctx.image.draw(poppedLayer)
proc fill( proc fill(ctx: Context, image: Image, path: Path, windingRule: WindingRule) =
ctx: Context, image: Image, path: Path, windingRule: WindingRule
) {.raises: [PixieError].} =
var image = image var image = image
if ctx.globalAlpha != 1: if ctx.globalAlpha != 1:
@ -150,7 +148,7 @@ proc fill(
ctx.layer.applyOpacity(ctx.globalAlpha) ctx.layer.applyOpacity(ctx.globalAlpha)
ctx.restore() ctx.restore()
proc stroke(ctx: Context, image: Image, path: Path) {.raises: [PixieError].} = proc stroke(ctx: Context, image: Image, path: Path) =
var image = image var image = image
if ctx.globalAlpha != 1: if ctx.globalAlpha != 1:
@ -172,7 +170,7 @@ proc stroke(ctx: Context, image: Image, path: Path) {.raises: [PixieError].} =
ctx.layer.applyOpacity(ctx.globalAlpha) ctx.layer.applyOpacity(ctx.globalAlpha)
ctx.restore() ctx.restore()
proc newFont(ctx: Context): Font {.raises: [PixieError].} = proc newFont(ctx: Context): Font =
if ctx.font == "": if ctx.font == "":
raise newException(PixieError, "No font has been set on this Context") raise newException(PixieError, "No font has been set on this Context")
@ -182,9 +180,7 @@ proc newFont(ctx: Context): Font {.raises: [PixieError].} =
result = newFont(ctx.typefaces.getOrDefault(ctx.font, nil)) result = newFont(ctx.typefaces.getOrDefault(ctx.font, nil))
result.size = ctx.fontSize result.size = ctx.fontSize
proc fillText( proc fillText(ctx: Context, image: Image, text: string, at: Vec2) =
ctx: Context, image: Image, text: string, at: Vec2
) {.raises: [PixieError].} =
let font = newFont(ctx) let font = newFont(ctx)
# Canvas positions text relative to the alphabetic baseline by default # Canvas positions text relative to the alphabetic baseline by default
@ -210,9 +206,7 @@ proc fillText(
ctx.layer.applyOpacity(ctx.globalAlpha) ctx.layer.applyOpacity(ctx.globalAlpha)
ctx.restore() ctx.restore()
proc strokeText( proc strokeText(ctx: Context, image: Image, text: string, at: Vec2) =
ctx: Context, image: Image, text: string, at: Vec2
) {.raises: [PixieError].} =
let font = newFont(ctx) let font = newFont(ctx)
# Canvas positions text relative to the alphabetic baseline by default # Canvas positions text relative to the alphabetic baseline by default
@ -501,7 +495,7 @@ proc getLineDash*(ctx: Context): seq[float32] {.inline, raises: [].} =
proc setLineDash*(ctx: Context, lineDash: seq[float32]) {.inline, raises: [].} = proc setLineDash*(ctx: Context, lineDash: seq[float32]) {.inline, raises: [].} =
ctx.lineDash = lineDash ctx.lineDash = lineDash
proc getTransform*(ctx: Context): Mat3 {.inline, raises: []} = proc getTransform*(ctx: Context): Mat3 {.inline, raises: [].} =
## Retrieves the current transform matrix being applied to the context. ## Retrieves the current transform matrix being applied to the context.
ctx.mat ctx.mat

View file

@ -23,7 +23,7 @@ template failInvalid() =
when defined(release): when defined(release):
{.push checks: off.} {.push checks: off.}
proc decodeHeader(data: string): PngHeader {.raises: [PixieError].} = proc decodeHeader(data: string): PngHeader =
result.width = data.readUint32(0).swap().int result.width = data.readUint32(0).swap().int
result.height = data.readUint32(4).swap().int result.height = data.readUint32(4).swap().int
result.bitDepth = data.readUint8(8) result.bitDepth = data.readUint8(8)
@ -79,7 +79,7 @@ proc decodeHeader(data: string): PngHeader {.raises: [PixieError].} =
if result.interlaceMethod != 0: if result.interlaceMethod != 0:
raise newException(PixieError, "Interlaced PNG not yet supported") raise newException(PixieError, "Interlaced PNG not yet supported")
proc decodePalette(data: string): seq[ColorRGB] {.raises: [PixieError].} = proc decodePalette(data: string): seq[ColorRGB] =
if data.len == 0 or data.len mod 3 != 0: if data.len == 0 or data.len mod 3 != 0:
failInvalid() failInvalid()
@ -90,7 +90,7 @@ proc decodePalette(data: string): seq[ColorRGB] {.raises: [PixieError].} =
proc unfilter( proc unfilter(
uncompressed: string, height, rowBytes, bpp: int uncompressed: string, height, rowBytes, bpp: int
): string {.raises: [].} = ): string =
result.setLen(uncompressed.len - height) result.setLen(uncompressed.len - height)
template uncompressedIdx(x, y: int): int = template uncompressedIdx(x, y: int): int =
@ -164,7 +164,7 @@ proc decodeImageData(
header: PngHeader, header: PngHeader,
palette: seq[ColorRGB], palette: seq[ColorRGB],
transparency, data: string transparency, data: string
): seq[ColorRGBA] {.raises: [PixieError].} = ): seq[ColorRGBA] =
result.setLen(header.width * header.height) result.setLen(header.width * header.height)
let let

View file

@ -33,12 +33,12 @@ type
template failInvalid() = template failInvalid() =
raise newException(PixieError, "Invalid SVG data") raise newException(PixieError, "Invalid SVG data")
proc attrOrDefault(node: XmlNode, name, default: string): string {.raises: [].} = proc attrOrDefault(node: XmlNode, name, default: string): string =
result = node.attr(name) result = node.attr(name)
if result.len == 0: if result.len == 0:
result = default result = default
proc initCtx(): Ctx {.raises: [PixieError].} = proc initCtx(): Ctx =
result.display = true result.display = true
try: try:
result.fill = parseHtmlColor("black").rgbx result.fill = parseHtmlColor("black").rgbx
@ -317,7 +317,7 @@ proc decodeCtxInternal(inherited: Ctx, node: XmlNode): Ctx =
else: else:
failInvalidTransform(transform) failInvalidTransform(transform)
proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx {.raises: [PixieError].} = proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
try: try:
decodeCtxInternal(inherited, node) decodeCtxInternal(inherited, node)
except PixieError as e: except PixieError as e:
@ -326,14 +326,14 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx {.raises: [PixieError].} =
let e = getCurrentException() let e = getCurrentException()
raise newException(PixieError, e.msg, e) raise newException(PixieError, e.msg, e)
proc fill(img: Image, ctx: Ctx, path: Path) {.inline, raises: [PixieError].} = proc fill(img: Image, ctx: Ctx, path: Path) {.inline.} =
if ctx.display and ctx.opacity > 0: if ctx.display and ctx.opacity > 0:
let paint = newPaint(ctx.fill) let paint = newPaint(ctx.fill)
if ctx.opacity != 1: if ctx.opacity != 1:
paint.opacity = paint.opacity * ctx.opacity paint.opacity = paint.opacity * ctx.opacity
img.fillPath(path, paint, ctx.transform, ctx.fillRule) img.fillPath(path, paint, ctx.transform, ctx.fillRule)
proc stroke(img: Image, ctx: Ctx, path: Path) {.inline, raises: [PixieError].} = proc stroke(img: Image, ctx: Ctx, path: Path) {.inline.} =
if ctx.display and ctx.opacity > 0: if ctx.display and ctx.opacity > 0:
let paint = newPaint(ctx.stroke) let paint = newPaint(ctx.stroke)
if ctx.opacity != 1: if ctx.opacity != 1:
@ -556,9 +556,7 @@ proc drawInternal(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
else: else:
raise newException(PixieError, "Unsupported SVG tag: " & node.tag) raise newException(PixieError, "Unsupported SVG tag: " & node.tag)
proc draw( proc draw(img: Image, node: XmlNode, ctxStack: var seq[Ctx]) =
img: Image, node: XmlNode, ctxStack: var seq[Ctx]
) {.raises: [PixieError].} =
try: try:
drawInternal(img, node, ctxStack) drawInternal(img, node, ctxStack)
except PixieError as e: except PixieError as e:

View file

@ -341,27 +341,25 @@ template eofCheck(buf: string, readTo: int) =
template failUnsupported() = template failUnsupported() =
raise newException(PixieError, "Unsupported font data") raise newException(PixieError, "Unsupported font data")
proc readUint16Seq(buf: string, offset, len: int): seq[uint16] {.raises: [].} = proc readUint16Seq(buf: string, offset, len: int): seq[uint16] =
result = newSeq[uint16](len) result = newSeq[uint16](len)
for i in 0 ..< len: for i in 0 ..< len:
result[i] = buf.readUint16(offset + i * 2).swap() result[i] = buf.readUint16(offset + i * 2).swap()
proc readFixed32(buf: string, offset: int): float32 {.raises: [].} = proc readFixed32(buf: string, offset: int): float32 =
## Packed 32-bit value with major and minor version numbers. ## Packed 32-bit value with major and minor version numbers.
ceil(buf.readInt32(offset).swap().float32 / 65536.0 * 100000.0) / 100000.0 ceil(buf.readInt32(offset).swap().float32 / 65536.0 * 100000.0) / 100000.0
proc readFixed16(buf: string, offset: int): float32 {.raises: [].} = proc readFixed16(buf: string, offset: int): float32 =
## Reads 16-bit signed fixed number with the low 14 bits of fraction (2.14). ## Reads 16-bit signed fixed number with the low 14 bits of fraction (2.14).
buf.readInt16(offset).swap().float32 / 16384.0 buf.readInt16(offset).swap().float32 / 16384.0
proc readLongDateTime(buf: string, offset: int): float64 {.raises: [].} = proc readLongDateTime(buf: string, offset: int): float64 =
## Date and time represented in number of seconds since 12:00 midnight, ## Date and time represented in number of seconds since 12:00 midnight,
## January 1, 1904, UTC. ## January 1, 1904, UTC.
buf.readInt64(offset).swap().float64 - 2082844800 buf.readInt64(offset).swap().float64 - 2082844800
proc parseCmapTable( proc parseCmapTable(buf: string, offset: int): CmapTable =
buf: string, offset: int
): CmapTable {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 4) buf.eofCheck(i + 4)
@ -456,9 +454,7 @@ proc parseCmapTable(
# TODO implement other cmap platformIDs # TODO implement other cmap platformIDs
discard discard
proc parseHeadTable( proc parseHeadTable(buf: string, offset: int): HeadTable =
buf: string, offset: int
): HeadTable {.raises: [PixieError].} =
buf.eofCheck(offset + 54) buf.eofCheck(offset + 54)
result = HeadTable() result = HeadTable()
@ -487,9 +483,7 @@ proc parseHeadTable(
if result.glyphDataFormat != 0: if result.glyphDataFormat != 0:
failUnsupported() failUnsupported()
proc parseHheaTable( proc parseHheaTable(buf: string, offset: int): HheaTable =
buf: string, offset: int
): HheaTable {.raises: [PixieError].} =
buf.eofCheck(offset + 36) buf.eofCheck(offset + 36)
result = HheaTable() result = HheaTable()
@ -518,9 +512,7 @@ proc parseHheaTable(
failUnsupported() failUnsupported()
result.numberOfHMetrics = buf.readUint16(offset + 34).swap() result.numberOfHMetrics = buf.readUint16(offset + 34).swap()
proc parseMaxpTable( proc parseMaxpTable(buf: string, offset: int): MaxpTable =
buf: string, offset: int
): MaxpTable {.raises: [PixieError].} =
buf.eofCheck(offset + 32) buf.eofCheck(offset + 32)
result = MaxpTable() result = MaxpTable()
@ -544,7 +536,7 @@ proc parseMaxpTable(
proc parseHmtxTable( proc parseHmtxTable(
buf: string, offset: int, hhea: HheaTable, maxp: MaxpTable buf: string, offset: int, hhea: HheaTable, maxp: MaxpTable
): HmtxTable {.raises: [PixieError].} = ): HmtxTable =
var i = offset var i = offset
let let
@ -565,9 +557,7 @@ proc parseHmtxTable(
result.leftSideBearings.add(buf.readInt16(i).swap()) result.leftSideBearings.add(buf.readInt16(i).swap())
i += 2 i += 2
proc parseNameTable( proc parseNameTable(buf: string, offset: int): NameTable =
buf: string, offset: int
): NameTable {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 6) buf.eofCheck(i + 6)
@ -593,9 +583,7 @@ proc parseNameTable(
record.offset = buf.readUint16(i + 10).swap() record.offset = buf.readUint16(i + 10).swap()
i += 12 i += 12
proc parseOS2Table( proc parseOS2Table(buf: string, offset: int): OS2Table =
buf: string, offset: int
): OS2Table {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 78) buf.eofCheck(i + 78)
@ -659,7 +647,7 @@ proc parseOS2Table(
proc parseLocaTable( proc parseLocaTable(
buf: string, offset: int, head: HeadTable, maxp: MaxpTable buf: string, offset: int, head: HeadTable, maxp: MaxpTable
): LocaTable {.raises: [PixieError].} = ): LocaTable =
var i = offset var i = offset
result = LocaTable() result = LocaTable()
@ -678,15 +666,13 @@ proc parseLocaTable(
proc parseGlyfTable( proc parseGlyfTable(
buf: string, offset: int, loca: LocaTable buf: string, offset: int, loca: LocaTable
): GlyfTable {.raises: [].} = ): GlyfTable =
result = GlyfTable() result = GlyfTable()
result.offsets.setLen(loca.offsets.len) result.offsets.setLen(loca.offsets.len)
for glyphId in 0 ..< loca.offsets.len: for glyphId in 0 ..< loca.offsets.len:
result.offsets[glyphId] = offset.uint32 + loca.offsets[glyphId] result.offsets[glyphId] = offset.uint32 + loca.offsets[glyphId]
proc parseKernTable( proc parseKernTable(buf: string, offset: int): KernTable =
buf: string, offset: int
): KernTable {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 2) buf.eofCheck(i + 2)
@ -748,9 +734,7 @@ proc parseKernTable(
else: else:
failUnsupported() failUnsupported()
# proc parseLangSys( # proc parseLangSys(buf: string, offset: int): LangSys =
# buf: string, offset: int
# ): LangSys {.raises: [PixieError].} =
# var i = offset # var i = offset
# buf.eofCheck(i + 6) # buf.eofCheck(i + 6)
@ -838,16 +822,14 @@ proc parseKernTable(
# result.featureRecords.add(featureRecord) # result.featureRecords.add(featureRecord)
# i += 6 # i += 6
proc parseRangeRecord( proc parseRangeRecord(buf: string, offset: int): RangeRecord =
buf: string, offset: int
): RangeRecord {.raises: [PixieError].} =
buf.eofCheck(offset + 6) buf.eofCheck(offset + 6)
result.startGlyphID = buf.readUint16(offset + 0).swap() result.startGlyphID = buf.readUint16(offset + 0).swap()
result.endGlyphID = buf.readUint16(offset + 2).swap() result.endGlyphID = buf.readUint16(offset + 2).swap()
result.startCoverageIndex = buf.readUint16(offset + 4).swap() result.startCoverageIndex = buf.readUint16(offset + 4).swap()
proc parseCoverage(buf: string, offset: int): Coverage {.raises: [PixieError].} = proc parseCoverage(buf: string, offset: int): Coverage =
var i = offset var i = offset
buf.eofCheck(i + 4) buf.eofCheck(i + 4)
@ -885,7 +867,7 @@ proc parseCoverage(buf: string, offset: int): Coverage {.raises: [PixieError].}
else: else:
failUnsupported() failUnsupported()
proc valueFormatSize(valueFormat: uint16): int {.raises: [].} = proc valueFormatSize(valueFormat: uint16): int =
# countSetBits(valueFormat) * 2 # countSetBits(valueFormat) * 2
var var
n = valueFormat n = valueFormat
@ -897,7 +879,7 @@ proc valueFormatSize(valueFormat: uint16): int {.raises: [].} =
proc parseValueRecord( proc parseValueRecord(
buf: string, offset: int, valueFormat: uint16 buf: string, offset: int, valueFormat: uint16
): ValueRecord {.raises: [PixieError].} = ): ValueRecord =
buf.eofCheck(offset + valueFormatSize(valueFormat)) buf.eofCheck(offset + valueFormatSize(valueFormat))
var i = offset var i = offset
@ -928,7 +910,7 @@ proc parseValueRecord(
proc parsePairValueRecord( proc parsePairValueRecord(
buf: string, offset: int, valueFormat1, valueFormat2: uint16 buf: string, offset: int, valueFormat1, valueFormat2: uint16
): PairValueRecord {.raises: [PixieError].} = ): PairValueRecord =
var i = offset var i = offset
buf.eofCheck(i + 2) buf.eofCheck(i + 2)
@ -942,7 +924,7 @@ proc parsePairValueRecord(
proc parsePairSet( proc parsePairSet(
buf: string, offset: int, valueFormat1, valueFormat2: uint16 buf: string, offset: int, valueFormat1, valueFormat2: uint16
): PairSet {.raises: [PixieError].} = ): PairSet =
var i = offset var i = offset
buf.eofCheck(i + 2) buf.eofCheck(i + 2)
@ -961,7 +943,7 @@ proc parsePairSet(
proc parseClass2Record( proc parseClass2Record(
buf: string, offset: int, valueFormat1, valueFormat2: uint16 buf: string, offset: int, valueFormat1, valueFormat2: uint16
): Class2Record {.raises: [PixieError].} = ): Class2Record =
var i = offset var i = offset
buf.eofCheck( buf.eofCheck(
@ -974,7 +956,7 @@ proc parseClass2Record(
proc parseClass1Record( proc parseClass1Record(
buf: string, offset: int, valueFormat1, valueFormat2, class2Count: uint16 buf: string, offset: int, valueFormat1, valueFormat2, class2Count: uint16
): Class1Record {.raises: [PixieError].} = ): Class1Record =
var i = offset var i = offset
result.class2Records.setLen(class2Count.int) result.class2Records.setLen(class2Count.int)
@ -985,14 +967,14 @@ proc parseClass1Record(
proc parseClassRangeRecord( proc parseClassRangeRecord(
buf: string, offset: int buf: string, offset: int
): ClassRangeRecord {.raises: [PixieError].} = ): ClassRangeRecord =
buf.eofCheck(offset + 6) buf.eofCheck(offset + 6)
result.startGlyphID = buf.readUint16(offset + 0).swap() result.startGlyphID = buf.readUint16(offset + 0).swap()
result.endGlyphID = buf.readUint16(offset + 2).swap() result.endGlyphID = buf.readUint16(offset + 2).swap()
result.class = buf.readUint16(offset + 4).swap() result.class = buf.readUint16(offset + 4).swap()
proc parseClassDef(buf: string, offset: int): ClassDef {.raises: [PixieError].} = proc parseClassDef(buf: string, offset: int): ClassDef =
var i = offset var i = offset
buf.eofCheck(i + 2) buf.eofCheck(i + 2)
@ -1024,7 +1006,7 @@ proc parseClassDef(buf: string, offset: int): ClassDef {.raises: [PixieError].}
else: else:
failUnsupported() failUnsupported()
proc parsePairPos(buf: string, offset: int): PairPos {.raises: [PixieError].} = proc parsePairPos(buf: string, offset: int): PairPos =
var i = offset var i = offset
buf.eofCheck(i + 4) buf.eofCheck(i + 4)
@ -1157,9 +1139,7 @@ proc parsePairPos(buf: string, offset: int): PairPos {.raises: [PixieError].} =
else: else:
failUnsupported() failUnsupported()
proc parseLookup( proc parseLookup(buf: string, offset: int, gpos: GposTable): Lookup =
buf: string, offset: int, gpos: GposTable
): Lookup {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 6) buf.eofCheck(i + 6)
@ -1185,9 +1165,7 @@ proc parseLookup(
pairPos.classPairAdjustments.len > 0: pairPos.classPairAdjustments.len > 0:
gpos.lookupList.pairPosTables.add(pairPos) gpos.lookupList.pairPosTables.add(pairPos)
proc parseLookupList( proc parseLookupList(buf: string, offset: int, gpos: GposTable): LookupList =
buf: string, offset: int, gpos: GposTable
): LookupList {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 2) buf.eofCheck(i + 2)
@ -1202,9 +1180,7 @@ proc parseLookupList(
for lookupOffset in result.lookupoffsets: for lookupOffset in result.lookupoffsets:
result.lookups.add(parseLookup(buf, offset + lookupOffset.int, gpos)) result.lookups.add(parseLookup(buf, offset + lookupOffset.int, gpos))
proc parseGposTable( proc parseGposTable(buf: string, offset: int): GPOSTable =
buf: string, offset: int
): GPOSTable {.raises: [PixieError].} =
var i = offset var i = offset
buf.eofCheck(i + 10) buf.eofCheck(i + 10)
@ -1235,9 +1211,7 @@ proc parseGposTable(
result.lookupList = result.lookupList =
parseLookupList(buf, offset + result.lookupListOffset.int, result) parseLookupList(buf, offset + result.lookupListOffset.int, result)
proc parsePostTable( proc parsePostTable(buf: string, offset: int): PostTable =
buf: string, offset: int
): PostTable {.raises: [PixieError].} =
buf.eofCheck(offset + 14) buf.eofCheck(offset + 14)
result = PostTable() result = PostTable()
@ -1247,14 +1221,14 @@ proc parsePostTable(
result.underlineThickness = buf.readInt16(offset + 10).swap() result.underlineThickness = buf.readInt16(offset + 10).swap()
result.isFixedPitch = buf.readUint32(offset + 12).swap() result.isFixedPitch = buf.readUint32(offset + 12).swap()
proc getGlyphId(opentype: OpenType, rune: Rune): uint16 {.inline, raises: [].} = proc getGlyphId(opentype: OpenType, rune: Rune): uint16 =
result = opentype.cmap.runeToGlyphId.getOrDefault(rune, 0) result = opentype.cmap.runeToGlyphId.getOrDefault(rune, 0)
proc parseGlyph(opentype: OpenType, glyphId: uint16): Path {.raises: [PixieError].} proc parseGlyph(opentype: OpenType, glyphId: uint16): Path {.raises: [PixieError].}
proc parseGlyphPath( proc parseGlyphPath(
buf: string, offset, numberOfContours: int buf: string, offset, numberOfContours: int
): Path {.raises: [PixieError].} = ): Path =
if numberOfContours < 0: if numberOfContours < 0:
raise newException(PixieError, "Glyph numberOfContours must be >= 0") raise newException(PixieError, "Glyph numberOfContours must be >= 0")
@ -1387,9 +1361,7 @@ proc parseGlyphPath(
result.closePath() result.closePath()
proc parseCompositeGlyph( proc parseCompositeGlyph(opentype: OpenType, offset: int): Path =
opentype: OpenType, offset: int
): Path {.raises: [PixieError].} =
result = newPath() result = newPath()
var var
@ -1486,7 +1458,7 @@ proc parseCompositeGlyph(
proc parseGlyph( proc parseGlyph(
opentype: OpenType, glyphId: uint16 opentype: OpenType, glyphId: uint16
): Path {.raises: [PixieError].} = ): Path =
if glyphId.int >= opentype.glyf.offsets.len: if glyphId.int >= opentype.glyf.offsets.len:
raise newException(PixieError, "Invalid glyph ID " & $glyphId) raise newException(PixieError, "Invalid glyph ID " & $glyphId)
@ -1516,7 +1488,7 @@ proc parseGlyph(
proc parseGlyph( proc parseGlyph(
opentype: OpenType, rune: Rune opentype: OpenType, rune: Rune
): Path {.inline, raises: [PixieError].} = ): Path {.inline.} =
opentype.parseGlyph(opentype.getGlyphId(rune)) opentype.parseGlyph(opentype.getGlyphId(rune))
proc getGlyphPath*( proc getGlyphPath*(

View file

@ -23,7 +23,7 @@ proc getKerningAdjustment*(
template failInvalid() = template failInvalid() =
raise newException(PixieError, "Invalid SVG font data") raise newException(PixieError, "Invalid SVG font data")
proc parseFloat(node: XmlNode, attr: string): float32 {.raises: [PixieError].} = proc parseFloat(node: XmlNode, attr: string): float32 =
let value = node.attr(attr) let value = node.attr(attr)
if value.len == 0: if value.len == 0:
raise newException(PixieError, "SVG font missing attr " & attr) raise newException(PixieError, "SVG font missing attr " & attr)

View file

@ -76,19 +76,19 @@ proc lineHeight*(typeface: Typeface): float32 {.inline, raises: [].} =
## The default line height in font units. ## The default line height in font units.
typeface.ascent - typeface.descent + typeface.lineGap typeface.ascent - typeface.descent + typeface.lineGap
proc underlinePosition(typeface: Typeface): float32 {.raises: [].} = proc underlinePosition(typeface: Typeface): float32 =
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.post.underlinePosition.float32 result = typeface.opentype.post.underlinePosition.float32
proc underlineThickness(typeface: Typeface): float32 {.raises: [].} = proc underlineThickness(typeface: Typeface): float32 =
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.post.underlineThickness.float32 result = typeface.opentype.post.underlineThickness.float32
proc strikeoutPosition(typeface: Typeface): float32 {.raises: [].} = proc strikeoutPosition(typeface: Typeface): float32 =
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.os2.yStrikeoutPosition.float32 result = typeface.opentype.os2.yStrikeoutPosition.float32
proc strikeoutThickness(typeface: Typeface): float32 {.raises: [].} = proc strikeoutThickness(typeface: Typeface): float32 =
if typeface.opentype != nil: if typeface.opentype != nil:
result = typeface.opentype.os2.yStrikeoutSize.float32 result = typeface.opentype.os2.yStrikeoutSize.float32
@ -152,7 +152,7 @@ proc newSpan*(text: string, font: Font): Span {.raises: [].} =
result.text = text result.text = text
result.font = font result.font = font
proc convertTextCase(runes: var seq[Rune], textCase: TextCase) {.raises: [].} = proc convertTextCase(runes: var seq[Rune], textCase: TextCase) =
case textCase: case textCase:
of tcNormal: of tcNormal:
discard discard
@ -169,7 +169,7 @@ proc convertTextCase(runes: var seq[Rune], textCase: TextCase) {.raises: [].} =
rune = rune.toUpper() rune = rune.toUpper()
prevRune = rune prevRune = rune
proc canWrap(rune: Rune): bool {.inline, raises: [].} = proc canWrap(rune: Rune): bool {.inline.} =
rune == Rune(32) or rune.isWhiteSpace() rune == Rune(32) or rune.isWhiteSpace()
proc typeset*( proc typeset*(
@ -447,7 +447,7 @@ proc textUber(
miterLimit = defaultMiterLimit, miterLimit = defaultMiterLimit,
dashes: seq[float32] = @[], dashes: seq[float32] = @[],
stroke: static[bool] = false stroke: static[bool] = false
) {.raises: [PixieError].} = ) =
var line: int var line: int
for spanIndex, (start, stop) in arrangement.spans: for spanIndex, (start, stop) in arrangement.spans:
let let

View file

@ -884,10 +884,10 @@ proc draw*(
proc drawTiled*( proc drawTiled*(
dst, src: Image, mat: Mat3, blendMode = bmNormal dst, src: Image, mat: Mat3, blendMode = bmNormal
) {.raises: [PixieError]} = ) {.raises: [PixieError].} =
dst.drawCorrect(src, mat, true, blendMode) dst.drawCorrect(src, mat, true, blendMode)
proc resize*(srcImage: Image, width, height: int): Image {.raises: [PixieError]} = proc resize*(srcImage: Image, width, height: int): Image {.raises: [PixieError].} =
## Resize an image to a given height and width. ## Resize an image to a given height and width.
if width == srcImage.width and height == srcImage.height: if width == srcImage.width and height == srcImage.height:
result = srcImage.copy() result = srcImage.copy()
@ -904,7 +904,7 @@ proc resize*(srcImage: Image, width, height: int): Image {.raises: [PixieError]}
proc shadow*( proc shadow*(
image: Image, offset: Vec2, spread, blur: float32, color: SomeColor image: Image, offset: Vec2, spread, blur: float32, color: SomeColor
): Image {.raises: [PixieError]} = ): Image {.raises: [PixieError].} =
## 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 let
mask = image.newMask() mask = image.newMask()
@ -916,7 +916,7 @@ proc shadow*(
result.fill(color) result.fill(color)
result.draw(shifted, blendMode = bmMask) result.draw(shifted, blendMode = bmMask)
proc superImage*(image: Image, x, y, w, h: int): Image {.raises: [PixieError]} = proc superImage*(image: Image, x, y, w, h: int): Image {.raises: [PixieError].} =
## Either cuts a sub image or returns a super image with padded transparency. ## Either cuts a sub image or returns a super image with padded transparency.
if x >= 0 and x + w <= image.width and y >= 0 and y + h <= image.height: if x >= 0 and x + w <= image.width and y >= 0 and y + h <= image.height:
result = image.subImage(x, y, w, h) result = image.subImage(x, y, w, h)

View file

@ -3,7 +3,7 @@ import chroma, vmath
when defined(amd64) and not defined(pixieNoSimd): when defined(amd64) and not defined(pixieNoSimd):
import nimsimd/sse2 import nimsimd/sse2
proc gaussianKernel*(radius: int): seq[uint32] = proc gaussianKernel*(radius: int): seq[uint32] {.raises: [].} =
## Compute lookup table for 1d Gaussian kernel. ## Compute lookup table for 1d Gaussian kernel.
## Values are [0, 255] * 1024. ## Values are [0, 255] * 1024.
result.setLen(radius * 2 + 1) result.setLen(radius * 2 + 1)
@ -23,7 +23,7 @@ proc gaussianKernel*(radius: int): seq[uint32] =
for i, f in floats: for i, f in floats:
result[i] = round(f * 255 * 1024).uint32 result[i] = round(f * 255 * 1024).uint32
proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX = proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
if opacity == 0: if opacity == 0:
rgbx(0, 0, 0, 0) rgbx(0, 0, 0, 0)
else: else:
@ -35,7 +35,7 @@ proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX =
a = ((color.a * x) div 255).uint8 a = ((color.a * x) div 255).uint8
rgbx(r, g, b, a) rgbx(r, g, b, a)
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) = proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
## 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:
@ -46,7 +46,7 @@ proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
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 | ColorRGBX]) = proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) {.raises: [].} =
## 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):
@ -94,7 +94,7 @@ proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
data[j] = c data[j] = c
when defined(amd64) and not defined(pixieNoSimd): when defined(amd64) and not defined(pixieNoSimd):
proc packAlphaValues*(v: M128i): M128i {.inline.} = proc packAlphaValues*(v: M128i): M128i {.inline, raises: [].} =
## Shuffle the alpha values for these 4 colors to the first 4 bytes ## Shuffle the alpha values for these 4 colors to the first 4 bytes
result = mm_srli_epi32(v, 24) result = mm_srli_epi32(v, 24)
let let
@ -105,7 +105,7 @@ when defined(amd64) and not defined(pixieNoSimd):
result = mm_or_si128(mm_or_si128(result, i), mm_or_si128(j, k)) result = mm_or_si128(mm_or_si128(result, i), mm_or_si128(j, k))
result = mm_and_si128(result, first32) result = mm_and_si128(result, first32)
proc unpackAlphaValues*(v: M128i): M128i {.inline.} = proc unpackAlphaValues*(v: M128i): M128i {.inline, raises: [].} =
## Unpack the first 32 bits into 4 rgba(0, 0, 0, value) ## Unpack the first 32 bits into 4 rgba(0, 0, 0, value)
let mask = cast[M128i]([uint8.high.uint64, 0]) let mask = cast[M128i]([uint8.high.uint64, 0])

View file

@ -64,7 +64,7 @@ converter parseSomePaint*(
elif type(paint) is Paint: elif type(paint) is Paint:
paint paint
proc toLineSpace(at, to, point: Vec2): float32 {.inline, raises: [].} = proc toLineSpace(at, to, point: Vec2): float32 {.inline.} =
## Convert position on to where it would fall on a line between at and to. ## Convert position on to where it would fall on a line between at and to.
let let
d = to - at d = to - at
@ -73,7 +73,7 @@ proc toLineSpace(at, to, point: Vec2): float32 {.inline, raises: [].} =
proc gradientPut( proc gradientPut(
image: Image, paint: Paint, x, y: int, t: float32, stops: seq[ColorStop] image: Image, paint: Paint, x, y: int, t: float32, stops: seq[ColorStop]
) {.raises: [].} = ) =
## Put an gradient color based on `t` - where are we related to a line. ## Put an gradient color based on `t` - where are we related to a line.
var index = -1 var index = -1
for i, stop in stops: for i, stop in stops:
@ -100,7 +100,7 @@ proc gradientPut(
color.a *= paint.opacity color.a *= paint.opacity
image.setRgbaUnsafe(x, y, color.rgbx()) image.setRgbaUnsafe(x, y, color.rgbx())
proc fillGradientLinear(image: Image, paint: Paint) {.raises: [PixieError].} = proc fillGradientLinear(image: Image, paint: Paint) =
## Fills a linear gradient. ## Fills a linear gradient.
if paint.gradientHandlePositions.len != 2: if paint.gradientHandlePositions.len != 2:
@ -122,7 +122,7 @@ proc fillGradientLinear(image: Image, paint: Paint) {.raises: [PixieError].} =
t = toLineSpace(at, to, xy) t = toLineSpace(at, to, xy)
image.gradientPut(paint, x, y, t, paint.gradientStops) image.gradientPut(paint, x, y, t, paint.gradientStops)
proc fillGradientRadial(image: Image, paint: Paint) {.raises: [PixieError].} = proc fillGradientRadial(image: Image, paint: Paint) =
## Fills a radial gradient. ## Fills a radial gradient.
if paint.gradientHandlePositions.len != 3: if paint.gradientHandlePositions.len != 3:
@ -153,7 +153,7 @@ proc fillGradientRadial(image: Image, paint: Paint) {.raises: [PixieError].} =
t = (mat * xy).length() t = (mat * xy).length()
image.gradientPut(paint, x, y, t, paint.gradientStops) image.gradientPut(paint, x, y, t, paint.gradientStops)
proc fillGradientAngular(image: Image, paint: Paint) {.raises: [PixieError].} = proc fillGradientAngular(image: Image, paint: Paint) =
## Fills an angular gradient. ## Fills an angular gradient.
if paint.gradientHandlePositions.len != 3: if paint.gradientHandlePositions.len != 3:

View file

@ -50,19 +50,19 @@ proc newPath*(): Path {.raises: [].} =
## Create a new Path. ## Create a new Path.
Path() Path()
proc pixelScale(transform: Mat3): float32 {.raises: [].} = proc pixelScale(transform: Mat3): float32 =
## What is the largest scale factor of this transform? ## What is the largest scale factor of this transform?
max( max(
vec2(transform[0, 0], transform[0, 1]).length, vec2(transform[0, 0], transform[0, 1]).length,
vec2(transform[1, 0], transform[1, 1]).length vec2(transform[1, 0], transform[1, 1]).length
) )
proc isRelative(kind: PathCommandKind): bool {.inline, raises: [].} = proc isRelative(kind: PathCommandKind): bool {.inline.} =
kind in { kind in {
RMove, RLine, TQuad, RTQuad, RHLine, RVLine, RCubic, RSCubic, RQuad, RArc RMove, RLine, TQuad, RTQuad, RHLine, RVLine, RCubic, RSCubic, RQuad, RArc
} }
proc parameterCount(kind: PathCommandKind): int {.raises: [].} = proc parameterCount(kind: PathCommandKind): int =
## Returns number of parameters a path command has. ## Returns number of parameters a path command has.
case kind: case kind:
of Close: 0 of Close: 0
@ -635,7 +635,7 @@ proc polygon*(
proc commandsToShapes( proc commandsToShapes(
path: Path, closeSubpaths = false, pixelScale: float32 = 1.0 path: Path, closeSubpaths = false, pixelScale: float32 = 1.0
): seq[seq[Vec2]] {.raises: [PixieError].} = ): seq[seq[Vec2]] =
## Converts SVG-like commands to sequences of vectors. ## Converts SVG-like commands to sequences of vectors.
var var
start, at: Vec2 start, at: Vec2
@ -999,7 +999,7 @@ proc commandsToShapes(
proc shapesToSegments( proc shapesToSegments(
shapes: seq[seq[Vec2]] shapes: seq[seq[Vec2]]
): seq[(Segment, int16)] {.raises: [].} = ): seq[(Segment, int16)] =
## Converts the shapes into a set of filtered segments with winding value. ## Converts the shapes into a set of filtered segments with winding value.
for shape in shapes: for shape in shapes:
for segment in shape.segments: for segment in shape.segments:
@ -1014,7 +1014,7 @@ proc shapesToSegments(
result.add((segment, winding)) result.add((segment, winding))
proc requiresAntiAliasing(segments: seq[(Segment, int16)]): bool {.raises: [].} = proc requiresAntiAliasing(segments: seq[(Segment, int16)]): bool =
## Returns true if the fill requires antialiasing. ## Returns true if the fill requires antialiasing.
template hasFractional(v: float32): bool = template hasFractional(v: float32): bool =
@ -1029,13 +1029,13 @@ proc requiresAntiAliasing(segments: seq[(Segment, int16)]): bool {.raises: [].}
# AA is required if all segments are not vertical or have fractional > 0 # AA is required if all segments are not vertical or have fractional > 0
return true return true
proc transform(shapes: var seq[seq[Vec2]], transform: Mat3) {.raises: [].} = proc transform(shapes: var seq[seq[Vec2]], transform: Mat3) =
if transform != mat3(): if transform != mat3():
for shape in shapes.mitems: for shape in shapes.mitems:
for vec in shape.mitems: for vec in shape.mitems:
vec = transform * vec vec = transform * vec
proc computeBounds(segments: seq[(Segment, int16)]): Rect {.raises: [].} = proc computeBounds(segments: seq[(Segment, int16)]): Rect =
## Compute the bounds of the segments. ## Compute the bounds of the segments.
var var
xMin = float32.high xMin = float32.high
@ -1067,7 +1067,7 @@ proc computeBounds*(
proc partitionSegments( proc partitionSegments(
segments: seq[(Segment, int16)], top, height: int segments: seq[(Segment, int16)], top, height: int
): Partitioning {.raises: [].} = ): Partitioning =
## Puts segments into the height partitions they intersect with. ## Puts segments into the height partitions they intersect with.
let let
maxPartitions = max(1, height div 10).uint32 maxPartitions = max(1, height div 10).uint32
@ -1091,9 +1091,7 @@ proc partitionSegments(
for i in atPartition .. toPartition: for i in atPartition .. toPartition:
result.partitions[i].add((segment, winding)) result.partitions[i].add((segment, winding))
proc getIndexForY( proc getIndexForY(partitioning: Partitioning, y: int): uint32 {.inline.} =
partitioning: Partitioning, y: int
): uint32 {.inline, raises: [].} =
if partitioning.partitionHeight == 0 or partitioning.partitions.len == 1: if partitioning.partitionHeight == 0 or partitioning.partitions.len == 1:
0.uint32 0.uint32
else: else:
@ -1104,7 +1102,7 @@ proc getIndexForY(
proc insertionSort( proc insertionSort(
a: var seq[(float32, int16)], lo, hi: int a: var seq[(float32, int16)], lo, hi: int
) {.inline, raises: [].} = ) {.inline.} =
for i in lo + 1 .. hi: for i in lo + 1 .. hi:
var var
j = i - 1 j = i - 1
@ -1114,7 +1112,7 @@ proc insertionSort(
dec j dec j
dec k dec k
proc sort(a: var seq[(float32, int16)], inl, inr: int) {.raises: [].} = proc sort(a: var seq[(float32, int16)], inl, inr: int) =
## Quicksort + insertion sort, in-place and faster than standard lib sort. ## Quicksort + insertion sort, in-place and faster than standard lib sort.
let n = inr - inl + 1 let n = inr - inl + 1
if n < 32: if n < 32:
@ -1138,7 +1136,7 @@ proc sort(a: var seq[(float32, int16)], inl, inr: int) {.raises: [].} =
proc shouldFill( proc shouldFill(
windingRule: WindingRule, count: int windingRule: WindingRule, count: int
): bool {.inline, raises: [].} = ): bool {.inline.} =
## Should we fill based on the current winding rule and count? ## Should we fill based on the current winding rule and count?
case windingRule: case windingRule:
of wrNonZero: of wrNonZero:
@ -1152,7 +1150,7 @@ iterator walk(
windingRule: WindingRule, windingRule: WindingRule,
y: int, y: int,
size: Vec2 size: Vec2
): (float32, float32, int32) {.raises: [].} = ): (float32, float32, int32) =
var var
prevAt: float32 prevAt: float32
count: int32 count: int32
@ -1184,7 +1182,7 @@ proc computeCoverages(
aa: bool, aa: bool,
partitioning: Partitioning, partitioning: Partitioning,
windingRule: WindingRule windingRule: WindingRule
) {.inline, raises: [].} = ) {.inline.} =
let let
quality = if aa: 5 else: 1 # Must divide 255 cleanly (1, 3, 5, 15, 17, 51, 85) quality = if aa: 5 else: 1 # Must divide 255 cleanly (1, 3, 5, 15, 17, 51, 85)
sampleCoverage = (255 div quality).uint8 sampleCoverage = (255 div quality).uint8
@ -1254,9 +1252,7 @@ proc computeCoverages(
for j in i ..< fillStart + fillLen: for j in i ..< fillStart + fillLen:
coverages[j - startX] += sampleCoverage coverages[j - startX] += sampleCoverage
proc clearUnsafe( proc clearUnsafe(target: Image | Mask, startX, startY, toX, toY: int) =
target: Image | Mask, startX, startY, toX, toY: int
) {.raises: [].} =
## Clears data from [start, to). ## Clears data from [start, to).
if startX == target.width or startY == target.height: if startX == target.width or startY == target.height:
return return
@ -1274,7 +1270,7 @@ proc fillCoverage(
startX, y: int, startX, y: int,
coverages: seq[uint8], coverages: seq[uint8],
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
var x = startX var x = startX
when defined(amd64) and not defined(pixieNoSimd): when defined(amd64) and not defined(pixieNoSimd):
if blendMode.hasSimdBlender(): if blendMode.hasSimdBlender():
@ -1361,7 +1357,7 @@ proc fillCoverage(
startX, y: int, startX, y: int,
coverages: seq[uint8], coverages: seq[uint8],
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
var x = startX var x = startX
when defined(amd64) and not defined(pixieNoSimd): when defined(amd64) and not defined(pixieNoSimd):
if blendMode.hasSimdMasker(): if blendMode.hasSimdMasker():
@ -1404,7 +1400,7 @@ proc fillHits(
numHits: int, numHits: int,
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
let blender = blendMode.blender() let blender = blendMode.blender()
var filledTo: int var filledTo: int
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, image.wh): for (prevAt, at, count) in hits.walk(numHits, windingRule, y, image.wh):
@ -1452,7 +1448,7 @@ proc fillHits(
numHits: int, numHits: int,
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
let masker = blendMode.masker() let masker = blendMode.masker()
var filledTo: int var filledTo: int
for (prevAt, at, count) in hits.walk(numHits, windingRule, y, mask.wh): for (prevAt, at, count) in hits.walk(numHits, windingRule, y, mask.wh):
@ -1496,7 +1492,7 @@ proc fillShapes(
color: SomeColor, color: SomeColor,
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
# Figure out the total bounds of all the shapes, # Figure out the total bounds of all the shapes,
# rasterize only within the total bounds # rasterize only within the total bounds
let let
@ -1554,7 +1550,7 @@ proc fillShapes(
shapes: seq[seq[Vec2]], shapes: seq[seq[Vec2]],
windingRule: WindingRule, windingRule: WindingRule,
blendMode: BlendMode blendMode: BlendMode
) {.raises: [PixieError].} = ) =
# Figure out the total bounds of all the shapes, # Figure out the total bounds of all the shapes,
# rasterize only within the total bounds # rasterize only within the total bounds
let let
@ -1592,11 +1588,11 @@ proc fillShapes(
mask.clearUnsafe(0, 0, 0, startY) mask.clearUnsafe(0, 0, 0, startY)
mask.clearUnsafe(0, pathHeight, 0, mask.height) mask.clearUnsafe(0, pathHeight, 0, mask.height)
proc miterLimitToAngle*(limit: float32): float32 {.inline, raises: [].} = proc miterLimitToAngle*(limit: float32): float32 {.inline.} =
## Converts miter-limit-ratio to miter-limit-angle. ## Converts miter-limit-ratio to miter-limit-angle.
arcsin(1 / limit) * 2 arcsin(1 / limit) * 2
proc angleToMiterLimit*(angle: float32): float32 {.inline, raises: [].} = proc angleToMiterLimit*(angle: float32): float32 {.inline.} =
## Converts miter-limit-angle to miter-limit-ratio. ## Converts miter-limit-angle to miter-limit-ratio.
1 / sin(angle / 2) 1 / sin(angle / 2)
@ -1607,7 +1603,7 @@ proc strokeShapes(
lineJoin: LineJoin, lineJoin: LineJoin,
miterLimit: float32, miterLimit: float32,
dashes: seq[float32] dashes: seq[float32]
): seq[seq[Vec2]] {.raises: [PixieError].} = ): seq[seq[Vec2]] =
if strokeWidth <= 0: if strokeWidth <= 0:
return return
@ -1743,7 +1739,7 @@ proc strokeShapes(
proc parseSomePath( proc parseSomePath(
path: SomePath, closeSubpaths: bool, pixelScale: float32 = 1.0 path: SomePath, closeSubpaths: bool, pixelScale: float32 = 1.0
): seq[seq[Vec2]] {.inline, raises: [PixieError].} = ): seq[seq[Vec2]] {.inline.} =
## Given SomePath, parse it in different ways. ## Given SomePath, parse it in different ways.
when type(path) is string: when type(path) is string:
parsePath(path).commandsToShapes(closeSubpaths, pixelScale) parsePath(path).commandsToShapes(closeSubpaths, pixelScale)
@ -1908,7 +1904,7 @@ proc overlaps(
shapes: seq[seq[Vec2]], shapes: seq[seq[Vec2]],
test: Vec2, test: Vec2,
windingRule: WindingRule windingRule: WindingRule
): bool {.raises: [].} = ): bool =
var hits: seq[(float32, int16)] var hits: seq[(float32, int16)]
let let