mirror of
https://github.com/aseprite/aseprite.git
synced 2024-12-27 03:16:58 +00:00
518 lines
15 KiB
Lua
518 lines
15 KiB
Lua
-- Copyright (C) 2020-2023 Igara Studio S.A.
|
|
--
|
|
-- This file is released under the terms of the MIT license.
|
|
-- Read LICENSE.txt for more information.
|
|
|
|
dofile('./test_utils.lua')
|
|
|
|
local colorModes = { ColorMode.RGB,
|
|
ColorMode.GRAY,
|
|
ColorMode.INDEXED }
|
|
|
|
local pencil = "pencil"
|
|
local pc = app.pixelColor
|
|
|
|
local function gray(g)
|
|
return pc.graya(g, 255)
|
|
end
|
|
|
|
function test_inks(colorMode)
|
|
-- Test ink over a transparent sprite
|
|
local s = Sprite(3, 3, colorMode)
|
|
local p, a, b, c, d
|
|
if colorMode == ColorMode.GRAY then
|
|
p = s.palettes[1]
|
|
a, b, c, d = gray(0), gray(64), gray(128), gray(255)
|
|
else
|
|
p = Palette()
|
|
p:resize(4)
|
|
p:setColor(0, Color(0, 0, 0))
|
|
p:setColor(1, Color(64, 64, 64))
|
|
p:setColor(2, Color(128, 128, 128))
|
|
p:setColor(3, Color(255, 255, 255))
|
|
s:setPalette(p)
|
|
|
|
a, b, c, d = 0, 1, 2, 3
|
|
if colorMode == ColorMode.RGB then
|
|
a = p:getColor(a).rgbaPixel
|
|
b = p:getColor(b).rgbaPixel
|
|
c = p:getColor(c).rgbaPixel
|
|
d = p:getColor(d).rgbaPixel
|
|
end
|
|
end
|
|
|
|
-- With simple ink opacity doesn't have affect (always the color)
|
|
local opacities = { 0, 128, 255 }
|
|
for i = 1,#opacities do
|
|
expect_img(app.activeImage,
|
|
{ 0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0 })
|
|
app.useTool{ tool=pencil, color=d, points={ Point(0, 0), Point(2, 2) },
|
|
ink=Ink.SIMPLE, opacity=opacities[i] }
|
|
expect_img(app.activeImage,
|
|
{ d, 0, 0,
|
|
0, d, 0,
|
|
0, 0, d })
|
|
if i < #opacities then app.undo() end
|
|
end
|
|
|
|
-- Check that painting with transparent index (color) on a
|
|
-- transparent layer (using any value of opacity) with alpha
|
|
-- compositing doesn't modify pixels
|
|
for i = 1,#opacities do
|
|
app.useTool{ tool=pencil, color=0, points={ Point(1, 1) },
|
|
ink=Ink.ALPHA_COMPOSITING, opacity=opacities[i] }
|
|
expect_img(app.activeImage,
|
|
{ d, 0, 0,
|
|
0, d, 0,
|
|
0, 0, d })
|
|
end
|
|
|
|
-- Convert to background layer
|
|
app.bgColor = Color{ index=0 }
|
|
app.command.BackgroundFromLayer()
|
|
|
|
app.useTool{ tool=pencil, color=d, points={ Point(0, 1), Point(2, 1) },
|
|
ink=Ink.ALPHA_COMPOSITING, opacity=64 }
|
|
expect_img(app.activeImage,
|
|
{ d, a, a,
|
|
b, d, b,
|
|
a, a, d })
|
|
|
|
app.useTool{ tool=pencil, color=d, points={ Point(0, 1) },
|
|
ink=Ink.ALPHA_COMPOSITING, opacity=86 }
|
|
expect_img(app.activeImage,
|
|
{ d, a, a,
|
|
c, d, b,
|
|
a, a, d })
|
|
|
|
----------------------------------------------------------------------
|
|
-- Inks with custom brushes
|
|
|
|
function test_custom_brush_inks(brushColorMode)
|
|
-- Colors in the brush image (ba, bb, bc, bd)
|
|
local ba, bb, bc, bd
|
|
if brushColorMode == ColorMode.RGB then
|
|
ba = Color(0, 0, 0)
|
|
bb = Color(64, 64, 64)
|
|
bc = Color(128, 128, 128)
|
|
bd = Color(255, 255, 255)
|
|
elseif brushColorMode == ColorMode.GRAY then
|
|
ba, bb, bc, bd = gray(0), gray(64), gray(128), gray(255)
|
|
else
|
|
ba, bb, bc, bd = 0, 1, 2, 3
|
|
end
|
|
|
|
local brushImage = Image(2, 2, brushColorMode)
|
|
array_to_pixels({ 0, bd,
|
|
bc, 0 }, brushImage)
|
|
local brush = Brush(brushImage)
|
|
|
|
-- da, db, dc, dd are the final result after painting the custom
|
|
-- brush in the sprite
|
|
local ra, rb, rc, rd
|
|
if s.colorMode ~= ColorMode.INDEXED and
|
|
brushColorMode == ColorMode.INDEXED then
|
|
-- For indexed images we take the index of the brush and use the
|
|
-- sprite palette, we are not sure if this in the future might
|
|
-- change, e.g. having the original palette that was used to
|
|
-- create the brush integrated to the brush itself, in that case
|
|
-- we should convert the brush index using the same brush
|
|
-- palette (instead of the sprite palette).
|
|
--
|
|
-- TODO check BrushInkProcessingBase comment for more information
|
|
if s.colorMode == ColorMode.RGB then
|
|
ra, rb, rc, rd =
|
|
p:getColor(ba).rgbaPixel,
|
|
p:getColor(bb).rgbaPixel,
|
|
p:getColor(bc).rgbaPixel,
|
|
p:getColor(bd).rgbaPixel
|
|
else
|
|
ra, rb, rc, rd =
|
|
p:getColor(ba).grayPixel,
|
|
p:getColor(bb).grayPixel,
|
|
p:getColor(bc).grayPixel,
|
|
p:getColor(bd).grayPixel
|
|
end
|
|
else
|
|
ra, rb, rc, rd = a, b, c, d
|
|
end
|
|
|
|
array_to_pixels({ a, a, a,
|
|
a, a, a,
|
|
a, a, a }, app.activeImage)
|
|
|
|
-- Simple
|
|
expect_img(app.activeImage,
|
|
{ a, a, a,
|
|
a, a, a,
|
|
a, a, a })
|
|
app.useTool{ tool=pencil, brush=brush, points={ Point(2, 2) },
|
|
ink=Ink.SIMPLE }
|
|
expect_img(app.activeImage,
|
|
{ a, a, a,
|
|
a, a, rd,
|
|
a, rc, a })
|
|
|
|
-- Alpha Compositing
|
|
app.useTool{ tool=pencil, brush=brush, points={ Point(1, 1) },
|
|
ink=Ink.ALPHA_COMPOSITING, opacity=255 }
|
|
expect_img(app.activeImage,
|
|
{ a, rd, a,
|
|
rc, a, rd,
|
|
a, rc, a })
|
|
|
|
local qc, qd
|
|
if s.colorMode == ColorMode.GRAY and
|
|
brushColorMode == ColorMode.INDEXED then
|
|
qc = gray(pc.grayaV(rc)/2)
|
|
qd = gray(pc.grayaV(rd)/2)
|
|
else
|
|
qc, qd = rb, rc
|
|
end
|
|
|
|
app.useTool{ tool=pencil, brush=brush, points={ Point(1, 2) },
|
|
ink=Ink.ALPHA_COMPOSITING, opacity=128 }
|
|
expect_img(app.activeImage,
|
|
{ a, rd, a,
|
|
rc, qd, rd,
|
|
qc, rc, a })
|
|
|
|
-- TODO test Lock Alpha, Copy Color+Alpha, Shading...
|
|
end
|
|
|
|
for j = 1,#colorModes do
|
|
test_custom_brush_inks(colorModes[j])
|
|
end
|
|
end
|
|
|
|
function test_alpha_compositing_on_indexed_with_full_opacity_and_repeated_colors_in_palette()
|
|
local s = Sprite(1, 1, ColorMode.INDEXED)
|
|
local p = Palette()
|
|
p:resize(5)
|
|
p:setColor(0, Color(0, 0, 0))
|
|
p:setColor(1, Color(64, 64, 64))
|
|
p:setColor(2, Color(128, 128, 128))
|
|
p:setColor(3, Color(128, 128, 128))
|
|
p:setColor(4, Color(255, 255, 255))
|
|
s:setPalette(p)
|
|
|
|
local inks = { Ink.SIMPLE, Ink.ALPHA_COMPOSITING }
|
|
|
|
-- k=1 -> transparent layer
|
|
-- k=2 -> background layer
|
|
for k=1,2 do
|
|
if k == 2 then app.command.BackgroundFromLayer() end
|
|
-- i=1 -> simple ink
|
|
-- i=2 -> alpha compositing ink
|
|
for i = 1,2 do
|
|
-- j=color index
|
|
for j = 0,4 do
|
|
expect_img(app.activeImage, { 0 })
|
|
app.useTool{ tool="pencil", color=j, points={ Point(0, 0) },
|
|
ink=inks[i], opacity=255 }
|
|
expect_img(app.activeImage, { j })
|
|
app.undo()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for i = 1,#colorModes do
|
|
test_inks(colorModes[i])
|
|
end
|
|
test_alpha_compositing_on_indexed_with_full_opacity_and_repeated_colors_in_palette()
|
|
|
|
----------------------------------------------------------------------
|
|
-- Test painting with transparent color on indexed
|
|
----------------------------------------------------------------------
|
|
|
|
do
|
|
local s = Sprite(2, 2, ColorMode.INDEXED)
|
|
s.transparentColor = 0
|
|
app.bgColor = 0
|
|
app.command.BackgroundFromLayer()
|
|
assert(app.activeLayer.isBackground)
|
|
expect_img(app.activeImage, { 0, 0,
|
|
0, 0 })
|
|
|
|
app.useTool{ tool="pencil", color=Color{r=0,g=0,b=0},
|
|
points={ Point(0, 0) },
|
|
ink=Ink.SIMPLE }
|
|
expect_img(app.activeImage, { 0, 0,
|
|
0, 0 })
|
|
|
|
-- Test that painting in the background layer with transparent color
|
|
-- with alpha compositing and all opacity=255, will use the transparent
|
|
-- index anyway. Reported here: https://github.com/aseprite/aseprite/issues/3047
|
|
app.useTool{ tool="pencil", color=0,
|
|
points={ Point(0, 0) },
|
|
ink=Ink.ALPHA_COMPOSITING,
|
|
opacity=255 }
|
|
expect_img(app.activeImage, { 0, 0,
|
|
0, 0 })
|
|
|
|
-- Other cases should keep working
|
|
local p = s.palettes[1]
|
|
|
|
-- palette with only 3 colors: white, gray (50%), black
|
|
p:setColor(0, Color{ r=255, g=255, b=255 })
|
|
p:setColor(1, Color{ r=128, g=128, b=128 })
|
|
p:setColor(2, Color{ r=0, g=0, b=0 })
|
|
app.useTool{ tool="paint_bucket", color=2,
|
|
points={ Point(0, 0) },
|
|
ink=Ink.SIMPLE }
|
|
expect_img(app.activeImage, { 2, 2,
|
|
2, 2 })
|
|
|
|
-- White over black w/opacity=50% => gray
|
|
app.useTool{ tool="pencil", color=0,
|
|
points={ Point(0, 0) },
|
|
ink=Ink.ALPHA_COMPOSITING,
|
|
opacity=128 }
|
|
expect_img(app.activeImage, { 1, 2,
|
|
2, 2 })
|
|
|
|
-- White over gray w/opacity=51% => white
|
|
app.useTool{ tool="pencil", color=0,
|
|
points={ Point(0, 0) },
|
|
ink=Ink.ALPHA_COMPOSITING,
|
|
opacity=129 }
|
|
expect_img(app.activeImage, { 0, 2,
|
|
2, 2 })
|
|
|
|
end
|
|
|
|
----------------------------------------------------------------------
|
|
-- Tests for Paint Bucket Tool with image brush and
|
|
-- pattern alignment SRC (ORIGIN) vs DST (TARGET)
|
|
----------------------------------------------------------------------
|
|
|
|
do
|
|
local s = Sprite(3, 3, ColorMode.INDEXED)
|
|
array_to_pixels({ 0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0 }, app.activeImage)
|
|
|
|
local brushImage = Image(2, 2, ColorMode.INDEXED)
|
|
array_to_pixels({ 0, 1,
|
|
2, 0 }, brushImage)
|
|
brush = Brush{
|
|
image=brushImage,
|
|
pattern=BrushPattern.ORIGIN
|
|
}
|
|
|
|
app.useTool{ tool="paint_bucket", brush=brush, points={ Point(0, 0) } }
|
|
expect_img(app.activeImage,
|
|
{ 0, 1, 0,
|
|
2, 0, 2,
|
|
0, 1, 0 })
|
|
app.undo()
|
|
app.useTool{ tool="paint_bucket", brush=brush, points={ Point(1, 0) } }
|
|
expect_img(app.activeImage,
|
|
{ 0, 1, 0,
|
|
2, 0, 2,
|
|
0, 1, 0 })
|
|
app.undo()
|
|
|
|
brush = Brush{
|
|
image=brushImage,
|
|
pattern=BrushPattern.TARGET
|
|
}
|
|
app.useTool{ tool="paint_bucket", brush=brush, points={ Point(1, 1) } }
|
|
expect_img(app.activeImage,
|
|
{ 0, 1, 0,
|
|
2, 0, 2,
|
|
0, 1, 0 })
|
|
app.undo()
|
|
app.useTool{ tool="paint_bucket", brush=brush, points={ Point(2, 1) } }
|
|
expect_img(app.activeImage,
|
|
{ 1, 0, 1,
|
|
0, 2, 0,
|
|
1, 0, 1})
|
|
end
|
|
|
|
----------------------------------------------------------------------
|
|
-- Tests for Eraser Tool, normal erase and replace color erasing
|
|
----------------------------------------------------------------------
|
|
do
|
|
-- Indexed image + background layer +
|
|
-- the mask color is in the palette and it's defined as
|
|
-- transparent color
|
|
local s = Sprite(3, 3, ColorMode.INDEXED)
|
|
local p = s.palettes[1]
|
|
p:setColor(0, Color{ r=0 , g=0 , b=0 , a=255 })
|
|
p:setColor(1, Color{ r=255, g=0 , b=0 , a=255 })
|
|
p:setColor(2, Color{ r=0 , g=255, b=0 , a=255 })
|
|
p:setColor(3, Color{ r=0 , g=0 , b=255, a=255 })
|
|
p:setColor(4, Color{ r=255, g=255, b=0 , a=255 })
|
|
p:setColor(5, Color{ r=255, g=255, b=255, a=255 })
|
|
p:setColor(6, Color{ r=0 , g=0 , b=0 , a=0 })
|
|
p:resize(7)
|
|
|
|
app.fgColor = 0
|
|
app.bgColor = 0
|
|
app.command.BackgroundFromLayer()
|
|
expect_img(app.activeImage,
|
|
{ 0, 0, 0,
|
|
0, 0, 0,
|
|
0, 0, 0 })
|
|
|
|
s.transparentColor = 6 -- mask color as transparent color
|
|
app.fgColor = 1
|
|
app.bgColor = 3
|
|
app.useTool{ tool='pencil',
|
|
points={ Point(0, 0), Point(2, 0)} }
|
|
app.useTool{ tool='pencil',
|
|
color=2,
|
|
points={ Point(0, 1), Point(2, 1)} }
|
|
app.useTool{ tool='pencil',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(0, 2), Point(2, 2)} }
|
|
expect_img(app.activeImage,
|
|
{ 1, 1, 1,
|
|
2, 2, 2,
|
|
3, 3, 3 })
|
|
|
|
app.fgColor = 2
|
|
app.bgColor = 6 -- (mask color)
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.LEFT,
|
|
points={ Point(0, 0), Point(0, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ 6, 1, 1,
|
|
6, 2, 2,
|
|
6, 3, 3 })
|
|
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(1, 0), Point(1, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ 6, 1, 1,
|
|
6, 6, 2,
|
|
6, 3, 3 })
|
|
end
|
|
|
|
-- Tests for Eraser Tool with RGBA image + background layer
|
|
do
|
|
local s = Sprite(3, 3, ColorMode.RGB)
|
|
local p = s.palettes[1]
|
|
local c0 = pc.rgba(0 , 0, 0, 255)
|
|
local c1 = pc.rgba(255, 0, 0, 255)
|
|
local c2 = pc.rgba(0 , 255, 0, 255)
|
|
local c3 = pc.rgba(0 , 0, 255, 255)
|
|
local c4 = pc.rgba(255, 255, 0, 255)
|
|
local c5 = pc.rgba(255, 255, 255, 255)
|
|
local c6 = pc.rgba(0 , 0, 0, 0)
|
|
p:setColor(0, c0)
|
|
p:setColor(1, c1)
|
|
p:setColor(2, c2)
|
|
p:setColor(3, c3)
|
|
p:setColor(4, c4)
|
|
p:setColor(5, c5)
|
|
p:setColor(6, c6)
|
|
p:resize(7)
|
|
|
|
app.fgColor = c0
|
|
app.bgColor = c0
|
|
app.command.BackgroundFromLayer()
|
|
expect_img(app.activeImage,
|
|
{ c0, c0, c0,
|
|
c0, c0, c0,
|
|
c0, c0, c0 })
|
|
|
|
app.fgColor = c1
|
|
app.bgColor = c3
|
|
app.useTool{ tool='pencil',
|
|
points={ Point(0, 0), Point(2, 0)} }
|
|
app.useTool{ tool='pencil',
|
|
color=c2,
|
|
points={ Point(0, 1), Point(2, 1)} }
|
|
app.useTool{ tool='pencil',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(0, 2), Point(2, 2)} }
|
|
expect_img(app.activeImage,
|
|
{ c1, c1, c1,
|
|
c2, c2, c2,
|
|
c3, c3, c3 })
|
|
|
|
app.fgColor = c2
|
|
app.bgColor = c6
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.LEFT,
|
|
points={ Point(0, 0), Point(0, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ c0, c1, c1,
|
|
c0, c2, c2,
|
|
c0, c3, c3 })
|
|
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(1, 0), Point(1, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ c0, c1, c1,
|
|
c0, c0, c2,
|
|
c0, c3, c3 })
|
|
end
|
|
|
|
-- Tests for Eraser Tool with GRAYSCALE image + background layer
|
|
do
|
|
local s = Sprite(3, 3, ColorMode.GRAYSCALE)
|
|
local p = s.palettes[1]
|
|
local c0 = pc.graya( 0, 255)
|
|
local c1 = pc.graya( 63, 255)
|
|
local c2 = pc.graya(127, 255)
|
|
local c3 = pc.graya(191, 255)
|
|
local c4 = pc.graya(255, 255)
|
|
local c5 = pc.graya( 0, 0)
|
|
p:setColor(0, c0)
|
|
p:setColor(1, c1)
|
|
p:setColor(2, c2)
|
|
p:setColor(3, c3)
|
|
p:setColor(4, c4)
|
|
p:setColor(5, c5)
|
|
p:resize(6)
|
|
|
|
app.fgColor = c0
|
|
app.bgColor = c0
|
|
app.command.BackgroundFromLayer()
|
|
expect_img(app.activeImage,
|
|
{ c0, c0, c0,
|
|
c0, c0, c0,
|
|
c0, c0, c0 })
|
|
|
|
app.fgColor = c1
|
|
app.bgColor = c3
|
|
app.useTool{ tool='pencil',
|
|
points={ Point(0, 0), Point(2, 0)} }
|
|
app.useTool{ tool='pencil',
|
|
color=c2,
|
|
points={ Point(0, 1), Point(2, 1)} }
|
|
app.useTool{ tool='pencil',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(0, 2), Point(2, 2)} }
|
|
expect_img(app.activeImage,
|
|
{ c1, c1, c1,
|
|
c2, c2, c2,
|
|
c3, c3, c3 })
|
|
|
|
app.fgColor = c2
|
|
app.bgColor = c5
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.LEFT,
|
|
points={ Point(0, 0), Point(0, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ c0, c1, c1,
|
|
c0, c2, c2,
|
|
c0, c3, c3 })
|
|
|
|
app.useTool{ tool='eraser',
|
|
button=MouseButton.RIGHT,
|
|
points={ Point(1, 0), Point(1, 2) } }
|
|
expect_img(app.activeImage,
|
|
{ c0, c1, c1,
|
|
c0, c0, c2,
|
|
c0, c3, c3 })
|
|
end
|