Merge remote-tracking branch 'tests/main'

This commit is contained in:
David Capello 2022-10-25 15:24:58 -03:00
commit c7cafca69a
75 changed files with 7288 additions and 8 deletions

View File

@ -64,13 +64,6 @@ jobs:
if [[ "${{ runner.os }}" == "Linux" ]] ; then
export XVFB=xvfb-run
fi
if [[ "${{ github.base_ref }}" == "beta" ]] || [[ "${{ github.ref }}" == "refs/heads/beta" ]] ; then
export TESTS_BRANCH=beta
else
export TESTS_BRANCH=main
fi
cd build
export ASEPRITE=$PWD/bin/aseprite
git clone --branch $TESTS_BRANCH --recursive https://github.com/aseprite/tests.git
export ASEPRITE=$PWD/build/bin/aseprite
cd tests
$XVFB bash run-tests.sh

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "tests/third_party/json"]
path = tests/third_party/json
url = https://github.com/aseprite/json.lua
[submodule "third_party/pixman"]
path = third_party/pixman
url = https://github.com/aseprite/pixman.git

21
tests/LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
Copyright (c) 2018-2022 Igara Studio S.A.
Copyright (c) 2018 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

31
tests/README.md Normal file
View File

@ -0,0 +1,31 @@
# Aseprite Tests
Test suite for [Aseprite](https://github.com/aseprite/aseprite)
to avoid breaking backward compatibility.
This project is cloned by the
[build.yml](https://github.com/aseprite/aseprite/blob/main/.github/workflows/build.yml) file
on Aseprite project to do several automated tests:
* Save/load file formats correctly. For this we have `.aseprite`, `.png`,
`.gif`, etc. files [sprites](https://github.com/aseprite/tests/tree/main/sprites)
folder.
* Test backward compatibility with [Aseprite CLI](https://www.aseprite.org/docs/cli/) options
* Future [scripting API](https://github.com/aseprite/api) using [scripts](https://github.com/aseprite/tests/tree/main/scripts)
## How to run tests?
You have to set the `ASEPRITE` environment variable pointing to the
Aseprite executable and then run `run-tests.sh` from Bash:
export ASEPRITE=$HOME/your-aseprite-build/bin/aseprite
git clone https://github.com/aseprite/tests.git
cd tests
bash run-tests.sh
You can filter some tests with a regex giving a parameter to
`run-tests.sh`, for example:
run-tests.sh color
Should run all tests which have the `color` word in their name.

61
tests/cli/file-formats.sh Normal file
View File

@ -0,0 +1,61 @@
#! /bin/bash
# Copyright (C) 2019 Igara Studio S.A.
# Create a simple image and save it in all formats using scripts
d=$t/file-formats
mkdir $d
cat >$d/gen.lua <<EOF
local a = Sprite(32, 32)
app.useTool{ points={{0,0},{31,31}}, tool='filled_ellipse', color=Color(255,255,255) }
a:saveAs('$d/test.aseprite')
a:saveAs('$d/test.gif')
a:saveAs('$d/test.ico')
a:saveAs('$d/test.jpg')
a:saveAs('$d/test.pcx')
a:saveAs('$d/test.svg')
a:saveAs('$d/test.tga')
a:saveAs('$d/test.webp')
EOF
$ASEPRITE -b -script "$d/gen.lua" || exit 1
# Load image and save in all formats using CLI
$ASEPRITE -b "$d/test.aseprite" \
-save-as "$d/test2.gif" \
-save-as "$d/test2.ico" \
-save-as "$d/test2.jpg" \
-save-as "$d/test2.pcx" \
-save-as "$d/test2.svg" \
-save-as "$d/test2.tga" \
-save-as "$d/test2.webp" \
|| exit 1
# Compare that all images are the same/equivalent
# Note: app.open() and Sprite{fromFile:} are the same
cat >$d/compare.lua <<EOF
local a = Sprite{ fromFile="$d/test.aseprite" }
local b = {
app.open("$d/test.gif"), app.open("$d/test2.gif"),
app.open("$d/test.ico"), app.open("$d/test2.ico"),
app.open("$d/test.jpg"), app.open("$d/test2.jpg"),
app.open("$d/test.pcx"), app.open("$d/test2.pcx"),
--app.open("$d/test.svg"), -- we don't support loading SVG files
app.open("$d/test.tga"), app.open("$d/test2.tga"),
app.open("$d/test.webp"), app.open("$d/test2.webp")
}
for i,c in ipairs(b) do
if c.colorMode == ColorMode.INDEXED then
app.activeSprite = c
app.command.ChangePixelFormat{ format="rgb" }
end
assert(c.colorMode == ColorMode.RGB)
if c.layers[1].isBackground then -- jpg and pcx
app.activeSprite = c
app.command.LayerFromBackground()
-- tolerance is 1 to remove jpg noise
app.command.ReplaceColor{ from=Color(0, 0, 0, 255), to=Color(0, 0, 0, 0), tolerance=1 }
app.command.ReplaceColor{ from=Color(255, 255, 255, 255), to=Color(255, 255, 255, 255), tolerance=1 }
end
assert(a.cels[1].image:isEqual(c.cels[1].image))
end
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1

7
tests/cli/help.sh Normal file
View File

@ -0,0 +1,7 @@
#! /bin/bash
# Copyright (C) 2018 Igara Studio S.A.
if ! $ASEPRITE --help | grep "\\-\\-help" > /dev/null ; then
echo "FAILED: --help doesn't include usage information"
exit 1
fi

10
tests/cli/list-layers.sh Normal file
View File

@ -0,0 +1,10 @@
#! /bin/bash
# Copyright (C) 2018 Igara Studio S.A.
expect "bg
fg" "$ASEPRITE -b --list-layers sprites/1empty3.aseprite"
expect "a
b
c
d" "$ASEPRITE -b --list-layers sprites/abcd.aseprite"

5
tests/cli/list-tags.sh Normal file
View File

@ -0,0 +1,5 @@
#! /bin/bash
# Copyright (C) 2018 Igara Studio S.A.
expect "a
b" "$ASEPRITE -b --list-tags sprites/1empty3.aseprite"

256
tests/cli/save-as.sh Normal file
View File

@ -0,0 +1,256 @@
#! /bin/bash
# Copyright (C) 2018-2021 Igara Studio S.A.
function list_files() {
oldwd=$(pwd $PWDARG)
cd $1 && ls -1 *.*
cd $oldwd
}
# --save-as
d=$t/save-as
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/image00.png" || exit 1
expect "image00.png
image01.png
image02.png" "list_files $d"
# --ignore-empty --save-as
d=$t/save-as-ignore-empty
$ASEPRITE -b sprites/1empty3.aseprite --ignore-empty --save-as $d/image00.png || exit 1
expect "image00.png
image02.png" "list_files $d"
# --split-layers --save-as
d=$t/save-as-split-layers
$ASEPRITE -b sprites/1empty3.aseprite --split-layers --save-as $d/layer.png || exit 1
expect "layer (bg) 0.png
layer (bg) 1.png
layer (bg) 2.png
layer (fg) 0.png
layer (fg) 1.png
layer (fg) 2.png" "list_files $d"
# --save-as {layer}
d=$t/save-as-layer
mkdir $d # TODO why do we need this?
$ASEPRITE -b sprites/1empty3.aseprite --save-as $d/layer-{layer}.gif || exit 1
expect "layer-bg.gif
layer-fg.gif" "list_files $d"
# --save-as frame8-test.png
d=$t/save-as-frame8-test
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame8-test.png" || exit 1
expect "frame8-test1.png
frame8-test2.png
frame8-test3.png" "list_files $d"
# --save-as frame-0.png
d=$t/save-as-frame-0
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-0.png" || exit 1
expect "frame-0.png
frame-1.png
frame-2.png" "list_files $d"
# --save-as frame-00.png
d=$t/save-as-frame-00
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-00.png" || exit 1
expect "frame-00.png
frame-01.png
frame-02.png" "list_files $d"
# --save-as frame-001.png
d=$t/save-as-frame-001
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-001.png" || exit 1
expect "frame-001.png
frame-002.png
frame-003.png" "list_files $d"
# --save-as frame-0032.png
d=$t/save-as-frame-0032
$ASEPRITE -b sprites/1empty3.aseprite --save-as "$d/frame-0032.png" || exit 1
expect "frame-0032.png
frame-0033.png
frame-0034.png" "list_files $d"
# --trim --save-as
d=$t/save-as-trim
$ASEPRITE -b --trim sprites/1empty3.aseprite --save-as "$d/trim-000.png" || exit 1
expect "trim-000.png
trim-001.png
trim-002.png" "list_files $d"
cat >$d/compare.lua <<EOF
local a = app.open("sprites/1empty3.aseprite")
assert(a.width == 32)
assert(a.height == 32)
app.command.FlattenLayers()
app.command.AutocropSprite()
assert(a.width == 22)
assert(a.height == 26)
local b = app.open("$d/trim-000.png")
assert(b.width == 22)
assert(b.height == 26)
local cleanImage = Image(b.spec)
cleanImage:clear()
for f = 1,3 do
local celA = a.layers[1]:cel(f)
local celB = b.layers[1]:cel(f)
if celA and celB then
assert(celA.image:isEqual(celB.image))
else
assert(not celA)
assert(not celB or celB.image:isEqual(cleanImage))
end
end
EOF
$ASEPRITE -b --script "$d/compare.lua" || exit 1
# -split-layers -trim -save-as
d=$t/save-as-split-layers-trim
$ASEPRITE -batch -split-layers -trim sprites/1empty3.aseprite -save-as "$d/{layer}{frame}.png" || exit 1
expect "bg0.png
bg1.png
bg2.png
fg0.png
fg1.png
fg2.png" "list_files $d"
cat >$d/compare.lua <<EOF
local orig = app.open("sprites/1empty3.aseprite")
local bg = app.open("$d/bg0.png")
local fg = app.open("$d/fg0.png")
assert(bg.width == 22)
assert(bg.height == 11)
assert(fg.width == 19)
assert(fg.height == 11)
for f = 1,3 do
local origCelBG = orig.layers[1]:cel(f)
local origCelFG = orig.layers[2]:cel(f)
local celBG = bg.layers[1]:cel(f)
local celFG = fg.layers[1]:cel(f)
if origCelBG and celBG then
assert(origCelBG.image:isEqual(celBG.image))
else
local cleanImage = Image(celBG.image.spec)
cleanImage:clear()
assert(not origCelBG)
assert(celBG.image:isEqual(cleanImage))
end
if origCelFG and celFG then
assert(origCelFG.image:isEqual(celFG.image))
else
local cleanImage = Image(celFG.image.spec)
cleanImage:clear()
assert(not origCelFG)
assert(celFG.image:isEqual(cleanImage))
end
end
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# --save-as without path
# https://github.com/aseprite/aseprite/issues/591
d=$t/save-as-without-path
mkdir $d
oldwd=$(pwd $PWDARG)
cd $d
$ASEPRITE -b -split-layers $oldwd/sprites/abcd.aseprite -save-as issue591.png || exit 1
if [[ ! -f "issue591 (a).png" ||
! -f "issue591 (b).png" ||
! -f "issue591 (c).png" ||
! -f "issue591 (d).png" ]]; then
echo "FAIL: Regression detected (issue 591)"
exit 1
fi
cd $oldwd
# --save-as group without showing hidden children
# https://github.com/aseprite/aseprite/issues/2084#issuecomment-525835889
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
# Ignore this test on Windows because we cannot give * as a parameter (?)
echo Do nothing
else
d=$t/save-as-groups-and-hidden
mkdir $d
$ASEPRITE -b sprites/groups2.aseprite -layer \* -save-as "$d/g2-all.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items -save-as "$d/g2-all-without-items.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer gun -save-as "$d/g2-all-without-gun1.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer sword -save-as "$d/g2-all-without-sword1.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items/gun -save-as "$d/g2-all-without-gun2.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer items/sword -save-as "$d/g2-all-without-sword2.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer \* -ignore-layer player -save-as "$d/g2-all-without-player.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer player -save-as "$d/g2-player.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer items -save-as "$d/g2-items.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer items/\* -save-as "$d/g2-items-all.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer sword -save-as "$d/g2-sword.png" || exit 1
$ASEPRITE -b sprites/groups2.aseprite -layer gun -save-as "$d/g2-gun.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer a -save-as "$d/g3-a.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer b -save-as "$d/g3-b.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer c -save-as "$d/g3-c.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/\* -save-as "$d/g3-a-all.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/\* -save-as "$d/g3-b-all.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/\* -save-as "$d/g3-c-all.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/a -save-as "$d/g3-aa.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/a -save-as "$d/g3-ba.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/a -save-as "$d/g3-ca.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/b -save-as "$d/g3-ab.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/b -save-as "$d/g3-bb.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/b -save-as "$d/g3-cb.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer a/c -save-as "$d/g3-ac.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer b/c -save-as "$d/g3-bc.png" || exit 1
$ASEPRITE -b sprites/groups3abc.aseprite -layer c/c -save-as "$d/g3-cc.png" || exit 1
cat >$d/compare.lua <<EOF
dofile('scripts/test_utils.lua')
local g2 = app.open("sprites/groups2.aseprite")
local g3 = app.open("sprites/groups3abc.aseprite")
function img(name)
local i = Image{ fromFile="$d/" .. name .. ".png" }
if not i then error('file ' .. name .. '.png does not exist') end
return i
end
expect_rendered_layers(img("g2-all"), g2, { "items/gun", "items/sword", "player/head", "player/body" })
expect_rendered_layers(img("g2-all-without-items"), g2, { "player/head", "player/body" })
expect_rendered_layers(img("g2-all-without-gun1"), g2, { "items/sword", "player/head", "player/body" })
expect_rendered_layers(img("g2-all-without-gun2"), g2, { "items/sword", "player/head", "player/body" })
expect_rendered_layers(img("g2-all-without-sword1"), g2, { "items/gun", "player/head", "player/body" })
expect_rendered_layers(img("g2-all-without-sword2"), g2, { "items/gun", "player/head", "player/body" })
expect_rendered_layers(img("g2-player"), g2, { "player/head", "player/body" })
expect_rendered_layers(img("g2-items"), g2, { "items/sword" })
expect_rendered_layers(img("g2-items-all"), g2, { "items/gun", "items/sword" })
expect_rendered_layers(img("g2-sword"), g2, { "items/sword" })
expect_rendered_layers(img("g2-gun"), g2, { "items/gun" })
expect_rendered_layers(img("g3-a"), g3, { "a/a", "a/b", "a/c" })
expect_rendered_layers(img("g3-b"), g3, { "b/a", "b/c" })
expect_rendered_layers(img("g3-c"), g3, { "c/c" })
expect_rendered_layers(img("g3-a-all"), g3, { "a/a", "a/b", "a/c" })
expect_rendered_layers(img("g3-b-all"), g3, { "b/a", "b/b", "b/c" })
expect_rendered_layers(img("g3-c-all"), g3, { "c/a", "c/b", "c/c" })
expect_rendered_layers(img("g3-aa"), g3, { "a/a" })
expect_rendered_layers(img("g3-ab"), g3, { "a/b" })
expect_rendered_layers(img("g3-ac"), g3, { "a/c" })
expect_rendered_layers(img("g3-ba"), g3, { "b/a" })
expect_rendered_layers(img("g3-bb"), g3, { "b/b" })
expect_rendered_layers(img("g3-bc"), g3, { "b/c" })
expect_rendered_layers(img("g3-ca"), g3, { "c/a" })
expect_rendered_layers(img("g3-cb"), g3, { "c/b" })
expect_rendered_layers(img("g3-cc"), g3, { "c/c" })
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
fi

402
tests/cli/sheet.sh Normal file
View File

@ -0,0 +1,402 @@
#! /bin/bash
# Copyright (C) 2019-2022 Igara Studio S.A.
# $1 = first sprite sheet json file
# $2 = second sprite sheet json file
function compare_sheet_data() {
cat $1 | grep -v "\"image\"" > $1-tmp
cat $2 | grep -v "\"image\"" > $2-tmp
diff -u $1-tmp $2-tmp
}
# --sheet and STDOUT
d=$t/sheet
mkdir $d # we need to create the directory because the >STDOUT redirection
if ! $ASEPRITE -b sprites/1empty3.aseprite --sheet "$d/sheet.png" > "$d/stdout.json" ; then
exit 1
fi
cat >$d/compare.lua <<EOF
local json = dofile('third_party/json/json.lua')
local data = json.decode(io.open('$d/stdout.json'):read('a'))
local frames = { data.frames['1empty3 0.aseprite'],
data.frames['1empty3 1.aseprite'],
data.frames['1empty3 2.aseprite'] }
assert(frames[1].frame.x == 0)
assert(frames[2].frame.x == 32)
assert(frames[3].frame.x == 64)
for i,v in ipairs(frames) do
assert(v.frame.y == 0)
assert(v.frame.w == 32)
assert(v.frame.h == 32)
end
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# --sheet --data
d0=$d
d=$t/sheet-data
$ASEPRITE -b sprites/1empty3.aseprite --sheet "$d/sheet.png" --data "$d/sheet.json" || exit 1
compare_sheet_data $d0/stdout.json $d/sheet.json || exit 1
cat >$d/compare.lua <<EOF
local orig = app.open("sprites/1empty3.aseprite")
local sheet = app.open("$d/sheet.png")
local expected = Image(orig.width*3, orig.height, orig.colorMode)
expected:clear()
for f = 1,3 do
expected:drawSprite(orig, f, (f-1)*orig.width, 0)
end
assert(expected:isEqual(sheet.cels[1].image))
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# vertical sprite sheet
d=$t/vertical-sheet
mkdir $d
# TODO this should be possible in a future
# $ASEPRITE -b sprites/1empty3.aseprite -sheet-type vertical --sheet "$d/sheet.png" --data "$d/sheet.json" || exit 1
cat >$d/create.lua <<EOF
local sprite = app.open("sprites/1empty3.aseprite")
app.command.ExportSpriteSheet {
type="vertical",
textureFilename="$d/sheet1.png",
dataFilename="$d/sheet1.json"
}
app.command.ExportSpriteSheet {
type=SpriteSheetType.VERTICAL,
textureFilename="$d/sheet2.png",
dataFilename="$d/sheet2.json"
}
EOF
$ASEPRITE -b -script "$d/create.lua" || exit 1
compare_sheet_data "$d/sheet1.json" "$d/sheet2.json" || exit 1
cmp "$d/sheet1.png" "$d/sheet2.png" || exit 1
cat >$d/compare.lua <<EOF
local orig = app.open("sprites/1empty3.aseprite")
local sheet = app.open("$d/sheet1.png")
local expected = Image(orig.width, orig.height*3, orig.colorMode)
expected:clear()
for f = 1,3 do
expected:drawSprite(orig, f, 0, (f-1)*orig.height)
end
assert(expected:isEqual(sheet.cels[1].image))
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# --split-layers --sheet --data
d=$t/split-layers-sheet-data
$ASEPRITE -b --split-layers sprites/1empty3.aseprite \
--filename-format "{layer}-{frame}" \
--sheet "$d/sheet.png" \
--data "$d/sheet.json" || exit 1
cat >$d/compare.lua <<EOF
local json = dofile('third_party/json/json.lua')
local data = json.decode(io.open('$d/sheet.json'):read('a'))
assert(data.meta.size.w == 96)
assert(data.meta.size.h == 64)
local orig = app.open("sprites/1empty3.aseprite")
local sheet = app.open("$d/sheet.png")
local expected = Image(orig.width*3, orig.height*2, orig.colorMode)
expected:clear()
for lay = 1,2 do
orig.layers[1].isVisible = (lay == 1)
orig.layers[2].isVisible = (lay == 2)
for frm = 1,3 do
local x, y = (frm-1)*orig.width, (lay-1)*orig.height
expected:drawSprite(orig, frm, x, y)
local frmData = data.frames[orig.layers[lay].name .. '-' .. (frm-1)]
assert(frmData.frame.x == x)
assert(frmData.frame.y == y)
assert(frmData.frame.w == 32)
assert(frmData.frame.h == 32)
end
end
assert(expected:isEqual(sheet.cels[1].image))
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# Test that the transparent color persists in the output sheet
d=$t/sheet-custom-transparent-index
if ! $ASEPRITE -b sprites/bg-index-3.aseprite -sheet "$d/sheet.aseprite" -data "$d/sheet.json" ; then
exit 1
fi
cat >$d/compare.lua <<EOF
local original = Sprite{ fromFile='sprites/bg-index-3.aseprite' }
assert(original.transparentColor == 3)
local sheet = Sprite{ fromFile='$d/sheet.aseprite' }
assert(sheet.transparentColor == 3)
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# Don't discard empty frames if -ignore-empty is not used (even if -trim is used)
# https://github.com/aseprite/aseprite/issues/2116
# -layer -trim -ignore-empty -list-tags -sheet -data
d=$t/sheet-trim-without-ignore-empty
$ASEPRITE -b \
-list-tags \
-layer "c" \
"sprites/tags3.aseprite" \
-trim \
-sheet-pack \
-sheet "$d/sheet1.png" \
-format json-array \
-data "$d/sheet1.json" || exit 1
$ASEPRITE -b \
-list-tags \
-layer "c" \
"sprites/tags3.aseprite" \
-trim -ignore-empty \
-sheet-pack \
-sheet "$d/sheet2.png" \
-format json-array \
-data "$d/sheet2.json" || exit 1
cat >$d/check.lua <<EOF
local json = dofile('third_party/json/json.lua')
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
assert(#sheet1.frames == 12)
assert(#sheet2.frames == 4)
EOF
$ASEPRITE -b -script "$d/check.lua" || exit 1
# -sheet -sheet-columns vs -sheet-rows
d=$t/sheet-columns-and-rows
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
-filename-format "{layer}{frame}" \
-sheet "$d/sheet1.png" \
-sheet-type rows \
-sheet-columns 3 \
-data "$d/sheet1.json" || exit $?
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
-filename-format "{layer}{frame}" \
-sheet "$d/sheet2.png" \
-sheet-type columns \
-sheet-rows 3 \
-data "$d/sheet2.json" || exit $?
$ASEPRITE -b \
-script-param file1=$d/sheet1.json \
-script-param file2=$d/sheet2.json \
-script scripts/compare_sprite_sheets.lua || exit $?
# -sheet -trim vs -trim-sprite
d=$t/sheet-columns-and-rows
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
-trim \
-filename-format "{layer}{frame}" \
-sheet "$d/sheet1.png" \
-data "$d/sheet1.json" || exit $?
$ASEPRITE -b -split-layers sprites/1empty3.aseprite \
-trim-sprite \
-filename-format "{layer}{frame}" \
-sheet "$d/sheet2.png" \
-data "$d/sheet2.json" || exit $?
$ASEPRITE -b \
-script-param file1=$d/sheet1.json \
-script-param file2=$d/sheet2.json \
-script scripts/compare_sprite_sheets.lua || exit $?
# Test all sprite sheet types
# -sheet horizontal/vertical/rows/columns/packed
d=$t/sheet-all-types
for type in horizontal vertical rows columns packed ; do
$ASEPRITE -b "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type.png" \
-format json-array -data "$d/$type.json" || exit $?
$ASEPRITE -b -split-layers "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type-layers.png" \
-format json-array -data "$d/$type-layers.json" || exit $?
$ASEPRITE -b -split-layers -merge-duplicates "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type-layers-merge-duplicates.png" \
-format json-array -data "$d/$type-layers-merge-duplicates.json" || exit $?
$ASEPRITE -b -split-tags "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type-tags.png" \
-format json-array -data "$d/$type-tags.json" || exit $?
$ASEPRITE -b -split-tags -trim "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type-tags-trim.png" \
-format json-array -data "$d/$type-tags-trim.json" || exit $?
$ASEPRITE -b -split-layers -split-tags "sprites/tags3.aseprite" \
-sheet-type $type -sheet "$d/$type-layer-tags.png" \
-format json-array -data "$d/$type-layer-tags.json" || exit $?
done
for type in horizontal vertical rows columns ; do
for subtype in "" "-layers" "-layers-merge-duplicates" "-tags" "-tags-trim" "-layer-tags" ; do
$ASEPRITE -b \
-script-param file1=$d/packed$subtype.json \
-script-param file2=$d/$type$subtype.json \
-script scripts/compare_sprite_sheets.lua || exit $?
done
done
# "Trim Cels" (-trim) with -merge-duplicates didn't generate the
# correct "spriteSourceSize" for each frame.
# https://igarastudio.zendesk.com/agent/tickets/407
d=$t/ticket-407
for layer in a b ; do
$ASEPRITE -b -layer "$layer" "sprites/point4frames.aseprite" \
-trim \
-data "$d/data1-$layer.json" \
-format json-array -sheet "$d/sheet1-$layer.png" || exit 1
$ASEPRITE -b -layer "$layer" "sprites/point4frames.aseprite" \
-trim -merge-duplicates \
-data "$d/data2-$layer.json" \
-format json-array -sheet "$d/sheet2-$layer.png" || exit 1
cat >$d/compare.lua <<EOF
local json = dofile('third_party/json/json.lua')
local data1 = json.decode(io.open('$d/data1-$layer.json'):read('a'))
local data2 = json.decode(io.open('$d/data2-$layer.json'):read('a'))
assert(#data1.frames == #data2.frames)
for i = 1,#data1.frames do
local a = data1.frames[i].spriteSourceSize
local b = data2.frames[i].spriteSourceSize
assert(a.x == b.x)
assert(a.y == b.y)
assert(a.w == b.w)
assert(a.h == b.h)
end
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
done
# Same problem as in ticket 407 but with "sourceSize" field and
# different sprites in the same texture atlas.
d=$t/ticket-407-w-atlas
$ASEPRITE -b \
-layer a "sprites/point4frames.aseprite" \
"sprites/point2frames.aseprite" \
-data "$d/data1.json" \
-format json-array -sheet "$d/sheet1.png" || exit 1
$ASEPRITE -b \
-layer a "sprites/point4frames.aseprite" \
"sprites/point2frames.aseprite" \
-trim \
-data "$d/data2.json" \
-format json-array -sheet-pack -sheet "$d/sheet2.png" || exit 1
cat >$d/compare.lua <<EOF
local json = dofile('third_party/json/json.lua')
local data1 = json.decode(io.open('$d/data1.json'):read('a'))
local data2 = json.decode(io.open('$d/data2.json'):read('a'))
assert(#data1.frames == #data2.frames)
for i = 1,#data1.frames do
local a = data1.frames[i].sourceSize
local b = data2.frames[i].sourceSize
assert(a.w == b.w)
assert(a.h == b.h)
end
EOF
$ASEPRITE -b -script "$d/compare.lua" || exit 1
# https://github.com/aseprite/aseprite/issues/2380
# Check that -split-layers and -list-layers include group information
d=$t/issue-2380
$ASEPRITE -b -trim -all-layers "sprites/groups3abc.aseprite" -data "$d/sheet1.json" -format json-array -sheet "$d/sheet1.png" -list-layers
$ASEPRITE -b -trim -all-layers -split-layers "sprites/groups3abc.aseprite" -data "$d/sheet2.json" -format json-array -sheet "$d/sheet2.png" -list-layers
cat >$d/check.lua <<EOF
local json = dofile('third_party/json/json.lua')
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
assert(#sheet1.meta.layers == 12)
assert(#sheet2.meta.layers == 12)
assert(json.encode(sheet1.meta.layers) == json.encode(sheet2.meta.layers))
EOF
$ASEPRITE -b -script "$d/check.lua" || exit 1
# https://github.com/aseprite/aseprite/issues/2432
# -ignore-layer is ignoring extra layers when -split-layers is used
d=$t/issue-2432
$ASEPRITE -b -trim -ignore-layer "c" -all-layers "sprites/groups3abc.aseprite" -data "$d/sheet1.json" -format json-array -sheet "$d/sheet1.png" -list-layers
$ASEPRITE -b -trim -ignore-layer "c" -all-layers -split-layers "sprites/groups3abc.aseprite" -data "$d/sheet2.json" -format json-array -sheet "$d/sheet2.png" -list-layers
cat >$d/check.lua <<EOF
local json = dofile('third_party/json/json.lua')
local sheet1 = json.decode(io.open('$d/sheet1.json'):read('a'))
local sheet2 = json.decode(io.open('$d/sheet2.json'):read('a'))
assert(#sheet1.meta.layers == 8)
assert(#sheet2.meta.layers == 8)
assert(json.encode(sheet1.meta.layers) == json.encode(sheet2.meta.layers))
EOF
$ASEPRITE -b -script "$d/check.lua" || exit 1
# https://github.com/aseprite/aseprite/issues/2600
# -merge-duplicates -split-layers -trim give incorrect 'frame' coordinates on linked cels
d=$t/issue-2600
$ASEPRITE -b -list-layers -format json-array -trim -merge-duplicates -split-layers -all-layers "sprites/link.aseprite" -data "$d/sheet.json" -sheet "$d/sheet.png"
cat >$d/check.lua <<EOF
local json = dofile('third_party/json/json.lua')
local sheet = json.decode(io.open('$d/sheet.json'):read('a'))
local restoredSprite = Sprite(sheet.frames[1].sourceSize.w, sheet.frames[1].sourceSize.h, ColorMode.RGB)
local spriteSheet = Image{ fromFile="$d/sheet.png" }
local lay = 1
repeat
local layerName = sheet.meta.layers[lay].name
local layer = restoredSprite.layers[lay]
for i=1, #sheet.frames do
if string.find(sheet.frames[i].filename, layerName) ~= nil then
local sample = sheet.frames[i]
local dotAseIndex = string.find(sample.filename, ".ase")
local frame = (string.sub(sample.filename, dotAseIndex - 2, dotAseIndex - 1)) + 1
for f=#restoredSprite.frames, frame-1 do
restoredSprite:newEmptyFrame()
end
local image = Image(sample.frame.w, sample.frame.h)
for y=0,image.height-1 do
for x=0,image.width-1 do
image:drawPixel(x, y, spriteSheet:getPixel(sample.frame.x + x, sample.frame.y + y))
end
end
restoredSprite:newCel(layer, frame, image, Point(sample.spriteSourceSize.x, sample.spriteSourceSize.y))
end
end
if lay < #sheet.meta.layers then
restoredSprite:newLayer()
end
lay = lay + 1
until(lay > #sheet.meta.layers)
app.activeSprite = restoredSprite
app.activeLayer = restoredSprite.layers[#restoredSprite.layers]
for i=1,#restoredSprite.layers-1 do
app.command.MergeDownLayer()
end
local orig = app.open("sprites/link.aseprite")
app.activeSprite = orig
app.activeLayer = orig.layers[#orig.layers]
for i=1,#orig.layers-1 do
app.command.MergeDownLayer()
end
assert(orig.width == restoredSprite.width)
assert(orig.height == restoredSprite.height)
assert(#orig.frames == #restoredSprite.frames)
for fr=1,#restoredSprite.frames do
for celIndex1=1,#restoredSprite.cels do
if restoredSprite.cels[celIndex1].frameNumber == fr then
for celIndex2=1,#orig.cels do
if orig.cels[celIndex2].frameNumber == fr then
assert(orig.cels[celIndex2].position == restoredSprite.cels[celIndex1].position)
if orig.cels[celIndex2].image ~= nil and restoredSprite.cels[celIndex1].image ~= nil then
assert(orig.cels[celIndex2].image:isEqual(restoredSprite.cels[celIndex1].image))
end
end
end
end
end
end
EOF
$ASEPRITE -b -script "$d/check.lua" || exit 1

7
tests/cli/version.sh Normal file
View File

@ -0,0 +1,7 @@
#! /bin/bash
# Copyright (C) 2018 Igara Studio S.A.
if ! $ASEPRITE --version | grep "Aseprite 1\\." > /dev/null ; then
echo "FAILED: --version doesn't include 'Aseprite 1.' string"
exit 1
fi

107
tests/run-tests.sh Executable file
View File

@ -0,0 +1,107 @@
#! /bin/bash
# Copyright (C) 2018 Igara Studio S.A.
# Copyright (C) 2018 David Capello
if [[ "$ASEPRITE" == "" ]]; then
echo ASEPRITE env var must be pointing to the Aseprite executable
exit 1
fi
function fail() {
echo FAIL
echo $BASH_SOURCE:$BASH_LINENO: error: $*
exit 1
}
function expect() {
if [[ $1 != "$($2 | tr -d "\r")" ]] ; then
echo "FAILED: $2"
echo "EXPECTED: $1"
echo "RESULT: $($2)"
exit 1
fi
}
# General information
echo ----------------------------------------------------------------------
echo $ASEPRITE --version
$ASEPRITE --version
filter="$*"
if [[ "$filter" != "" ]]; then
echo Filter: $filter
fi
t=$(mktemp -d)
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
PWDARG=-W
t=$(cd "$t" && pwd $PWDARG)
else
PWDARG=
fi
echo Temp dir: $t
export ASEPRITE_USER_FOLDER=$t
if [[ "$filter" == "" ]] || [[ "console" =~ $filter ]]; then
echo ----------------------------------------------------------------------
echo "Testing console..."
echo "uname=$(uname)"
$ASEPRITE -b --script scripts/console_assert.lua >$t/tmp 2>&1
! grep -q "this should be in the output" $t/tmp && fail "print() text not found in output"
! grep -q "assertion failed" $t/tmp && fail "assert() text not found in output"
grep -q "this should not be in the output" $t/tmp && fail "text that shouldn't be in the output is"
if [[ "$(uname)" =~ "MINGW" ]] || [[ "$(uname)" =~ "MSYS" ]] ; then
echo Ignore console tests on Windows
else
$ASEPRITE -b --script scripts/console_print.lua >$t/tmp 2>&1
cat >$t/tmp_expected <<EOF
hello world
1 2 3
EOF
! diff -u $t/tmp $t/tmp_expected && fail
fi
fi
first=0
result=0
for script in scripts/*.lua ; do
[[ $script =~ console ]] && continue
if [[ "$filter" != "" ]]; then
[[ $script =~ $filter ]] || continue
fi
if [ $first == 0 ]; then
echo ----------------------------------------------------------------------
echo "Testing scripts..."
first=1
fi
echo "Running $script"
if ! $ASEPRITE -b --script $script >$t/tmp 2>&1 ; then
echo FAILED && cat $t/tmp
result=1
fi
done
first=0
for script in cli/*.sh ; do
if [[ "$filter" == "" ]] || [[ $script =~ $filter ]]; then
if [ $first == 0 ]; then
echo ----------------------------------------------------------------------
echo "Testing CLI..."
first=1
fi
echo "Running $script"
source $script
fi
done
echo ----------------------------------------------------------------------
if [ $result == 0 ] ; then
echo Done
else
echo FAILED
fi
echo ----------------------------------------------------------------------
exit $result

View File

@ -0,0 +1,25 @@
-- Copyright (C) 2018-2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local s = Sprite(32, 64)
assert(s == app.activeSprite)
assert(s == app.site.sprite)
assert(s == app.activeFrame.sprite)
assert(s == app.site.frame.sprite)
assert(1 == app.activeFrame.frameNumber)
assert(1 == app.site.frame.frameNumber)
assert(1 == app.site.frameNumber)
assert(0.100 == app.activeFrame.duration) -- Default frame duration
assert(0.100 == app.site.frame.duration)
assert(s == app.activeLayer.sprite)
assert(s == app.site.layer.sprite)
assert(s == app.activeCel.sprite)
assert(s == app.site.cel.sprite)
app.activeFrame.duration = 0.8
app.command.NewFrame()
assert(2 == app.activeFrame.frameNumber)
assert(0.8 == app.activeFrame.duration) -- Copy frame duration of previous frame

View File

@ -0,0 +1,606 @@
-- Copyright (C) 2019-2020 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
dofile('./test_utils.lua')
local rgba = app.pixelColor.rgba
local rgbaR = app.pixelColor.rgbaR
local rgbaG = app.pixelColor.rgbaG
local rgbaB = app.pixelColor.rgbaB
do -- Undo/Redo commands (like app.undo/redo())
local s = Sprite(32, 32)
assert(s.width == 32)
assert(s.height == 32)
s:resize(50, 40)
assert(s.width == 50)
assert(s.height == 40)
app.command.Undo()
assert(s.width == 32)
assert(s.height == 32)
app.command.Redo()
assert(s.width == 50)
assert(s.height == 40)
end
do -- NewSprite
local s1 = app.activeSprite
app.command.NewFile{ }
assert(s1 == app.activeSprite)
app.command.NewFile{ width=256, height=128, colorMode=ColorMode.INDEXED }
local s2 = app.activeSprite
assert(s1 ~= s2)
assert(s2.width == 256)
assert(s2.height == 128)
assert(s2.colorMode == ColorMode.INDEXED)
end
do -- ExportSpriteSheet
local s = Sprite{ fromFile="sprites/2f-index-3x3.aseprite" }
app.command.ExportSpriteSheet {
type="horizontal",
textureFilename="_test_export_spritesheet1.png",
shapePadding=1
}
local i = Image{ fromFile="_test_export_spritesheet1.png" }
expect_img(i, {
11,8,11,21,8,11,11,
11,8,11,21,11,8,11,
11,8,11,21,11,11,8,
})
end
do -- NewLayer/RemoveLayer
local s = Sprite(32, 32)
assert(#s.layers == 1)
local lay = s.layers[1]
app.command.NewLayer{top=true}
local lay2 = app.activeLayer
assert(#s.layers == 2)
assert(s.layers[2].isImage)
app.command.NewLayer{top=true, group=true}
local lay3 = app.activeLayer
assert(#s.layers == 3)
assert(s.layers[3].isGroup)
assert(app.activeLayer == lay3)
app.command.RemoveLayer()
assert(app.activeLayer == lay2)
assert(#s.layers == 2)
app.command.RemoveLayer()
assert(app.activeLayer == lay)
assert(#s.layers == 1)
end
do -- Background/Transparent layers
local s = Sprite(32, 32)
assert(s.layers[1].isTransparent)
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(0, 0, 0, 0))
app.bgColor = Color(32, 64, 128)
app.command.BackgroundFromLayer() -- the layer will be filled with app.bgColor
assert(s.layers[1].isBackground)
assert(s.layers[1] == s.backgroundLayer)
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(32, 64, 128, 255))
app.command.LayerFromBackground()
assert(s.layers[1].isTransparent)
assert(s.cels[1].image:getPixel(0, 0) == app.pixelColor.rgba(32, 64, 128, 255))
end
do -- Crop and Trim
local s = Sprite(32, 32)
s.selection:select(4, 5, 8, 10)
assert(s.cels[1].bounds == Rectangle(0, 0, 32, 32))
-- Crop
app.command.CropSprite()
assert(s.width == 8)
assert(s.height == 10)
assert(s.cels[1].bounds == Rectangle(-4, -5, 32, 32))
-- Autocrop (Trim)
app.command.AutocropSprite() -- Trim does nothing when we should remove all pixels
assert(s.width == 8)
assert(s.height == 10)
s.cels[1].image:putPixel(5, 5, Color(255, 0, 0))
s.cels[1].image:putPixel(4, 6, Color(255, 0, 0))
app.command.AutocropSprite()
assert(s.width == 2)
assert(s.height == 2)
end
do -- Cel Opacity
local s = Sprite(32, 32)
local c = s.cels[1]
assert(c.opacity == 255)
app.command.CelOpacity{opacity=128}
assert(c.opacity == 128)
s.cels[1].opacity = 255
assert(c.opacity == 255)
app.undo()
assert(c.opacity == 128)
app.undo()
assert(c.opacity == 255)
end
do -- PaletteSize
local s = Sprite(32, 32)
assert(#s.palettes[1] == 256)
app.command.PaletteSize{ size=32 }
assert(#s.palettes[1] == 32)
app.command.PaletteSize{ size=8 }
assert(#s.palettes[1] == 8)
end
do -- CanvasSize
local s = Sprite(32, 32)
assert(s.bounds == Rectangle(0, 0, 32, 32))
app.command.CanvasSize{ left=2 }
assert(s.bounds == Rectangle(0, 0, 34, 32))
app.command.CanvasSize{ top=2, right=4, bottom=8 }
assert(s.bounds == Rectangle(0, 0, 38, 42))
end
do -- ReplaceColor
local s = Sprite(4, 4)
local cel = app.activeCel
local red = Color(255, 0, 0)
local yellow = Color(255, 255, 0)
local blue = Color(0, 0, 255)
local r = red.rgbaPixel
local y = yellow.rgbaPixel
local b = blue.rgbaPixel
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 })
app.useTool{ brush=Brush(1), color=red, points={Point(1,1)} }
app.useTool{ brush=Brush(1), color=yellow, points={Point(2,2)} }
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
expect_img(cel.image,
{ r, 0,
0, y })
app.command.ReplaceColor{ from=red, to=blue }
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
expect_img(cel.image,
{ b, 0,
0, y })
end
do -- Invert
local s = Sprite(2, 2)
local cel = app.activeCel
local aa = Color(255, 128, 128).rgbaPixel
local na = Color(0, 127, 127).rgbaPixel
local bb = Color(128, 128, 255).rgbaPixel
local nb = Color(127, 127, 0).rgbaPixel
local i = cel.image
i:drawPixel(0, 0, aa)
i:drawPixel(1, 0, bb)
i:drawPixel(0, 1, bb)
i:drawPixel(1, 1, aa)
expect_img(cel.image,
{ aa, bb,
bb, aa })
app.command.InvertColor()
expect_img(cel.image,
{ na, nb,
nb, na })
local Na = Color(0, 127, 128).rgbaPixel
local Ng = Color(127, 127, 255).rgbaPixel
app.command.InvertColor{ channels=FilterChannels.BLUE }
expect_img(cel.image,
{ Na, Ng,
Ng, Na })
end
do -- Outline
local s = Sprite(4, 4)
local cel = app.activeCel
local red = Color(255, 0, 0)
local yellow = Color(255, 255, 0)
local blue = Color(0, 0, 255)
local r = red.rgbaPixel
local y = yellow.rgbaPixel
local b = blue.rgbaPixel
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 })
app.useTool{ brush=Brush(1), color=red, points={Point(1,1)} }
app.useTool{ brush=Brush(1), color=yellow, points={Point(2,2)} }
expect_eq(cel.bounds, Rectangle(1, 1, 2, 2))
expect_img(cel.image,
{ r, 0,
0, y })
app.command.Outline{ color=blue }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ 0, b, 0, 0,
b, r, b, 0,
0, b, y, b,
0, 0, b, 0 })
-- Test "bgColor", "matrix", "place" params
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=blue, points={Point(0,0), Point(3,3)} }
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=yellow, points={Point(1,1), Point(2,2)} }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ b, b, b, b,
b, y, y, b,
b, y, y, b,
b, b, b, b })
app.command.Outline{ color=red, bgColor=blue, matrix='circle' }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ b, r, r, b,
r, y, y, r,
r, y, y, r,
b, r, r, b })
app.undo()
app.command.Outline{ color=red, bgColor=blue, matrix='square' }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ r, r, r, r,
r, y, y, r,
r, y, y, r,
r, r, r, r })
app.undo()
app.command.Outline{ color=red, bgColor=blue, place='inside' }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(cel.image,
{ b, b, b, b,
b, r, r, b,
b, r, r, b,
b, b, b, b })
end
do -- BrightnessContrast
local s = Sprite(2, 2)
local cel = app.activeCel
local c = { rgba(255, 128, 64), rgba(250, 225, 110),
rgba( 30, 60, 0), rgba(200, 100, 50), }
local i = cel.image
i:drawPixel(0, 0, c[1])
i:drawPixel(1, 0, c[2])
i:drawPixel(0, 1, c[3])
i:drawPixel(1, 1, c[4])
expect_img(i,
{ c[1], c[2],
c[3], c[4] })
app.command.BrightnessContrast() -- Do nothing by default
expect_img(i,
{ c[1], c[2],
c[3], c[4] })
local d = {}
for k,v in ipairs(c) do
d[k] = rgba(math.min(255, rgbaR(v)*1.5),
math.min(255, rgbaG(v)*1.5),
math.min(255, rgbaB(v)*1.5), 255)
end
app.command.BrightnessContrast{ brightness=50 } -- Do nothing by default
expect_img(i,
{ d[1], d[2],
d[3], d[4] })
end
do -- Despeckle
local s = Sprite(5, 5)
local white = Color(255, 255, 255)
local red = Color(255, 0, 0)
app.bgColor = white
app.command.BackgroundFromLayer()
local cel = app.activeCel
local i = cel.image
local b = white.rgbaPixel
local c = red.rgbaPixel
expect_img(i,
{ b,b,b,b,b,
b,b,b,b,b,
b,b,b,b,b,
b,b,b,b,b,
b,b,b,b,b })
app.useTool{ tool='filled_rectangle', brush=Brush(1), color=red,
points={Point(1,1),Point(3,3)} }
expect_img(i,
{ b,b,b,b,b,
b,c,c,c,b,
b,c,c,c,b,
b,c,c,c,b,
b,b,b,b,b })
app.command.Despeckle()
expect_img(i,
{ b,b,b,b,b,
b,b,c,b,b,
b,c,c,c,b,
b,b,c,b,b,
b,b,b,b,b })
app.command.Despeckle()
expect_img(i,
{ b,b,b,b,b,
b,b,b,b,b,
b,b,c,b,b,
b,b,b,b,b,
b,b,b,b,b })
end
do -- HueSaturation
local s = Sprite(1, 1)
local cel = app.activeCel
local i = cel.image
local b = Color(255, 0, 0).rgbaPixel
i:drawPixel(0, 0, b)
expect_img(i, { b })
app.command.HueSaturation{ hue=360 } -- Do nothing (change hue to a full 360 circle)
expect_img(i, { b })
app.command.HueSaturation{ hue=60 }
b = Color(255, 255, 0).rgbaPixel
expect_img(i, { b })
app.command.HueSaturation{ hue=60 }
b = Color(0, 255, 0).rgbaPixel
expect_img(i, { b })
app.command.HueSaturation{ saturation=-50 }
b = Color(64, 191, 64).rgbaPixel
expect_img(i, { b })
app.undo()
app.command.HueSaturation{ saturation=-100 }
b = Color(128, 128, 128).rgbaPixel
expect_img(i, { b })
app.undo()
app.command.HueSaturation{ saturation=-50, mode='hsv' }
b = Color(128, 255, 128).rgbaPixel
expect_img(i, { b })
app.undo()
app.command.HueSaturation{ value=75 }
b = Color(191, 255, 191).rgbaPixel
expect_img(i, { b })
app.undo()
app.command.HueSaturation{ alpha=-50 }
b = Color(0, 255, 0, 127).rgbaPixel
expect_img(i, { b })
end
do -- ColorCurve
local s = Sprite(2, 1)
local cel = app.activeCel
local i = cel.image
i:drawPixel(0, 0, rgba(255, 128, 0))
i:drawPixel(1, 0, rgba(64, 0, 32))
expect_img(i, { rgba(255, 128, 0), rgba(64, 0, 32) })
app.command.ColorCurve() -- Do nothing
expect_img(i, { rgba(255, 128, 0), rgba(64, 0, 32) })
app.command.ColorCurve{ curve={{0,0},{255,128}} }
expect_img(i, { rgba(128, 64, 0), rgba(32, 0, 16) })
app.command.ColorCurve{ channels=FilterChannels.ALPHA, curve={{0,0},{255,128}} }
expect_img(i, { rgba(128, 64, 0, 128), rgba(32, 0, 16, 128) })
app.command.ColorCurve{ channels=FilterChannels.RGBA, curve={{0,255},{255,255}} }
expect_img(i, { rgba(255, 255, 255), rgba(255, 255, 255) })
app.command.ColorCurve{ channels=FilterChannels.GREEN, curve={{0,0},{255,0}} }
expect_img(i, { rgba(255, 0, 255), rgba(255, 0, 255) })
app.command.ColorCurve{ channels=FilterChannels.BLUE, curve="0,128,255,128" }
expect_img(i, { rgba(255, 0, 128), rgba(255, 0, 128) })
end
do -- ConvolutionMatrix
local s = Sprite(3, 3)
local cel = app.activeCel
local i = cel.image
local b = rgba(0, 0, 0)
local w = rgba(255, 255, 255)
app.bgColor = Color(255, 255, 255)
app.command.BackgroundFromLayer()
i:drawPixel(1, 1, b)
expect_img(i, { w, w, w,
w, b, w,
w, w, w })
local u = rgba(239, 239, 239)
local v = rgba(223, 223, 223)
local w = rgba(191, 191, 191)
app.command.ConvolutionMatrix{ fromResource="blur-3x3" }
expect_img(i, { u, v, u,
v, w, v,
u, v, u })
end
-- MoveColors and CopyColors
do
local s = Sprite(32, 32, ColorMode.INDEXED)
local p = Palette(4)
p:setColor(0, Color(0, 0, 0))
p:setColor(1, Color(255, 0, 0))
p:setColor(2, Color(0, 255, 0))
p:setColor(3, Color(0, 0, 255))
s:setPalette(p)
assert(#app.range.colors == 0)
app.range.colors = { 0, 2 }
assert(#app.range.colors == 2)
assert(app.range.colors[1] == 0)
assert(app.range.colors[2] == 2)
app.command.MoveColors{ before=0 }
p = s.palettes[1]
p:setColor(0, Color(0, 0, 0))
p:setColor(1, Color(0, 255, 0))
p:setColor(2, Color(255, 0, 0))
p:setColor(3, Color(0, 0, 255))
app.range.colors = { 0, 1 }
assert(#app.range.colors == 2)
assert(app.range.colors[1] == 0)
assert(app.range.colors[2] == 1)
app.command.CopyColors{ before=4 }
p = s.palettes[1]
p:setColor(0, Color(0, 0, 0))
p:setColor(1, Color(0, 255, 0))
p:setColor(2, Color(255, 0, 0))
p:setColor(3, Color(0, 0, 255))
p:setColor(4, Color(0, 0, 0))
p:setColor(5, Color(0, 255, 0))
end
-- AddColor
do
local s = Sprite(32, 32)
local p = s.palettes[1]
function testAddColor(color)
assert(p:getColor(#p-1) ~= color)
app.command.AddColor{ color=color }
assert(p:getColor(#p-1) == color)
end
testAddColor(Color(255, 0, 0))
testAddColor(Color(0, 255, 0))
testAddColor(Color(0, 0, 255))
local color = Color(128, 0, 0)
app.preferences.color_bar.fg_color = color
app.command.AddColor{ source="fg" }
assert(p:getColor(#p-1) == color)
local color = Color(0, 0, 128)
app.preferences.color_bar.bg_color = color
app.command.AddColor{ source="bg" }
assert(p:getColor(#p-1) == color)
end
-- Flip
do
local s = Sprite(4, 2, ColorMode.INDEXED)
local i = s.cels[1].image
array_to_pixels({ 0, 1, 2, 3,
4, 5, 6, 7 }, i)
app.command.Flip{ orientation="horizontal" }
expect_img(i, { 3, 2, 1, 0,
7, 6, 5, 4 })
app.command.Flip{ orientation="vertical" }
expect_img(i, { 7, 6, 5, 4,
3, 2, 1, 0 })
s.selection:select{ 1, 0, 2, 2 }
app.command.Flip{ orientation="horizontal", target="mask" }
expect_img(i, { 7, 5, 6, 4,
3, 1, 2, 0 })
s:newFrame()
assert(app.activeCel.frameNumber == 2)
local j = app.activeImage
app.command.Flip{ orientation="vertical", target="mask" }
expect_img(i, { 7, 5, 6, 4,
3, 1, 2, 0 })
expect_img(j, { 7, 1, 2, 4,
3, 5, 6, 0 })
app.range.frames = { 1, 2 }
app.command.Flip{ orientation="horizontal", target="mask" }
expect_img(i, { 7, 6, 5, 4,
3, 2, 1, 0 })
expect_img(j, { 7, 2, 1, 4,
3, 6, 5, 0 })
end
-- Fill
do
local s = Sprite(4, 2, ColorMode.INDEXED)
local c = s.cels[1]
local i = c.image
i:clear(1)
array_to_pixels({ 1, 1, 1, 1,
1, 1, 1, 1 }, i)
app.fgColor = Color{ index=0 }
s.selection = Selection(Rectangle(1, 1, 2, 1))
app.command.Fill()
expect_eq(Rectangle(0, 0, 4, 2), c.bounds)
expect_img(i, { 1, 1, 1, 1,
1, 0, 0, 1 })
c.position = { x=0, y=1 }
app.fgColor = Color{ index=2 }
s.selection = Selection(Rectangle(1, 0, 2, 2))
app.command.Fill()
expect_eq(Rectangle(0, 0, 4, 3), c.bounds)
expect_img(i, { 0, 2, 2, 0,
1, 2, 2, 1,
1, 0, 0, 1 })
app.fgColor = Color{ index=0 }
s.selection = Selection(Rectangle(0, 0, 3, 3))
app.command.Fill()
expect_eq(Rectangle(3, 1, 1, 2), c.bounds)
expect_img(i, { 1,
1 })
app.undo() -- undo Fill
expect_eq(Rectangle(0, 0, 4, 3), c.bounds)
expect_img(i, { 0, 2, 2, 0,
1, 2, 2, 1,
1, 0, 0, 1 })
expect_eq(Rectangle(0, 0, 3, 3), s.selection.bounds)
app.undo() -- undo selection change
expect_eq(Rectangle(1, 0, 2, 2), s.selection.bounds)
app.undo() -- undo Fill
expect_eq(Rectangle(0, 1, 4, 2), c.bounds)
expect_img(i, { 1, 1, 1, 1,
1, 0, 0, 1 })
end

77
tests/scripts/app_fs.lua Normal file
View File

@ -0,0 +1,77 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local fs = app.fs
local sep = fs.pathSeparator
assert('' == fs.filePath('first.png'))
assert('path' == fs.filePath('path/second.png'))
assert('C:\\path' == fs.filePath('C:\\path\\third.png'))
assert('first.png' == fs.fileName('first.png'))
assert('second.png' == fs.fileName('path/second.png'))
assert('third.png' == fs.fileName('C:\\path\\third.png'))
assert('png' == fs.fileExtension('path/file.png'))
assert('first' == fs.fileTitle('first.png'))
assert('second' == fs.fileTitle('path/second.png'))
assert('third' == fs.fileTitle('C:\\path\\third.png'))
assert('first' == fs.filePathAndTitle('first.png'))
assert('path/second' == fs.filePathAndTitle('path/second.png'))
assert('C:\\path\\third' == fs.filePathAndTitle('C:\\path\\third.png'))
assert('hi/bye' == fs.joinPath('hi/', 'bye'))
assert('hi/bye' .. sep .. 'smth.png' == fs.joinPath('hi/', 'bye', 'smth.png'))
local pwd = fs.currentPath
assert(pwd ~= nil)
assert(fs.isDirectory(pwd))
assert(not fs.isFile(pwd))
assert(fs.isFile(fs.joinPath(pwd, 'run-tests.sh')))
do
local runTestsFound = false
local readmeFound = false
local files = fs.listFiles(pwd)
for i in pairs(files) do
if files[i] == 'run-tests.sh' then
runTestsFound = true
elseif files[i] == 'README.md' then
readmeFound = true
end
local fullFs = fs.joinPath(pwd, files[i])
if fs.isFile(fullFs) then
assert(fs.fileSize(fullFs) > 0)
end
end
assert(runTestsFound)
assert(readmeFound)
end
-- Create directories
do
assert(fs.makeDirectory("_tmp"))
assert(fs.isDirectory("_tmp"))
assert(fs.makeAllDirectories("_tmp/a/b"))
assert(fs.isDirectory("_tmp/a"))
assert(fs.isDirectory("_tmp/a/b"))
assert(fs.removeDirectory("_tmp/a/b"))
assert(not fs.isDirectory("_tmp/a/b"))
assert(fs.isDirectory("_tmp/a"))
assert(not fs.removeDirectory("_tmp")) -- Should fail
assert(fs.isDirectory("_tmp/a"))
assert(fs.isDirectory("_tmp"))
assert(fs.removeDirectory("_tmp/a"))
assert(fs.removeDirectory("_tmp"))
assert(not fs.isDirectory("_tmp/a"))
assert(not fs.isDirectory("_tmp"))
end

View File

@ -0,0 +1,12 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local pc = app.pixelColor
assert(0 == pc.rgba(0, 0, 0, 0))
assert(1 == pc.rgbaR(pc.rgba(1, 2, 3, 4)))
assert(2 == pc.rgbaG(pc.rgba(1, 2, 3, 4)))
assert(3 == pc.rgbaB(pc.rgba(1, 2, 3, 4)))
assert(4 == pc.rgbaA(pc.rgba(1, 2, 3, 4)))
assert(0xff104080 == pc.rgba(0x80, 0x40, 0x10, 0xff))

View File

@ -0,0 +1,140 @@
-- Copyright (C) 2019-2021 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
-- Preferences for tools
do
-- The first time we get the tool preferences in CLI mode, we get
-- the default options for this tool (in GUI, we get the current
-- user-defined options).
local t = app.preferences.tool('pencil')
assert(t.opacity == 255)
assert(t.tolerance == 0)
assert(t.contiguous == true)
assert(t.brush.type == BrushType.CIRCLE)
assert(t.brush.size == 1)
t.brush.size = 2
assert(t.brush.size == 2)
-- Getting the tool again must give us the configuration that was
-- set inside the script
t = app.preferences.tool('pencil')
assert(t.brush.size == 2)
end
-- Preferences for documents
do
local defPref = app.preferences.document(nil)
defPref.grid.bounds = Rectangle(0, 0, 16, 16)
local s = Sprite(32, 32)
local p = app.preferences.document(s)
assert(s.gridBounds == Rectangle(0, 0, 16, 16))
assert(p.grid.bounds == Rectangle(0, 0, 16, 16))
assert(p.grid.color == Color(0, 0, 255))
p.grid.color = Color(255, 0, 0)
assert(p.grid.color == Color(255, 0, 0))
end
-- Default & doc preferences combinations (related to https://community.aseprite.org/t/4305)
do
-- Set default preferences
local defPref = app.preferences.document(nil)
defPref.grid.bounds = Rectangle(0, 0, 10, 10)
defPref.grid.color = Color(255, 255, 0) -- Yellow
assert(defPref.grid.bounds == Rectangle(0, 0, 10, 10))
assert(defPref.grid.color == Color(255, 255, 0))
do -- File with default preferences
local doc = Sprite(32, 32)
local docPref = app.preferences.document(doc)
assert(doc.gridBounds == Rectangle(0, 0, 10, 10))
assert(docPref.grid.bounds == Rectangle(0, 0, 10, 10))
assert(docPref.grid.color == Color(255, 255, 0))
doc:saveAs('_test_pref.png')
doc:close()
end
do -- File with specific preferences
local doc = Sprite(32, 32)
local docPref = app.preferences.document(doc)
docPref.grid.color = Color(0, 128, 0) -- Green
assert(docPref.grid.bounds == Rectangle(0, 0, 10, 10))
assert(docPref.grid.color == Color(0, 128, 0))
doc:saveAs('_test_pref2.png')
doc:close()
end
-- Now we change default preferences
defPref.grid.bounds = Rectangle(0, 0, 64, 64)
defPref.grid.color = Color(255, 0, 0) -- Red
assert(defPref.grid.bounds == Rectangle(0, 0, 64, 64))
assert(defPref.grid.color == Color(255, 0, 0))
do -- A new document should have the new default preferences
local doc = Sprite(32, 32)
local docPref = app.preferences.document(doc)
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
assert(docPref.grid.color == Color(255, 0, 0))
doc:close()
end
do -- The first document should have the new default preferences (because it was saved with the defaults)
-- TODO maybe related to https://community.aseprite.org/t/grid-for-new-documents/3303
-- should we get the new defaults or the values when we saved the document?
-- (e.g. even if we didn't change the grid values, it looks
-- like if the user changed something about the grid or the
-- background colors, the expected behavior would be to
-- restore the exact same colors, no the new defaults)
local doc = Sprite{ fromFile="_test_pref.png" }
local docPref = app.preferences.document(doc)
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
assert(docPref.grid.color == Color(255, 0, 0))
doc:close()
end
do -- The second document should have the new specific preferences for the grid color
local doc = Sprite{ fromFile="_test_pref2.png" }
local docPref = app.preferences.document(doc)
assert(docPref.grid.bounds == Rectangle(0, 0, 64, 64))
assert(docPref.grid.color == Color(0, 128, 0))
doc:close()
end
end
do -- Test that undoing grid bounds, updates the grid in the preferences correctly
local doc = Sprite(32, 32)
assert(doc.gridBounds == Rectangle(0, 0, 64, 64))
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 64, 64))
doc.gridBounds = Rectangle(0, 0, 4, 4)
assert(doc.gridBounds == Rectangle(0, 0, 4, 4))
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 4, 4))
app.undo()
assert(doc.gridBounds == Rectangle(0, 0, 64, 64))
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 64, 64))
app.redo()
assert(doc.gridBounds == Rectangle(0, 0, 4, 4))
assert(app.preferences.document(doc).grid.bounds == Rectangle(0, 0, 4, 4))
end
do -- Test symmetry preferences
do -- File with default preferences
local doc = Sprite(200, 100)
local docPref = app.preferences.document(doc)
assert(docPref.symmetry.x_axis == 100)
assert(docPref.symmetry.y_axis == 50)
docPref.symmetry.x_axis = 25
doc:saveAs('_test_symmetry.png')
doc:close()
end
do -- File with default preferences
local doc = Sprite{ fromFile='_test_symmetry.png' }
local docPref = app.preferences.document(doc)
assert(docPref.symmetry.x_axis == 25)
assert(docPref.symmetry.y_axis == 50)
doc:close()
end
end

View File

@ -0,0 +1,40 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local s = Sprite(16, 32)
assert(s.width == 16)
assert(s.height == 32)
s.width = 20
assert(s.width == 20)
assert(s.height == 32)
s.height = 40
assert(s.width == 20)
assert(s.height == 40)
app.undo()
assert(s.width == 20)
assert(s.height == 32)
app.undo()
assert(s.width == 16)
assert(s.height == 32)
app.transaction(
function()
s.width = 20
s.height = 40
end)
assert(s.width == 20)
assert(s.height == 40)
app.undo()
assert(s.width == 16)
assert(s.height == 32)
app.redo()
assert(s.width == 20)
assert(s.height == 40)

74
tests/scripts/brush.lua Normal file
View File

@ -0,0 +1,74 @@
-- Copyright (C) 2019 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')
do
local b = Brush()
assert(b.type == BrushType.CIRCLE)
assert(b.size == 1)
assert(b.angle == 0)
assert(b.center == Point{ x=0, y=0 })
assert(b.pattern == BrushPattern.NONE)
assert(b.patternOrigin == Point{ x=0, y=0 })
local c = Brush(3)
assert(c.type == BrushType.CIRCLE)
assert(c.size == 3)
assert(c.center == Point{ x=1, y=1 })
local d = Brush(4)
assert(d.type == BrushType.CIRCLE)
assert(d.size == 4)
assert(d.center == Point{ x=2, y=2 })
end
do
local b = Brush{ type=BrushType.SQUARE, size=4 }
assert(b.type == BrushType.SQUARE)
assert(b.size == 4)
assert(b.angle == 0)
end
do
local b = Brush{ type=BrushType.LINE, size=5, angle=90 }
assert(b.type == BrushType.LINE)
assert(b.size == 5)
assert(b.angle == 90)
end
do
local b = Brush{ type=BrushType.IMAGE, image=Image(4, 8) }
local c = Brush{ image=Image(4, 8) }
assert(b.type == BrushType.IMAGE)
assert(c.type == BrushType.IMAGE)
assert(b.image.width == 4)
assert(b.image.height == 8)
assert(b.pattern == BrushPattern.NONE)
assert(b.patternOrigin.x == 0)
assert(b.patternOrigin.y == 0)
end
do
local rgba = app.pixelColor.rgba
local r = rgba(255, 0, 0)
local g = rgba(0, 128, 0)
local b = rgba(0, 0, 255)
local img = Image(2, 2)
img:putPixel(0, 0, r)
img:putPixel(1, 0, b)
img:putPixel(0, 1, b)
img:putPixel(1, 1, r)
local brush = Brush{ image=img }
expect_img(brush.image, { r, b, b, r })
brush:setFgColor(g)
expect_img(brush.image, { r, g, g, r })
brush:setBgColor(b)
expect_img(brush.image, { b, g, g, b })
end

29
tests/scripts/cel.lua Normal file
View File

@ -0,0 +1,29 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local s = Sprite(32, 64)
assert(#s.layers == 1)
assert(#s.cels == 1)
local c = s.cels[1]
assert(c.sprite == s)
assert(c.layer == s.layers[1])
assert(c.frame == s.frames[1])
assert(c.frame.frameNumber == 1)
assert(c.frameNumber == 1)
assert(c.image)
assert(c.bounds == Rectangle(0, 0, 32, 64))
assert(c.position == Point(0, 0))
assert(c.color == Color())
assert(c.data == "")
c.color = Color{ r=255, g=100, b=20 }
c.data = "test"
assert(c.color == Color{ r=255, g=100, b=20 })
assert(c.data == "test")
c.position = Point(2, 4)
assert(c.position == Point(2, 4))
assert(c.bounds == Rectangle(2, 4, 32, 64))

86
tests/scripts/cels.lua Normal file
View File

@ -0,0 +1,86 @@
-- Copyright (C) 2020 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
dofile('./test_utils.lua')
do
local s = Sprite(32, 32)
for i = 1,3 do s:newFrame() end
assert(#s.frames == 4)
-- Layer a and b
local a = s.layers[1]
local b = s:newLayer()
local ca = { s.cels[1],
s.cels[2],
s.cels[3] }
local cb = { s:newCel(b, 1),
s:newCel(b, 2, Image(8, 8), 4, 4),
s:newCel(b, 3, Image(32, 10), 16, 10) }
assert(cb[1].bounds == Rectangle(0, 0, 32, 32))
assert(cb[2].bounds == Rectangle(4, 4, 8, 8))
assert(cb[3].bounds == Rectangle(16, 10, 32, 10))
-- Check how layer cels are updated when we delete a cel in the middle
assert(cb[1] == b.cels[1])
assert(cb[2] == b.cels[2])
assert(cb[3] == b.cels[3])
local i = 1
for k,v in ipairs(b.cels) do
assert(i == k)
assert(v == b.cels[k])
i = i+1
end
s:deleteCel(cb[2])
assert(cb[1] == b.cels[1])
assert(cb[3] == b.cels[2])
end
-- Some extra tests of newCel() and deleteCel()
do
local s = Sprite(4, 4, ColorMode.INDEXED)
local layer = app.activeLayer
app.bgColor = 0
app.command.BackgroundFromLayer()
expect_img(s.cels[1].image, { 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 })
-- Crash in old versions undoing newCel() in a background layer
s:newCel(layer, 1)
app.undo()
-- Check that newCel clears with bgColor in background layer
local img = Image(ImageSpec{ width=2, height=2,
colorMode=ColorMode.INDEXED })
array_to_pixels({ 0, 1,
2, 3 }, img)
app.bgColor = Color(1) -- bgColor used to clear the background cel
s:newCel(layer, 1, img, Point(1, 1))
expect_img(s.cels[1].image, { 1, 1, 1, 1,
1, 0, 1, 1,
1, 2, 3, 1,
1, 1, 1, 1 })
app.undo()
-- Check deleteCel()
app.bgColor = Color(2)
s:deleteCel(layer, 1)
expect_img(s.cels[1].image, { 2, 2, 2, 2,
2, 2, 2, 2,
2, 2, 2, 2,
2, 2, 2, 2 })
app.undo()
end

45
tests/scripts/color.lua Normal file
View File

@ -0,0 +1,45 @@
-- Copyright (C) 2022 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local a, b
a = Color()
assert(a.red == 0)
assert(a.green == 0)
assert(a.blue == 0)
assert(a.alpha == 0)
a = Color{ r=100, g=50, b=10 }
b = Color(100, 50, 10)
assert(a.red == 100)
assert(a.green == 50)
assert(a.blue == 10)
assert(a.alpha == 255)
assert(a == b)
a = Color{ red=200, green=100, blue=20, alpha=200 }
b = Color(200, 100, 20, 200)
assert(a.red == 200)
assert(a.green == 100)
assert(a.blue == 20)
assert(a.alpha == 200)
assert(a == b)
print(a.rgbaPixel)
print(app.pixelColor.rgba(200, 100, 20, 200))
assert(a.rgbaPixel == app.pixelColor.rgba(200, 100, 20, 200))
a = Color{ h=180, s=0.4, v=0.5, a=200 }
b = Color{ hue=180, saturation=0.4, value=0.5, alpha=200 }
assert(a.hue == 180)
assert(a.saturation == 0.4)
assert(a.value == 0.5)
assert(a.alpha == 200)
assert(b.hue == 180)
assert(b.saturation == 0.4)
assert(b.value == 0.5)
assert(b.alpha == 200)
assert(a == b)
assert(a ~= 1) -- Comparing with other type fails

View File

@ -0,0 +1,51 @@
-- Copyright (C) 2019-2022 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')
-- this tests and ensures that the alpha-ness of a background
-- layer is maintained when sprite conversion takes place from
-- Indexed to RGB
do
local sprite = Sprite(2, 2, ColorMode.INDEXED)
local pal = sprite.palettes[1]
assert(sprite.layers[1].isTransparent)
assert(sprite.colorMode == ColorMode.INDEXED)
assert(#pal == 256)
local color = pal:getColor(3)
color.alpha = 200
pal:setColor(3, color)
local image = sprite.cels[1].image
image:drawPixel(0, 0, pal:getColor(2))
image:drawPixel(0, 1, pal:getColor(3))
image:drawPixel(1, 0, pal:getColor(4))
image:drawPixel(1, 1, pal:getColor(5))
app.bgColor = Color{ index=0 }
app.command.BackgroundFromLayer()
local layer = sprite.layers[1]
assert(layer.isTransparent == false)
assert(layer.name == "Background")
-- change color mode from Indexed to RGB
app.command.ChangePixelFormat {
format="rgb"
}
assert(sprite.colorMode == ColorMode.RGB)
image = sprite.cels[1].image
for x=0, 1, 1 do
for y=0, 1, 1 do
local pixel = image:getPixel(x, y)
assert(app.pixelColor.rgbaA(pixel) == 255)
end
end
end

View File

@ -0,0 +1,201 @@
-- Copyright (C) 2019-2022 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 rgba = app.pixelColor.rgba
----------------------------------------------------------------------
-- app.command.ColorQuantization
do
-- One sprite with a background layer
local s = Sprite(2, 2)
app.command.BackgroundFromLayer()
local i = s.cels[1].image
local p = s.palettes[1]
assert(#p == 256)
assert(s.colorMode == ColorMode.RGB)
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 1)
array_to_pixels({ rgba(255, 255, 0), rgba(255, 255, 0),
rgba(255, 255, 0), rgba(255, 255, 0) }, i)
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 1)
assert(p:getColor(0) == Color(255, 255, 0))
array_to_pixels({ rgba(255, 0, 0), rgba(255, 0, 0),
rgba(255, 255, 0), rgba(255, 255, 0) }, i)
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 2)
assert(p:getColor(0) == Color(255, 0, 0))
assert(p:getColor(1) == Color(255, 255, 0))
array_to_pixels({ rgba(255, 0, 0), rgba(255, 0, 0),
rgba(255, 255, 0), rgba(0, 0, 255) }, i)
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 3)
assert(p:getColor(0) == Color(255, 0, 0))
assert(p:getColor(1) == Color(255, 255, 0))
assert(p:getColor(2) == Color(0, 0, 255))
-- Convert the background layer to a transparent layer
app.command.LayerFromBackground()
app.command.ColorQuantization{ algorithm="rgb5a3", withAlpha=false }
assert(#p == 4) -- One extra color for transparent layer
assert(p:getColor(0) == Color(0, 0, 0))
assert(p:getColor(1) == Color(255, 0, 0))
assert(p:getColor(2) == Color(255, 255, 0))
assert(p:getColor(3) == Color(0, 0, 255))
app.command.ColorQuantization()
assert(#p == 4)
assert(p:getColor(0) == Color(0, 0, 0, 0))
assert(p:getColor(1) == Color(255, 0, 0))
assert(p:getColor(2) == Color(255, 255, 0))
assert(p:getColor(3) == Color(0, 0, 255))
array_to_pixels({ rgba(0, 0, 0), rgba(255, 0, 0),
rgba(255, 0, 0), rgba(0, 0, 255) }, i)
app.command.ColorQuantization{ algorithm="rgb5a3", withAlpha=false }
assert(#p == 4)
assert(p:getColor(0) == Color(0, 0, 0))
assert(p:getColor(1) == Color(0, 0, 0))
assert(p:getColor(2) == Color(255, 0, 0))
assert(p:getColor(3) == Color(0, 0, 255))
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 4)
assert(p:getColor(0) == Color(0, 0, 0, 0))
assert(p:getColor(1) == Color(0, 0, 0))
assert(p:getColor(2) == Color(255, 0, 0))
assert(p:getColor(3) == Color(0, 0, 255))
end
do
-- One sprite with a transparent layer + a background layer
local s = Sprite(2, 2)
local p = s.palettes[1]
app.command.BackgroundFromLayer()
local bg = s.cels[1].image
local fg = s:newCel(s:newLayer(), 1).image
assert(#s.frames == 1)
assert(#s.layers == 2)
assert(#s.cels == 2)
array_to_pixels({ rgba(0, 0, 0, 0), rgba(0, 255, 0),
rgba(255, 0, 0), rgba(0, 0, 0, 0) }, fg)
array_to_pixels({ rgba(0, 0, 0), rgba(0, 0, 0),
rgba(0, 0, 0), rgba(0, 0, 255) }, bg)
app.command.ColorQuantization{ algorithm="rgb5a3" }
assert(#p == 5)
assert(p:getColor(0) == Color(0, 0, 0, 0))
assert(p:getColor(1) == Color(0, 0, 0))
assert(p:getColor(2) == Color(0, 255, 0))
assert(p:getColor(3) == Color(255, 0, 0))
assert(p:getColor(4) == Color(0, 0, 255))
end
----------------------------------------------------------------------
-- app.command.ChangePixelFormat
do
local s = Sprite(2, 2, ColorMode.RGB)
local p = Palette(4)
p:setColor(0, Color(0, 0, 0))
p:setColor(1, Color(101, 90, 200))
p:setColor(2, Color(102, 91, 201))
p:setColor(3, Color(103, 92, 203))
s:setPalette(p)
app.command.BackgroundFromLayer()
local bg = s.cels[1].image
array_to_pixels({ rgba(0, 0, 0), rgba(101, 90, 200),
rgba(102, 91, 201), rgba(103, 92, 203) }, bg)
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
-- Using the 5-bit precision of RGB5A3 will match everything with
-- the first palette entry.
bg = s.cels[1].image
expect_img(bg, { 0, 1,
1, 1 })
app.undo()
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
bg = s.cels[1].image
expect_img(bg, { 0, 1,
2, 3 })
app.undo()
p:setColor(0, Color(0, 0, 0, 0))
bg = s.cels[1].image
array_to_pixels({ rgba(101, 90, 200, 0), rgba(101, 90, 200),
rgba(102, 91, 201), rgba(103, 92, 203, 0) }, bg)
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
bg = s.cels[1].image
expect_img(bg, { 0, 1,
2, 0 })
end
----------------------------------------------------------------------
-- Tests for issue aseprite/aseprite#3207
-- Conversion RGB to INDEXED color mode, in transparent layers, always
-- picks index 0 as transparent color, even if the mask color is present
-- in the palette.
do
local s = Sprite(2, 3, ColorMode.RGB)
local p = Palette(4)
p:setColor(0, Color(0, 0, 0))
p:setColor(1, Color(255, 0, 0))
p:setColor(2, Color(0, 0, 0, 0))
p:setColor(3, Color(0, 255, 0))
s:setPalette(p)
local bg = s.cels[1].image
array_to_pixels({ rgba(0, 0, 0),rgba(255, 0, 0),
rgba(255, 0, 0), rgba(0, 0, 0, 0),
rgba(0, 0, 0, 0), rgba(0, 0, 0, 0), }, bg)
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
-- Using the 5-bit precision of RGB5A3 will match everything with
-- the first palette entry.
bg = s.cels[1].image
expect_img(bg, { 0, 1,
1, 2,
2, 2 })
app.undo()
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
bg = s.cels[1].image
expect_img(bg, { 0, 1,
1, 2,
2, 2 })
app.undo()
p:setColor(2, Color(0, 0, 255))
s:setPalette(p)
bg = s.cels[1].image
app.command.ChangePixelFormat{ format="indexed", rgbmap="rgb5a3" }
bg = s.cels[1].image
expect_img(bg, { 2, 1,
1, 0,
0, 0 })
app.undo()
app.command.ChangePixelFormat{ format="indexed", rgbmap="octree" }
bg = s.cels[1].image
expect_img(bg, { 2, 1,
1, 0,
0, 0 })
end

View File

@ -0,0 +1,21 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local none = ColorSpace() -- None
local srgb = ColorSpace{ sRGB=true }
local none2 = ColorSpace{ sRGB=false }
assert(none ~= srgb)
assert(none == none2)
local spr = Sprite(32, 32)
local cs1 = spr.colorSpace
local cs2 = spr.spec.colorSpace
assert(cs1 == cs2)
assert(cs1 ~= none)
assert(cs1 == srgb) -- Default color profile: sRGB
local spr3 = Sprite(32, 32)
local cs3 = spr.spec.colorSpace
assert(cs1 == cs3)

View File

@ -0,0 +1,60 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local file1 = app.params["file1"]
local file2 = app.params["file2"]
if file1 == nil or file2 == nil then
return 0
end
local json = dofile('../third_party/json/json.lua')
local data1 = json.decode(io.open(file1):read('a'))
local data2 = json.decode(io.open(file2):read('a'))
if data1 == nil then
print('Cannot read file ' .. file1)
return 1
elseif data2 == nil then
print('Cannot read file ' .. file2)
return 1
end
local function replace_filename(fn, newfn)
return string.gsub(fn, "(.*)[/\\]([^/\\]+)", "%1/"..newfn)
end
local sheet1 = app.open(replace_filename(file1, data1.meta.image))
local sheet2 = app.open(replace_filename(file2, data2.meta.image))
for k,v in pairs(data1.frames) do
local fr1 = data1.frames[k]
local fr2 = data2.frames[k]
if fr1.duration ~= fr2.duration then
print('Frame '..k..' doesn\'t match duration')
return 1
end
if fr1.sourceSize.w ~= fr2.sourceSize.w or
fr1.sourceSize.h ~= fr2.sourceSize.h then
print('Frame '..k..' doesn\'t match sourceSize')
return 1
end
local celImage1 = Image(fr1.frame.w, fr1.frame.h, sheet1.colorMode)
local celImage2 = Image(fr2.frame.w, fr2.frame.h, sheet2.colorMode)
celImage1:drawSprite(sheet1, 1, -fr1.frame.x, -fr1.frame.y)
celImage2:drawSprite(sheet2, 1, -fr2.frame.x, -fr2.frame.y)
local frImage1 = Image(fr1.sourceSize.w, fr1.sourceSize.h, sheet1.colorMode)
local frImage2 = Image(fr2.sourceSize.w, fr2.sourceSize.h, sheet2.colorMode)
frImage1:drawImage(celImage1, fr1.spriteSourceSize.x, fr1.spriteSourceSize.y)
frImage2:drawImage(celImage2, fr2.spriteSourceSize.x, fr2.spriteSourceSize.y)
-- To debug this function
--frImage1:saveAs(replace_filename(file1, k .. "-fr1.png"))
--frImage2:saveAs(replace_filename(file2, k .. "-fr2.png"))
--print(k, "fr1", fr1.frame.x, fr1.frame.y, "fr2", fr2.frame.x, fr2.frame.y)
assert(frImage1:isEqual(frImage2))
end

View File

@ -0,0 +1,9 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert(true)
print("this should be in the output")
assert(false)
print("this should not be in the output")

View File

@ -0,0 +1,7 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
print("hello world")
print(1, 2, 3)

View File

@ -0,0 +1,8 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert(ColorMode.RGB == 0)
assert(ColorMode.GRAYSCALE == 1)
assert(ColorMode.INDEXED == 2)

83
tests/scripts/drawing.lua Normal file
View File

@ -0,0 +1,83 @@
-- Copyright (C) 2018-2022 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local pc = app.pixelColor
-- Image:clear
local function test_clear(colorMode, transparentColor)
local i = Image(ImageSpec{ width=2, height=2, colorMode=colorMode, transparentColor=transparentColor })
i:putPixel(0, 0, 1)
i:putPixel(1, 0, 2)
i:putPixel(0, 1, 3)
i:putPixel(1, 1, 4)
assert(1 == i:getPixel(0, 0))
assert(2 == i:getPixel(1, 0))
assert(3 == i:getPixel(0, 1))
assert(4 == i:getPixel(1, 1))
i:clear(5)
assert(5 == i:getPixel(0, 0))
assert(5 == i:getPixel(1, 0))
assert(5 == i:getPixel(0, 1))
assert(5 == i:getPixel(1, 1))
print("transparentColor = ", transparentColor)
assert(transparentColor == i.spec.transparentColor)
i:clear() -- Image:clear() clears with i.spec.transparentColor by default
assert(transparentColor == i:getPixel(0, 0))
assert(transparentColor == i:getPixel(1, 0))
assert(transparentColor == i:getPixel(0, 1))
assert(transparentColor == i:getPixel(1, 1))
end
test_clear(ColorMode.RGB, 0)
test_clear(ColorMode.GRAYSCALE, 0)
test_clear(ColorMode.INDEXED, 0)
test_clear(ColorMode.INDEXED, 255)
-- Image:drawSprite
do
local spr = Sprite(4, 4)
local cel = spr.cels[1]
cel.image:putPixel(0, 0, pc.rgba(255, 0, 0, 255))
cel.image:putPixel(1, 0, pc.rgba(0, 255, 0, 255))
cel.image:putPixel(0, 1, pc.rgba(0, 0, 255, 255))
cel.image:putPixel(1, 1, pc.rgba(255, 255, 0, 255))
local r = Image(spr.spec) -- render
r:drawSprite(spr, 1, 0, 0)
assert(r:getPixel(0, 0) == pc.rgba(255, 0, 0, 255))
assert(r:getPixel(1, 0) == pc.rgba(0, 255, 0, 255))
assert(r:getPixel(0, 1) == pc.rgba(0, 0, 255, 255))
assert(r:getPixel(1, 1) == pc.rgba(255, 255, 0, 255))
r = Image(3, 3, spr.colorMode)
r:drawSprite(spr, 1, Point{x=1, y=1})
assert(r:getPixel(0, 0) == pc.rgba(0, 0, 0, 0))
assert(r:getPixel(1, 0) == pc.rgba(0, 0, 0, 0))
assert(r:getPixel(2, 0) == pc.rgba(0, 0, 0, 0))
assert(r:getPixel(0, 1) == pc.rgba(0, 0, 0, 0))
assert(r:getPixel(1, 1) == pc.rgba(255, 0, 0, 255))
assert(r:getPixel(2, 1) == pc.rgba(0, 255, 0, 255))
assert(r:getPixel(0, 2) == pc.rgba(0, 0, 0, 0))
assert(r:getPixel(1, 2) == pc.rgba(0, 0, 255, 255))
assert(r:getPixel(2, 2) == pc.rgba(255, 255, 0, 255))
end
-- Image:drawPixel with indexed color
do
local a = Sprite(32, 32, ColorMode.INDEXED)
local i = a.cels[1].image
assert(i:getPixel(0, 0) == 0)
assert(i:getPixel(1, 0) == 0)
assert(i:getPixel(2, 0) == 0)
i:drawPixel(0, 0, Color{ index=2 })
i:drawPixel(1, 0, Color{ index=3 }.index)
i:drawPixel(2, 0, Color(4))
assert(i:getPixel(0, 0) == 2)
assert(i:getPixel(1, 0) == 3)
assert(i:getPixel(2, 0) == 4)
end

136
tests/scripts/events.lua Normal file
View File

@ -0,0 +1,136 @@
-- Copyright (C) 2021 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')
-- Test app.events
do
local i = 0
local listener = app.events:on('sitechange',
function() i = i + 1 end)
assert(i == 0)
local a = Sprite(32, 32)
expect_eq(a, app.activeSprite)
expect_eq(1, i)
local b = Sprite(32, 32)
expect_eq(b, app.activeSprite)
expect_eq(2, i)
app.activeSprite = a
expect_eq(3, i)
app.events:off(listener)
app.activeSprite = b
expect_eq(3, i)
end
do
local pref = app.preferences
pref.color_bar.fg_color = Color(0, 0, 0)
pref.color_bar.bg_color = Color(0, 0, 0)
local fg, bg = 0, 0
local a = app.events:on('fgcolorchange', function() fg = fg + 1 end)
local b = app.events:on('bgcolorchange', function() bg = bg + 1 end)
assert(fg == 0)
assert(bg == 0)
pref.color_bar.fg_color = Color(255, 0, 0)
pref.color_bar.bg_color = Color(255, 0, 0)
assert(fg == 1)
assert(bg == 1)
pref.color_bar.fg_color = Color(255, 0, 0) -- No change (same color)
assert(fg == 1)
pref.color_bar.fg_color = Color(0, 0, 0)
assert(fg == 2)
app.events:off(a)
app.events:off(b)
pref.color_bar.fg_color = Color(255, 0, 0)
assert(fg == 2)
end
-- Test Sprite.events
do
local spr = Sprite(32, 64)
local changes = 0
function incChanges() changes = changes + 1 end
spr.events:on('change', incChanges)
expect_eq(0, changes)
spr.width = 64
expect_eq(1, changes)
app.undo()
expect_eq(2, changes)
app.redo()
expect_eq(3, changes)
spr.events:off(incChanges)
app.undo()
expect_eq(3, changes)
end
-- Multiple listeners
do
local spr = Sprite(2, 2)
local ai, bi = 0, 0
function a() ai = ai + 1 end
function b() bi = bi + 1 end
spr.events:on('change', a)
spr.events:on('change', b)
spr.width = 4
expect_eq(1, ai)
expect_eq(1, bi)
spr.events:off(a)
spr.width = 8
expect_eq(1, ai)
expect_eq(2, bi)
spr.events:off(b)
spr.width = 16
expect_eq(1, ai)
expect_eq(2, bi)
end
-- Avoid removing invalid listener when we use Events:off(function)
do
local spr = Sprite(2, 2)
local i = 0
function inc() i = i + 1 end
spr.events:on('change', inc)
spr.width = 4
expect_eq(1, i)
app.events:off(inc)
spr.width = 8
-- If this fails is because app.events:off(inc) removed the sprite
-- listener instead of doing nothing.
expect_eq(2, i)
end
-- Accessing Sprite.events when closing the same sprite will call
-- push_sprite_events() creating a new app::script::SpriteEvents
-- instance again even when we've just destroyed the old one (because
-- we're just closing the sprite).
do
local s = Sprite(32, 32)
function onSpriteChange()
-- Do nothing
end
-- Here we access s.events for first time, creating the
-- app::script::SpriteEvents for this sprite.
s.events:on('change', onSpriteChange)
function onSiteChange()
-- Accessing s.events again on 'sitechange' when we're just
-- closing the sprite, re-generating its SpriteEvents instance.
-- We've to have special care of this case.
s.events:off(onSpriteChange)
end
app.events:on('sitechange', onSiteChange)
-- Closing the sprite will create a 'sitechange' event calling
-- onSiteChange() function.
s:close()
app.events:off(onSiteChange)
end

95
tests/scripts/frames.lua Normal file
View File

@ -0,0 +1,95 @@
-- Copyright (C) 2018 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local a = Sprite(32, 32)
assert(#a.frames == 1)
assert(a.frames[1].frameNumber == 1)
assert(a.frames[1].duration == 0.1)
a.frames[1].duration = 0.2
assert(a.frames[1].duration == 0.2)
assert(a.layers[1]:cel(1) ~= nil)
-- Sprite:newEmptyFrame()
local fr0 = a:newEmptyFrame()
assert(fr0.frameNumber == 2) -- returned the second frame
assert(#a.frames == 2)
assert(a.frames[1].frameNumber == 1)
assert(a.frames[2].frameNumber == 2)
assert(a.frames[1].duration == 0.2)
assert(a.frames[2].duration == 0.2) -- the duration is copied
assert(a.layers[1]:cel(1) ~= nil)
assert(a.layers[1]:cel(fr0) == nil) -- no cel
assert(fr0 == a.frames[2])
a:deleteFrame(fr0)
assert(#a.frames == 1)
-- Sprite:newFrame() without arguments
local fr = a:newFrame()
assert(fr.frameNumber == 2) -- returned the second frame
assert(#a.frames == 2)
assert(a.frames[1].frameNumber == 1)
assert(a.frames[2].frameNumber == 2)
assert(a.frames[1].duration == 0.2)
assert(a.frames[2].duration == 0.2)
assert(fr == a.frames[2])
fr.duration = 0.3
assert(a.frames[1].duration == 0.2)
assert(a.frames[2].duration == 0.3)
local i = 1
for k,v in ipairs(a.frames) do
assert(i == k)
assert(v == a.frames[k])
i = i+1
end
a:deleteFrame(1)
assert(#a.frames == 1)
assert(a.frames[1].duration == 0.3)
-- TODO This is a big issue, if we add/delete frames, we don't
-- update frame objects, they are still pointing to the same frame
-- number, which could lead to confusion.
assert(fr.frameNumber == 2)
fr.duration = 1 -- This is a do nothing operation
-- Sprite:newEmptyFrame(n)
local fr2 = a:newEmptyFrame(1)
assert(#a.frames == 2)
assert(fr2.frameNumber == 1) -- returned the first frame
print(a.frames[1].duration)
assert(a.frames[1].duration == 0.3) -- the duration is copied from the frame
assert(a.frames[2].duration == 0.3)
assert(fr2 == a.frames[1])
assert(a.layers[1]:cel(1) == nil)
assert(a.layers[1]:cel(2) ~= nil)
-- Sprite:newFrame(n)
local fr3 = a:newFrame(2)
assert(#a.frames == 3)
assert(fr3.frameNumber == 2) -- returned the second frame
assert(a.frames[1].duration == 0.3)
assert(a.frames[2].duration == 0.3) -- copied duration from old frame 2
assert(a.frames[3].duration == 0.3)
local cel1 = a.layers[1]:cel(1)
local cel2 = a.layers[1]:cel(2)
local cel3 = a.layers[1]:cel(3)
assert(cel1 == nil)
assert(cel2 ~= nil)
assert(cel3 ~= nil)
print(cel2.image.spec.colorMode)
print(cel2.image.spec.width)
print(cel2.image.spec.height)
print(cel3.image.spec.colorMode)
print(cel3.image.spec.width)
print(cel3.image.spec.height)
assert(cel2.image.spec == cel3.image.spec)
assert(fr3.previous == a.frames[1])
assert(fr3 == a.frames[2])
assert(fr3.next == a.frames[3])
end

276
tests/scripts/image.lua Normal file
View File

@ -0,0 +1,276 @@
-- Copyright (C) 2019-2022 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
dofile('./test_utils.lua')
local rgba = app.pixelColor.rgba
local a = Image(32, 64)
assert(a.width == 32)
assert(a.height == 64)
assert(a.colorMode == ColorMode.RGB) -- RGB by default
assert(a.rowStride == 32*4)
assert(a:isEmpty())
assert(a:isPlain(rgba(0, 0, 0, 0)))
assert(a:isPlain(0))
do
local b = Image(32, 64, ColorMode.INDEXED)
assert(b.width == 32)
assert(b.height == 64)
assert(b.colorMode == ColorMode.INDEXED)
assert(b.rowStride == 32*1)
local c = Image{ width=32, height=64, colorMode=ColorMode.INDEXED }
assert(c.width == 32)
assert(c.height == 64)
assert(c.colorMode == ColorMode.INDEXED)
end
-- Get/put RGBA pixels
do
for y=0,a.height-1 do
for x=0,a.width-1 do
a:putPixel(x, y, rgba(x, y, x+y, x-y))
end
end
assert(not a:isEmpty())
end
-- Clone
do
local c = Image(a)
local d = a:clone()
assert(c.width == 32)
assert(c.height == 64)
assert(c.colorMode == ColorMode.RGB)
assert(c.width == d.width)
assert(c.height == d.height)
assert(c.colorMode == d.colorMode)
-- Get RGB pixels
for y=0,c.height-1 do
for x=0,c.width-1 do
local expectedColor = rgba(x, y, x+y, x-y)
assert(c:getPixel(x, y) == expectedColor)
assert(d:getPixel(x, y) == expectedColor)
end
end
-- Clone a rectangle
local e = Image(c, Rectangle(1, 1, 4, 5))
print(e.width)
print(e.height)
assert(e.width == 4)
assert(e.height == 5)
-- Empty clone
assert(nil == Image(c, Rectangle(1, 1, 0, 0)))
end
-- Patch
do
local spr = Sprite(256, 256)
local image = app.site.image
local copy = image:clone()
assert(image:getPixel(0, 0) == 0)
for y=0,copy.height-1 do
for x=0,copy.width-1 do
copy:putPixel(x, y, rgba(255-x, 255-y, 0, 255))
end
end
image:putImage(copy)
assert(image:getPixel(0, 0) == rgba(255, 255, 0, 255))
assert(image:getPixel(255, 255) == rgba(0, 0, 0, 255))
app.undo()
assert(image:getPixel(0, 0) == rgba(0, 0, 0, 0))
assert(image:getPixel(255, 255) == rgba(0, 0, 0, 0))
end
-- Load/Save
do
local a = Image{ fromFile="sprites/1empty3.aseprite" }
assert(a.width == 32)
assert(a.height == 32)
a:saveAs("_test_oneframe.png")
local b = Image{ fromFile="_test_oneframe.png" }
assert(b.width == 32)
assert(b.height == 32)
for y=0,a.height-1 do
for x=0,a.width-1 do
assert(a:getPixel(x, y) == b:getPixel(x, y))
end
end
end
-- Save indexed image and load and check that the palette is the same
do
local spr = Sprite{ fromFile="sprites/abcd.aseprite" }
local img = Image{ fromFile="sprites/abcd.aseprite" }
spr.cels[1].image:saveAs("_test_palette_a.png")
img:saveAs("_test_palette_b.png") -- This file will contain a black palette
img:saveAs{ filename="_test_palette_c.png", palette=spr.palettes[1] }
local a = Sprite{ fromFile="_test_palette_a.png" }
local b = Sprite{ fromFile="_test_palette_b.png" }
local c = Sprite{ fromFile="_test_palette_c.png" }
assert(a.width == 5)
assert(a.height == 7)
assert(b.width == 32)
assert(b.height == 32)
assert(c.width == 32)
assert(c.height == 32)
local bimg = b.cels[1].image
local cimg = c.cels[1].image
for y=0,31 do
for x=0,31 do
assert(bimg:getPixel(x, y) == cimg:getPixel(x, y))
end
end
local apal = a.palettes[1]
local bpal = b.palettes[1]
local cpal = c.palettes[1]
-- Same palette in a and c
assert(#apal == #cpal)
for i=0,#apal-1 do
assert(apal:getColor(i) == cpal:getColor(i))
end
-- b should contain a complete black palette
assert(bpal:getColor(0) == Color(0, 0, 0, 0))
for i=1,#bpal-1 do
assert(bpal:getColor(i) == Color(0, 0, 0, 255))
end
end
-- Resize image
do
local a = Sprite(3, 2)
local cel = a.cels[1]
assert(cel.bounds == Rectangle(0, 0, 3, 2))
local img = cel.image
local cols = { rgba(10, 60, 1), rgba(20, 50, 2), rgba(30, 40, 3),
rgba(40, 30, 4), rgba(50, 20, 5), rgba(60, 10, 6) }
array_to_pixels(cols, img)
expect_img(img, cols)
-- Test resize of a cel with origin=0,0
img:resize(img.width*2, img.height*2)
expect_eq(cel.bounds, Rectangle(0, 0, 6, 4))
expect_eq(img.width, 6)
expect_eq(img.height, 4)
local cols2 = { cols[1],cols[1], cols[2],cols[2], cols[3],cols[3],
cols[1],cols[1], cols[2],cols[2], cols[3],cols[3],
cols[4],cols[4], cols[5],cols[5], cols[6],cols[6],
cols[4],cols[4], cols[5],cols[5], cols[6],cols[6] }
expect_img(img, cols2)
-- Undo
function undo()
app.undo()
img = cel.image -- TODO img shouldn't be invalidated, the resize operation should kept the image ID
end
undo()
-- Test a resize when cel origin > 0,0
cel.position = Point(2, 1)
expect_eq(cel.bounds, Rectangle(2, 1, 3, 2))
expect_img(img, cols)
img:resize{ width=6, height=4 }
expect_eq(cel.bounds, Rectangle(2, 1, 6, 4)) -- Position is not modified
expect_eq(img.width, 6)
expect_eq(img.height, 4)
undo()
img:resize{ size=Size(6, 4), pivot=Point(1, 1) }
expect_eq(cel.bounds, Rectangle(1, 0, 6, 4))
undo()
img:resize{ size=Size(6, 4), pivot=Point(3, 2) }
expect_eq(cel.bounds, Rectangle(-1, -1, 6, 4))
-- Test resize without cel
local img2 = Image(img)
expect_img(img2, cols2)
img2:resize(3, 2)
expect_img(img2, cols)
end
-- Test v1.2.17 crashes
do
local defSpec = ImageSpec{ width=1, height=1, colorMode=ColorMode.RGB }
local img = Image() -- we create a 1x1 RGB image
assert(img ~= nil)
assert(img.spec == defSpec)
img = Image(nil)
assert(img ~= nil)
assert(img.spec == defSpec)
local spr = Sprite(32, 32, ColorMode.INDEXED)
spr.cels[1].image:putPixel(15, 15, 129)
img = Image(spr) -- we create a sprite render of the first frame
assert(img ~= nil)
assert(img.spec == spr.spec)
assert(img:getPixel(15, 15) == 129)
end
-- Fix drawImage() when drawing in a cel image
do
local a = Image(3, 2, ColorMode.INDEXED)
array_to_pixels({ 0, 1, 2,
2, 3, 4 }, a)
local function test(b)
expect_img(b, { 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0 })
b:drawImage(a, Point(2, 1))
expect_img(b, { 0, 0, 0, 0, 0,
0, 0, 0, 1, 2,
0, 0, 2, 3, 4,
0, 0, 0, 0, 0 })
b:drawImage(a, Point(0, 1))
expect_img(b, { 0, 0, 0, 0, 0,
0, 1, 2, 1, 2,
2, 3, 4, 3, 4,
0, 0, 0, 0, 0 })
b:drawImage(a, Point(-1, 2))
expect_img(b, { 0, 0, 0, 0, 0,
0, 1, 2, 1, 2,
1, 2, 4, 3, 4,
3, 4, 0, 0, 0 })
b:drawImage(a, Point(0, 3))
expect_img(b, { 0, 0, 0, 0, 0,
0, 1, 2, 1, 2,
1, 2, 4, 3, 4,
0, 1, 2, 0, 0 })
b:drawImage(a, Point(0, 3)) -- Do nothing
expect_img(b, { 0, 0, 0, 0, 0,
0, 1, 2, 1, 2,
1, 2, 4, 3, 4,
0, 1, 2, 0, 0 })
end
local b = Image(5, 4, ColorMode.INDEXED)
test(b)
local s = Sprite(5, 4, ColorMode.INDEXED)
test(app.activeCel.image)
end

View File

@ -0,0 +1,72 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local pc = app.pixelColor
-- Iterate pixels
do
local spr = Sprite(2, 2)
local image = app.site.image
local colors = { pc.rgba(255, 0, 0, 255),
pc.rgba(0, 255, 0, 255),
pc.rgba(255, 0, 255, 255),
pc.rgba(255, 0, 255, 255) }
local xy = {
{ x=0, y=0 },
{ x=1, y=0 },
{ x=0, y=1 },
{ x=1, y=1 } }
local c = 1
for y=0,image.height-1 do
for x=0,image.width-1 do
image:putPixel(x, y, colors[c])
c = c+1
end
end
c = 1
for y=0,image.height-1 do
for x=0,image.width-1 do
assert(colors[c] == image:getPixel(x, y))
c = c+1
end
end
c = 1
for it in image:pixels() do
assert(colors[c] == it())
assert(xy[c].x == it.x)
assert(xy[c].y == it.y)
c = c+1
end
c = 0
for it in image:pixels{x=1, y=0, width=1, height=2} do
local i = 1 + it.y*2 + it.x
assert(colors[i] == it())
assert(xy[i].x == it.x)
assert(xy[i].y == it.y)
c = c + 1
end
assert(c == 2)
-- Iterating outside
for it in image:pixels{x=2, y=0, width=2, height=2} do
assert(false)
end
c = 1
for it in image:pixels() do
it(pc.rgba(255, 32*c, 0, 255))
c = c+1
end
c = 1
for it in image:pixels() do
assert(pc.rgba(255, 32*c, 0, 255) == it())
c = c+1
end
end

View File

@ -0,0 +1,47 @@
-- Copyright (C) 2018 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local spec = ImageSpec{colorMode=ColorMode.GRAY, width=32, height=64, transparentColor=2}
assert(spec.colorMode == ColorMode.GRAY)
assert(spec.width == 32)
assert(spec.height == 64)
assert(spec.transparentColor == 2)
end
do
local sprite = Sprite(32, 64, ColorMode.INDEXED)
assert(sprite.width == 32)
assert(sprite.height == 64)
assert(sprite.colorMode == ColorMode.INDEXED)
local sprite2 = Sprite(sprite.spec)
assert(sprite2.width == 32)
assert(sprite2.height == 64)
assert(sprite2.colorMode == ColorMode.INDEXED)
local spec = sprite.spec
assert(spec.width == 32)
assert(spec.height == 64)
assert(spec.colorMode == ColorMode.INDEXED)
spec.width = 30
spec.height = 40
spec.colorMode = ColorMode.RGB
assert(spec.width == 30)
assert(spec.height == 40)
assert(spec.colorMode == ColorMode.RGB)
local image = Image(spec)
assert(image.width == 30)
assert(image.height == 40)
assert(image.colorMode == ColorMode.RGB)
print(image.spec.width, image.spec.height, image.spec.colorMode)
assert(image.spec.width == 30)
assert(image.spec.height == 40)
assert(image.spec.colorMode == ColorMode.RGB)
end

View File

@ -0,0 +1,75 @@
-- Copyright (C) 2021 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')
do
local s = Sprite(8, 4, ColorMode.INDEXED)
assert(#s.cels == 1)
local i = s.cels[1].image
array_to_pixels({ 0, 1, 2, 3, 3, 2, 1, 0,
1, 2, 3, 4, 4, 3, 2, 1,
1, 2, 3, 4, 4, 3, 2, 1,
0, 1, 2, 3, 3, 2, 1, 0 }, i)
app.command.ImportSpriteSheet{
ui=false,
type=SpriteSheetType.ROWS,
frameBounds=Rectangle(0, 0, 4, 4)
}
assert(#s.cels == 2)
expect_img(s.cels[1].image,
{ 0, 1, 2, 3,
1, 2, 3, 4,
1, 2, 3, 4,
0, 1, 2, 3 })
expect_img(s.cels[2].image,
{ 3, 2, 1, 0,
4, 3, 2, 1,
4, 3, 2, 1,
3, 2, 1, 0 })
app.undo();
app.command.ImportSpriteSheet{
ui=false,
type=SpriteSheetType.ROWS,
frameBounds=Rectangle(0, 0, 2, 3)
}
assert(#s.cels == 4)
expect_img(s.cels[1].image,
{ 0, 1,
1, 2,
1, 2 })
expect_img(s.cels[2].image,
{ 2, 3,
3, 4,
3, 4 })
expect_img(s.cels[3].image,
{ 3, 2,
4, 3,
4, 3 })
expect_img(s.cels[4].image,
{ 1, 0,
2, 1,
2, 1 })
app.undo();
app.command.ImportSpriteSheet{
ui=false,
type=SpriteSheetType.ROWS,
frameBounds=Rectangle(1, 1, 2, 2),
padding=Size(2, 0)
}
assert(#s.cels == 2)
expect_img(s.cels[1].image,
{ 2, 3,
2, 3 })
expect_img(s.cels[2].image,
{ 3, 2,
3, 2 })
end

285
tests/scripts/inks.lua Normal file
View File

@ -0,0 +1,285 @@
-- Copyright (C) 2020-2022 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

22
tests/scripts/layer.lua Normal file
View File

@ -0,0 +1,22 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 64)
local l = s.layers[1]
assert(l.parent == s)
assert(l.opacity == 255)
assert(l.blendMode == BlendMode.NORMAL)
l.name = "My Layer"
l.opacity = 128
l.blendMode = BlendMode.MULTIPLY
assert(l.name == "My Layer")
assert(l.opacity == 128)
assert(l.blendMode == BlendMode.MULTIPLY)
l.data = "Data"
assert(l.data == "Data")
end

215
tests/scripts/layers.lua Normal file
View File

@ -0,0 +1,215 @@
-- Copyright (C) 2019-2022 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 32)
assert(#s.layers == 1)
local a = s.layers[1]
local b = s:newLayer()
local c = s:newLayer()
assert(#s.layers == 3)
assert(s.layers[1] == a)
assert(s.layers[2] == b)
assert(s.layers[3] == c)
local i = 1
for k,v in ipairs(s.layers) do
assert(i == k)
assert(v == s.layers[k])
i = i+1
end
s:deleteLayer(b)
assert(#s.layers == 2)
assert(s.layers[1] == a)
assert(s.layers[2] == c)
end
-- Test groups
do
local s = Sprite(32, 64)
local l = s.layers[1]
assert(#s.layers == 1)
local g = s:newGroup()
assert(#s.layers == 2)
assert(l.parent == s)
assert(g.parent == s)
assert(s.layers[1] == l)
assert(s.layers[2] == g)
l.parent = g
assert(g.parent == s)
assert(l.parent == g)
assert(#s.layers == 1)
assert(s.layers[1] == g)
assert(#s.layers[1].layers == 1)
assert(s.layers[1].layers[1] == l)
end
do
local s = Sprite(4, 4)
-- 4 layers
local a = s.layers[1] a.name = "a"
local b = s:newLayer() b.name = "b"
local c = s:newLayer() c.name = "c"
local d = s:newLayer() d.name = "d"
-- 3 groups
local e = s:newGroup() e.name = "e"
local f = s:newGroup() f.name = "f"
local g = s:newGroup() g.name = "g"
e.parent = f
a.parent = f
b.parent = f
c.parent = g
d.parent = g
assert(#s.layers == 2)
assert(s.layers[1] == f)
assert(s.layers[2] == g)
assert(s.layers["f"] == f)
assert(s.layers["g"] == g)
assert(f.stackIndex == 1)
assert(g.stackIndex == 2)
assert(#f.layers == 3)
assert(f.layers[1] == e)
assert(f.layers[2] == a)
assert(f.layers[3] == b)
assert(f.layers["e"] == e)
assert(f.layers["a"] == a)
assert(f.layers["b"] == b)
assert(e.stackIndex == 1)
assert(a.stackIndex == 2)
assert(b.stackIndex == 3)
assert(#g.layers == 2)
assert(g.layers[1] == c)
assert(g.layers[2] == d)
assert(g.layers["c"] == c)
assert(g.layers["d"] == d)
assert(c.stackIndex == 1)
assert(d.stackIndex == 2)
d.stackIndex = 1
assert(d.stackIndex == 1)
assert(c.stackIndex == 2)
d.stackIndex = 2
assert(c.stackIndex == 1)
assert(d.stackIndex == 2)
c.stackIndex = 2
assert(d.stackIndex == 1)
assert(c.stackIndex == 2)
end
-- Test possible bugs with stackIndex
do
local s = Sprite(4, 4)
local a = s.layers[1] a.name = "a"
local b = s:newLayer() b.name = "b"
local c = s:newLayer() c.name = "c"
local d = s:newLayer() d.name = "d"
assert(d.stackIndex == 4)
assert(s.layers[4].name == "d")
d.stackIndex = d.stackIndex+1
assert(d.stackIndex == 4)
assert(s.layers[4].name == "d")
-- Go down in the stack
d.stackIndex = d.stackIndex-1
assert(s.layers[3].name == "d")
d.stackIndex = d.stackIndex-1
assert(s.layers[2].name == "d")
-- Without change
d.stackIndex = d.stackIndex
assert(s.layers[2].name == "d")
-- Go up
d.stackIndex = d.stackIndex+1
assert(d.stackIndex == 3)
assert(s.layers[3].name == "d")
d.stackIndex = d.stackIndex+1
assert(d.stackIndex == 4)
assert(s.layers[4].name == "d")
-- Go specific stack indexes
for i=1,4 do
d.stackIndex = i
assert(d.stackIndex == i)
assert(s.layers[i].name == "d")
end
end
-- Test crash because ActiveSiteHandler::onBeforeRemoveLayer() didn't
-- update the selected range of layers correctly (i.e. removing
-- deleted layer from the selected layers in the active range).
do
local s = Sprite(4, 4)
local a = s:newGroup() a.name = "a"
local b = s:newGroup() b.name = "b"
local c = s:newGroup() c.name = "c"
local ca = s:newGroup() ca.name = "ca"
local cb = s:newGroup() cb.name = "cb"
local d = s:newGroup() d.name = "d"
d.parent = ca
ca.parent = c
cb.parent = c
c.parent = b
b.parent = a
assert(#a.layers == 1)
assert(#c.layers == 2)
app.range.layers = { b }
app.command.RemoveLayer()
assert(#a.layers == 0)
app.undo()
assert(#a.layers == 1)
assert(#c.layers == 2)
-- Crash selecting a layer that was removed and then brought back to
-- life with "undo"
app.range.layers = { b }
end
-- Test layer name bug when iterating over layers where names given to
-- some layers are integers and also are valid ranges/indexes in the
-- list of layers
do
local layerNames = { "2", "4", "Non-integer", "1" }
local s = Sprite(4, 4)
local layer1 = s.layers[1] layer1.name = layerNames[1]
local layer2 = s:newLayer() layer2.name = layerNames[2]
local layer3 = s:newLayer() layer3.name = layerNames[3]
local layer4 = s:newLayer() layer4.name = layerNames[4]
local i = 1
for index, layer in ipairs(app.activeSprite.layers) do
assert(index == i)
assert(layer.name == layerNames[i])
i = i + 1
end
end
-- Compare layers vs sprites (just return false)
do
local s = Sprite(2, 2)
assert(s.layers[1].parent == s)
assert(s.layers[1] ~= s) -- Uses Layer_eq() to compare
assert(s ~= s.layers[1]) -- Uses Sprite_eq() to compare
end

10
tests/scripts/math.lua Normal file
View File

@ -0,0 +1,10 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert(100 == math.abs(-100))
assert(100 == math.min(100, 200, 300))
assert(300 == math.max(100, 200, 300))
assert(50 == math.fmod(250, 100))
assert(3141 == math.floor(1000*math.pi))

View File

@ -0,0 +1,27 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local red = Color{ r=255, g=0, b=0 }
local blue = Color{ r=0, g=0, b=255 }
-- Reproduces the bug reported in https://community.aseprite.org/t/2894
do
local s = Sprite(32, 32)
local a = s.layers[1]
app.useTool{ color=red, layer=a, points={ Point(2, 2) }}
local b = s:newLayer()
app.useTool{ color=blue, layer=b, points={ Point(1, 1) }}
a.isContinuous = true
b.isContinuous = true
app.command.NewFrame()
app.activeLayer = b
app.command.MergeDownLayer()
assert(#s.cels == 2)
assert(s.cels[1].image:isEqual(s.cels[2].image))
end

14
tests/scripts/os.lua Normal file
View File

@ -0,0 +1,14 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert("" ~= os.getenv("PATH"))
print("PATH", os.getenv("PATH"))
local start_clock = os.clock()
print("Start ", start_clock)
local end_clock = os.clock()
print("End ", end_clock, " Elapsed ", end_clock - start_clock)
assert(start_clock < end_clock)

View File

@ -0,0 +1,55 @@
-- Copyright (C) 2020-2021 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')
app.activeTool = 'paint_bucket'
assert(app.activeTool.id == 'paint_bucket')
assert(app.activeBrush.type == BrushType.CIRCLE)
assert(app.activeBrush.size == 1)
assert(app.activeBrush.angle == 0)
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 0)
local function test_paint_bucket(colorMode, a, b, c)
local spr = Sprite(4, 4, colorMode)
local img = app.activeImage
array_to_pixels({ a, a, a, a,
a, b, b, a,
a, a, b, a,
a, a, a, b, }, img)
app.useTool{ points={Point(0, 0)}, color=b }
expect_img(img, { b, b, b, b,
b, b, b, b,
b, b, b, b,
b, b, b, b, })
app.undo()
-- FOUR_CONNECTED=0
app.preferences.tool('paint_bucket').floodfill.pixel_connectivity = 0
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 0)
app.useTool{ points={Point(1, 1)}, color=c }
expect_img(img, { a, a, a, a,
a, c, c, a,
a, a, c, a,
a, a, a, b, })
app.undo()
-- EIGHT_CONNECTED=1
app.preferences.tool('paint_bucket').floodfill.pixel_connectivity = 1
assert(app.preferences.tool('paint_bucket').floodfill.pixel_connectivity == 1)
app.useTool{ points={Point(1, 1)}, color=c }
expect_img(img, { a, a, a, a,
a, c, c, a,
a, a, c, a,
a, a, a, c, })
end
local rgba = app.pixelColor.rgba
local gray = app.pixelColor.graya
test_paint_bucket(ColorMode.RGB, rgba(0, 0, 0), rgba(128, 128, 128), rgba(255, 255, 255))
test_paint_bucket(ColorMode.GRAYSCALE, gray(0), gray(128), gray(255))
test_paint_bucket(ColorMode.INDEXED, 1, 2, 3)

87
tests/scripts/palette.lua Normal file
View File

@ -0,0 +1,87 @@
-- Copyright (C) 2019 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local p = Palette()
assert(#p == 256)
for i = 0,#p-1 do
assert(p:getColor(i) == Color(0, 0, 0))
end
end
do
local p = Palette(32)
assert(#p == 32)
for i = 0,#p-1 do
assert(p:getColor(i) == Color(0, 0, 0))
end
p:resize(4)
assert(#p == 4)
p:setColor(0, Color(255, 8, 32))
p:setColor(1, Color(250, 4, 30))
p:setColor(2, Color(240, 3, 20))
p:setColor(3, Color(210, 2, 10))
assert(p:getColor(0) == Color(255, 8, 32))
assert(p:getColor(1) == Color(250, 4, 30))
assert(p:getColor(2) == Color(240, 3, 20))
assert(p:getColor(3) == Color(210, 2, 10))
-- Check alpha
local c = Color{red=100, green=50, blue=10, alpha=128}
p:setColor(3, c)
assert(p:getColor(3) == c)
assert(p:getColor(3).alpha == 128)
end
-- Load/save
do
local p = Palette{ fromFile="sprites/abcd.aseprite" }
assert(#p == 5)
assert(p:getColor(0) == Color(0, 0, 0))
assert(p:getColor(1) == Color(25, 0, 255))
assert(p:getColor(2) == Color(255, 0, 0))
assert(p:getColor(3) == Color(255, 255, 0))
assert(p:getColor(4) == Color(0, 128, 0))
p:saveAs("_test_.gpl")
local q = Palette{ fromFile="_test_.gpl" }
assert(#p == #q)
for i=0,#q-1 do
assert(p:getColor(i) == q:getColor(i))
end
end
-- Default palette and resources
do
local db16 = Palette{ fromResource="DB16" }
local db32 = Palette{ fromResource="DB32" }
assert(#db16 == 16)
assert(#db32 == 32)
assert(db32:getColor(0) == Color(0, 0, 0))
assert(db32:getColor(31) == Color(138, 111, 48))
assert(app.defaultPalette == db32)
app.defaultPalette = db16
assert(app.defaultPalette == db16)
-- Default sprite palette is completely black
-- TODO should we use the app.defaultPalette as the default palette?
local spr = Sprite(32, 32, ColorMode.INDEXED)
local sprPal = spr.palettes[1];
assert(#sprPal == 256)
assert(sprPal ~= db16)
assert(sprPal ~= db32)
for i=0,255 do
assert(sprPal:getColor(i) == Color(0, 0,0))
end
spr:setPalette(db32)
assert(sprPal == db32)
end

View File

@ -0,0 +1,361 @@
-- Copyright (C) 2019-2021 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 spr = Sprite(6, 6)
local cel = spr.cels[1]
-- Point size 1px, solid color, no symmetry, no tiled mode
do
local title = '1px, solid, no symmetry, no tiled'
local red = Color{ r=255, g=0, b=0 }
local r = red.rgbaPixel
local pixel=Brush{ size=1, type=BrushType.CIRCLE }
local testData = {
{
id='1 - ' .. title .. ': right then down',
points={ Point(2, 2), Point(3, 2), Point(3, 3) },
expected={ r, 0,
0, r }
},
{
id='2 - ' .. title .. ': down then right',
points={ Point(2, 2), Point(2, 3), Point(3, 3) },
expected={ r, 0,
0, r }
},
{
id='3 - ' .. title .. ': left then up',
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
expected={ r, 0,
0, r }
},
{
id='4 - ' .. title .. ': up then left',
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
expected={ r, 0,
0, r }
}
}
for i,v in ipairs(testData) do
app.useTool{
tool='pencil',
freehandAlgorithm=1,
brush=pixel,
color=red,
points=v.points}
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
cel.image:clear(0)
end
end
-- Point size 2px, translucent color, no symmetry, no tiled mode
do
local title = '2px, translucent, no symmetry, no tiled'
local red = Color{ r=255, g=0, b=0, a=127 }
local r = red.rgbaPixel
local square=Brush{ size=2, type=BrushType.SQUARE }
local testData = {
{
id='1 - ' .. title .. ': right then down',
points={ Point(2, 2), Point(3, 2), Point(3, 3) },
expected={ r, r, 0,
r, r, r,
0, r, r }
},
{
id='2 - ' .. title .. ': down then right',
points={ Point(2, 2), Point(2, 3), Point(3, 3) },
expected={ r, r, 0,
r, r, r,
0, r, r }
},
{
id='3 - ' .. title .. ': left then up',
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
expected={ r, r, 0,
r, r, r,
0, r, r }
},
{
id='4 - ' .. title .. ': up then left',
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
expected={ r, r, 0,
r, r, r,
0, r, r }
}
}
for i,v in ipairs(testData) do
app.useTool{
tool='pencil',
freehandAlgorithm=1,
brush=square,
color=red,
points=v.points}
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
cel.image:clear(0)
end
end
-- Point size 2px, translucent color, symmetry, no tiled mode
do
local pref = app.preferences
local docPref = pref.document(spr)
pref.symmetry_mode.enabled = true
docPref.symmetry.mode = 3
docPref.symmetry.x_axis = 3
docPref.symmetry.y_axis = 3
local title = '2px, translucent, symmetry on, no tiled'
local red = Color{ r=255, g=0, b=0, a=127 }
local r = red.rgbaPixel
local square=Brush{ size=2, type=BrushType.SQUARE }
local testData = {
{
id='1 - ' .. title .. ': right then down',
points={ Point(1, 1), Point(2, 1), Point(2, 2) },
expected={ r, r, 0, 0, r, r,
r, r, r, r, r, r,
0, r, r, r, r, 0,
0, r, r, r, r, 0,
r, r, r, r, r, r,
r, r, 0, 0, r, r }
},
{
id='2 - ' .. title .. ': down then right',
points={ Point(1, 1), Point(1, 2), Point(2, 2) },
expected={ r, r, 0, 0, r, r,
r, r, r, r, r, r,
0, r, r, r, r, 0,
0, r, r, r, r, 0,
r, r, r, r, r, r,
r, r, 0, 0, r, r }
},
{
id='3 - ' .. title .. ': left then up',
points={ Point(2, 2), Point(1, 2), Point(1, 1) },
expected={ r, r, 0, 0, r, r,
r, r, r, r, r, r,
0, r, r, r, r, 0,
0, r, r, r, r, 0,
r, r, r, r, r, r,
r, r, 0, 0, r, r }
},
{
id='4 - ' .. title .. ': up then left',
points={ Point(2, 2), Point(2, 1), Point(1, 1) },
expected={ r, r, 0, 0, r, r,
r, r, r, r, r, r,
0, r, r, r, r, 0,
0, r, r, r, r, 0,
r, r, r, r, r, r,
r, r, 0, 0, r, r }
}
}
for i,v in ipairs(testData) do
app.useTool{
tool='pencil',
freehandAlgorithm=1,
brush=square,
color=red,
points=v.points}
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
cel.image:clear(0)
end
end
-- Point size 2px, translucent color, no symmetry, tiled mode on
do
local pref = app.preferences
local docPref = pref.document(spr)
pref.symmetry_mode.enabled = false
docPref.tiled.mode = 3
local title = '2px, translucent, no symmetry, tiled'
local red = Color{ r=255, g=0, b=0, a=127 }
local r = red.rgbaPixel
local square=Brush{ size=2, type=BrushType.SQUARE }
local testData = {
-- Top left corner
{
id='1 - ' .. title .. ': on top left corner, right then down',
points={ Point(0, 0), Point(1, 0), Point(1, 1) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='2 - ' .. title .. ': on top left corner, down then right',
points={ Point(0, 0), Point(0, 1), Point(1, 1) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='3 - ' .. title .. ': on top left corner, left then up',
points={ Point(0, 0), Point(-1, 0), Point(-1, -1) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
{
id='4 - ' .. title .. ': on top left corner, up then left',
points={ Point(0, 0), Point(0, -1), Point(-1, -1) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
-- Top right corner
{
id='5 - ' .. title .. ': on top right corner, right then down',
points={ Point(6, 0), Point(7, 0), Point(7, 1) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='6 - ' .. title .. ': on top right corner, down then right',
points={ Point(6, 0), Point(6, 1), Point(7, 1) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='7 - ' .. title .. ': on top right corner, left then up',
points={ Point(6, 0), Point(5, 0), Point(5, -1) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
{
id='8 - ' .. title .. ': on top right corner, up then left',
points={ Point(6, 0), Point(5, 0), Point(5, -1) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
-- Bottom left corner
{
id='9 - ' .. title .. ': on bottom left corner, right then down',
points={ Point(0, 6), Point(1, 6), Point(1, 7) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='10 - ' .. title .. ': on bottom left corner, down then right',
points={ Point(0, 6), Point(0, 7), Point(1, 7) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='11 - ' .. title .. ': on bottom left corner, left then up',
points={ Point(0, 6), Point(-1, 6), Point(-1, 5) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
{
id='12 - ' .. title .. ': on bottom left corner, up then left',
points={ Point(0, 6), Point(0, 5), Point(-1, 5) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
-- Botomm right corner
{
id='13 - ' .. title .. ': on bottom right corner, right then down',
points={ Point(6, 6), Point(7, 6), Point(7, 7) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='14 - ' .. title .. ': on bottom right corner, down then right',
points={ Point(6, 6), Point(6, 7), Point(7, 7) },
expected={ r, r, 0, 0, 0, r,
r, r, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
r, 0, 0, 0, 0, r }
},
{
id='15 - ' .. title .. ': on bottom right corner, left then up',
points={ Point(6, 6), Point(5, 6), Point(5, 5) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
{
id='16 - ' .. title .. ': on bottom right corner, up then left',
points={ Point(6, 6), Point(6, 5), Point(5, 5) },
expected={ r, 0, 0, 0, 0, r,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, r, r,
r, 0, 0, 0, r, r }
},
}
for i,v in ipairs(testData) do
app.useTool{
tool='pencil',
freehandAlgorithm=1,
brush=square,
color=red,
points=v.points}
expect_img_msg(cel.image, v.expected, '\nTest \'' .. v.id .. '\' failed')
cel.image:clear(0)
end
end

75
tests/scripts/point.lua Normal file
View File

@ -0,0 +1,75 @@
-- Copyright (C) 2019 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local pt = Point()
assert(pt.x == 0)
assert(pt.y == 0)
pt = Point(1, 2)
assert(pt.x == 1)
assert(pt.y == 2)
assert("Point{ x=1, y=2 }" == tostring(pt))
local pt2 = Point(pt)
assert(pt2.x == 1)
assert(pt2.y == 2)
pt.x = 5
pt.y = 6
assert(pt.x == 5)
assert(pt.y == 6)
pt = Point{x=10, y=20}
assert(pt.x == 10)
assert(pt.y == 20)
pt = Point{45, 25}
assert(pt.x == 45)
assert(pt.y == 25)
pt = -pt
assert(pt.x == -45)
assert(pt.y == -25)
-- add/sub/mul/div/mod/pow/idiv
pt = Point(1, 2) + 4
pt2 = 4 + Point(1, 2)
assert(pt.x == 5)
assert(pt.y == 6)
assert(pt == pt2)
pt = Point(1, 2) + Point(3, 4)
assert(pt.x == 4)
assert(pt.y == 6)
pt = Point(3, 4) - 1
assert(pt.x == 2)
assert(pt.y == 3)
pt = Point(1, 5) - Point(3, 2)
assert(pt.x == -2)
assert(pt.y == 3)
pt = Point(6, 10) * 2
assert(pt.x == 12)
assert(pt.y == 20)
pt = Point(6, 10) / 2
assert(pt.x == 3)
assert(pt.y == 5)
pt = Point(10, 5) % 2
assert(pt.x == 0)
assert(pt.y == 1)
pt = Point(2, 5) ^ 2
assert(pt.x == 4)
assert(pt.y == 25)
pt = Point(31, 10) // 3
assert(pt.x == 10)
assert(pt.y == 3)

View File

@ -0,0 +1,10 @@
-- Copyright (C) 2019 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
-- Create global variable which will be GC'd on lua_close()
a = { }
-- Call print() on __gc, in previous version this produced a crash at exit
setmetatable(a, { __gc=function() print('gc') end })

118
tests/scripts/range.lua Normal file
View File

@ -0,0 +1,118 @@
-- Copyright (C) 2019-2020 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
-- Three layers
local s = Sprite(32, 32)
assert(#s.layers == 1)
app.activeCel = s.cels[1]
local r = app.range
assert(#r.layers == 1)
assert(#r.frames == 1)
assert(#r.cels == 1)
assert(r.layers[1] == s.layers[1])
assert(r.frames[1] == s.frames[1])
assert(r.cels[1] == s.cels[1])
s:newLayer()
assert(#s.layers == 2)
local r = app.range
assert(#r.layers == 1)
assert(#r.frames == 1)
assert(#r.cels == 0)
assert(r.layers[1] == s.layers[2])
assert(r.frames[1] == s.frames[1])
end
-- Test app.range.colors
do
assert(#app.range.colors == 0)
app.range.colors = { 2 }
assert(#app.range.colors == 1)
assert(app.range.colors[1] == 2)
app.range.colors = { 1, 4 }
assert(#app.range.colors == 2)
assert(app.range.colors[1] == 1)
assert(app.range.colors[2] == 4)
app.range.colors = { 5, 2, 10, 8, 0 }
assert(#app.range.colors == 5)
-- app.range.colors are always sorted by color index
assert(app.range.colors[1] == 0)
assert(app.range.colors[2] == 2)
assert(app.range.colors[3] == 5)
assert(app.range.colors[4] == 8)
assert(app.range.colors[5] == 10)
assert(app.range:containsColor(0))
assert(not app.range:containsColor(1))
assert(app.range:containsColor(2))
assert(app.range:containsColor(5))
assert(app.range:containsColor(8))
assert(app.range:containsColor(10))
end
-- Test setters
do
local spr = Sprite(32, 32)
local lay1 = spr.layers[1]
local r = app.range
assert(r.type == RangeType.EMPTY)
assert(#r.layers == 1)
assert(#r.frames == 1)
assert(r.layers[1] == lay1)
assert(r.frames[1].frameNumber == 1)
local lay2 = spr:newLayer()
r = app.range
assert(r.type == RangeType.EMPTY)
assert(#r.layers == 1)
assert(#r.frames == 1)
assert(r.layers[1] == lay2)
assert(r.frames[1].frameNumber == 1)
r.layers = { lay1, lay2 }
assert(r.type == RangeType.LAYERS)
assert(#r.layers == 2)
assert(#r.frames == 1)
assert(r.layers[1] == lay1)
assert(r.layers[2] == lay2)
assert(r.frames[1].frameNumber == 1)
spr:newFrame()
spr:newFrame()
r.frames = { 1, 3 }
assert(r.type == RangeType.FRAMES)
assert(#r.layers == 2)
assert(#r.frames == 2)
assert(r.layers[1] == lay1)
assert(r.layers[2] == lay2)
assert(r.frames[1].frameNumber == 1)
assert(r.frames[2].frameNumber == 3)
r.layers = { lay2 }
assert(r.type == RangeType.LAYERS)
assert(#r.layers == 1)
assert(#r.frames == 2)
assert(r.layers[1] == lay2)
assert(r.frames[1].frameNumber == 1)
assert(r.frames[2].frameNumber == 3)
-- Clear range
r:clear()
assert(r.type == RangeType.EMPTY)
assert(#r.layers == 1)
assert(#r.frames == 1)
assert(r.layers[1] == app.activeLayer)
assert(r.frames[1] == app.activeFrame)
-- Check that Range:clear() reset the selected colors
r.colors = { 2 }
assert(#r.colors == 1)
assert(r.colors[1] == 2)
r:clear()
assert(#r.colors == 0)
end

View File

@ -0,0 +1,72 @@
-- Copyright (C) 2019 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local rc = Rectangle()
assert(rc.x == 0)
assert(rc.y == 0)
assert(rc.width == 0)
assert(rc.height == 0)
assert(rc.isEmpty)
rc = Rectangle(1, 2, 3, 4)
assert(rc.x == 1)
assert(rc.y == 2)
assert(rc.width == 3)
assert(rc.height == 4)
assert(not rc.isEmpty)
assert("Rectangle{ x=1, y=2, width=3, height=4 }" == tostring(rc))
local rc2 = Rectangle(rc)
assert(rc2.x == 1)
assert(rc2.y == 2)
assert(rc2.width == 3)
assert(rc2.height == 4)
rc.x = 5;
rc.y = 6;
rc.width = 7;
rc.height = 8;
assert(rc.x == 5)
assert(rc.y == 6)
assert(rc.width == 7)
assert(rc.height == 8)
rc = Rectangle{x=2, y=3, width=4, height=5}
assert(rc.x == 2)
assert(rc.y == 3)
assert(rc.width == 4)
assert(rc.height == 5)
rc = Rectangle{6, 7, 8, 9}
assert(rc.x == 6)
assert(rc.y == 7)
assert(rc.width == 8)
assert(rc.height == 9)
-- Rectangle:contains
local a = Rectangle{x=2, y=3, width=4, height=5}
local b = Rectangle{x=3, y=4, width=1, height=1}
assert(a:contains(b))
assert(not b:contains(a))
-- Rectangle:intersect
assert(a:intersects(b))
assert(b == a:intersect(b))
a = Rectangle{x=2, y=3, width=4, height=5}
b = Rectangle{x=3, y=4, width=4, height=5}
c = Rectangle{x=3, y=4, width=3, height=4}
assert(c == a:intersect(b))
assert(c == b:intersect(a))
assert((a & b) == c)
-- Rectangle:union
c = Rectangle{x=2, y=3, width=5, height=6}
assert(c == a:union(b))
assert(c == (a | b))

View File

@ -0,0 +1,142 @@
-- Copyright (C) 2022 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
function fix_test_img(testImg, scale, fileExt, cm, c1)
-- With file formats that don't support alpha channel, we
-- compare totally transparent pixels (alpha=0) with black.
if fileExt == "tga" and cm == ColorMode.GRAYSCALE then
local pixel
if cm == ColorMode.RGB then
pixel = c1.rgbaPixel
elseif cm == ColorMode.GRAYSCALE then
pixel = c1.grayPixel
else
pixel = 0 -- Do nothing in indexed
end
for p in testImg:pixels() do
if p() == 0 then p(pixel) end
end
end
testImg:resize(testImg.width*scale, testImg.height*scale)
end
for _,cm in ipairs{ ColorMode.RGB,
ColorMode.GRAYSCALE,
ColorMode.INDEXED } do
local spr = Sprite(32, 32, cm)
spr.palettes[1]:resize(3)
spr.palettes[1]:setColor(0, Color(0, 0, 0, 0))
spr.palettes[1]:setColor(1, Color(0, 0, 0, 255))
spr.palettes[1]:setColor(2, Color(255, 0, 0, 255))
local c1, c2
if cm == ColorMode.RGB then
c1 = Color(0, 0, 0)
c2 = Color(255, 0, 0)
elseif cm == ColorMode.GRAYSCALE then
c1 = Color{ gray=0 }
c2 = Color{ gray=255 }
elseif cm == ColorMode.INDEXED then
c1 = 1
c2 = 2
end
app.useTool{ color=c1, brush=Brush(1),
tool="filled_ellipse", points={{0,0},{31,31}} }
app.useTool{ color=c2, brush=Brush(1),
tool="filled_ellipse", points={{4,4},{27,27}} }
spr.filename = "_test_a.aseprite"
app.command.SaveFile()
assert(spr.filename == "_test_a.aseprite")
app.command.SaveFileAs{ filename="_test_b.png" }
assert(spr.filename == "_test_b.png")
app.command.SaveFileCopyAs{ filename="_test_c.png" }
assert(spr.filename == "_test_b.png")
-- Scale
for _,fn in ipairs{ "_test_c_scaled.png",
"_test_c_scaled.gif",
"_test_c_scaled.fli",
"_test_c_scaled.tga",
"_test_c_scaled.bmp" } do
local fileExt = app.fs.fileExtension(fn)
-- TODO support saving any color mode to FLI files on the fly
if (fileExt ~= "fli" or cm == ColorMode.INDEXED) and
-- TODO Review grayscale support in bmp files
(fileExt ~= "bmp" or cm ~= ColorMode.GRAYSCALE) then
for _,scale in ipairs({ 1, 2, 3, 4 }) do
print(fn, scale, cm)
app.activeSprite = spr
app.command.SaveFileCopyAs{ filename=fn, scale=scale }
local c = app.open(fn)
assert(c.width == spr.width*scale)
assert(c.height == spr.height*scale)
-- GIF file is loaded as indexed, so we have to convert from
-- indexed to the ColorMode
if c.colorMode ~= cm then
assert(fileExt == "gif" or fileExt == "bmp")
if cm == ColorMode.RGB then
app.activeSprite = c
app.command.ChangePixelFormat{ format="rgb" }
elseif cm == ColorMode.GRAYSCALE then
app.activeSprite = c
app.command.ChangePixelFormat{ format="grayscale" }
else
assert(false)
end
end
local testImg = Image(spr.cels[1].image)
fix_test_img(testImg, scale, fileExt, cm, c1)
if not c.cels[1].image:isEqual(testImg) then
c.cels[1].image:saveAs("_testA.png")
testImg:saveAs("_testB.png")
end
assert(c.cels[1].image.colorMode == testImg.colorMode)
assert(c.cels[1].image:isEqual(testImg))
end
end
end
-- Scale + Slices
local slice = spr:newSlice(Rectangle(1, 2, 8, 15))
slice.name = "small_slice"
for _,fn in ipairs({ "_test_c_small_slice.png",
-- TODO slices aren't supported in gif/fli yet
--"_test_c_small_slice.gif",
--"_test_c_small_slice.fli",
"_test_c_small_slice.tga",
"_test_c_small_slice.bmp" }) do
local fileExt = app.fs.fileExtension(fn)
if (fileExt ~= "bmp" or cm ~= ColorMode.GRAYSCALE) then
for _,scale in ipairs({ 1, 2, 3, 4 }) do
print(fn, scale, cm)
app.activeSprite = spr
app.command.SaveFileCopyAs{ filename=fn, slice="small_slice", scale=scale }
local c = app.open(fn)
assert(c.width == slice.bounds.width*scale)
assert(c.height == slice.bounds.height*scale)
local testImg = Image(spr.cels[1].image, spr.slices[1].bounds)
fix_test_img(testImg, scale, fileExt, cm, c1)
if not c.cels[1].image:isEqual(testImg) then
c.cels[1].image:saveAs("_testA.png")
testImg:saveAs("_testB.png")
end
assert(c.cels[1].image:isEqual(testImg))
end
end
end
end

121
tests/scripts/selection.lua Normal file
View File

@ -0,0 +1,121 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
-- Isolated selection
do
local a = Selection()
assert(a.bounds.x == 0)
assert(a.bounds.y == 0)
assert(a.bounds.width == 0)
assert(a.bounds.height == 0)
assert(a.isEmpty)
a:select(1, 2, 3, 4)
assert(a.bounds.x == 1)
assert(a.bounds.y == 2)
assert(a.bounds.width == 3)
assert(a.bounds.height == 4)
assert(not a.isEmpty)
assert(a:contains(1, 2))
assert(a:contains(1+3-1, 2+4-1))
assert(not a:contains(0, 1))
assert(not a:contains(1+3, 2+4))
a:select{x=5, y=6, width=7, height=8}
assert(a.bounds.x == 5)
assert(a.bounds.y == 6)
assert(a.bounds.width == 7)
assert(a.bounds.height == 8)
a:deselect()
assert(a.bounds.x == 0)
assert(a.bounds.y == 0)
assert(a.bounds.width == 0)
assert(a.bounds.height == 0)
assert(a.isEmpty)
assert(not a:contains(0, 0))
-- Constructor with rectangles
local b = Selection(1, 2, 3, 4)
assert(b.bounds == Rectangle(1, 2, 3, 4))
assert(b.origin == Point(1, 2))
-- Move
b.origin = Point(5, 6)
assert(b.bounds == Rectangle(5, 6, 3, 4))
assert(b.origin == Point(5, 6))
end
-- Sprite Selection
do
local spr = Sprite(32, 32)
local sel = spr.selection
assert(sel.bounds.x == 0)
assert(sel.bounds.y == 0)
assert(sel.bounds.width == 0)
assert(sel.bounds.height == 0)
sel:selectAll()
assert(sel.bounds.x == 0)
assert(sel.bounds.y == 0)
assert(sel.bounds.width == spr.width)
assert(sel.bounds.height == spr.height)
sel:select(2, 3, 4, 5)
assert(sel.bounds.x == 2)
assert(sel.bounds.y == 3)
assert(sel.bounds.width == 4)
assert(sel.bounds.height == 5)
sel.origin = Point(5, 6)
assert(sel.bounds == Rectangle(5, 6, 4, 5))
end
-- Comparison
do
local a = Selection()
local b = Selection()
assert(a == b)
a:select(0, 0, 1, 1)
assert(a ~= b)
b:add(a)
assert(a == b)
a:subtract(b)
assert(a ~= b)
b:subtract(b)
assert(a == b)
end
-- Operations
do
local a = Selection()
a:select(2, 3, 4, 5)
assert(a.bounds == Rectangle(2, 3, 4, 5))
a:subtract(2, 3, 4, 1)
assert(a.bounds == Rectangle(2, 4, 4, 4))
assert(a:contains(3, 5))
a:subtract(3, 5, 1, 1)
assert(not a:contains(3, 5))
assert(a.bounds == Rectangle(2, 4, 4, 4))
local b = Selection()
assert(a.bounds == Rectangle(2, 4, 4, 4))
assert(b.isEmpty)
a:subtract(b) -- This should be a no-op because b is empty
assert(a.bounds == Rectangle(2, 4, 4, 4))
b:select(0, 0, 32, 32)
assert(a ~= b)
b:intersect(a)
assert(a == b)
assert(b.bounds == Rectangle(2, 4, 4, 4))
assert(b.bounds == Rectangle(2, 4, 4, 4))
end

View File

@ -0,0 +1,28 @@
-- Copyright (C) 2021 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')
----------------------------------------------------------------------
-- Test magic wand in transparent layer
-- Note: A regression in the beta was found in this case.
do
local s = Sprite(4, 4, ColorMode.INDEXED)
app.command.LayerFromBackground()
local i = s.cels[1].image
i:clear(0)
i:putPixel(0, 0, 1)
expect_eq(4, i.width)
expect_eq(4, i.height)
app.useTool{ tool='magic_wand', points={Point(0, 0)} }
expect_eq(Rectangle(0, 0, 1, 1), s.selection.bounds)
app.useTool{ tool='magic_wand', points={Point(1, 0)} }
expect_eq(Rectangle(0, 0, 4, 4), s.selection.bounds)
assert(not s.selection:contains(0, 0))
end

75
tests/scripts/size.lua Normal file
View File

@ -0,0 +1,75 @@
-- Copyright (C) 2019 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
local sz = Size()
assert(sz.width == 0)
assert(sz.height == 0)
sz = Size(3, 4)
assert(sz.width == 3)
assert(sz.height == 4)
assert("Size{ width=3, height=4 }" == tostring(sz))
local sz2 = Size(sz)
assert(sz2.width == 3)
assert(sz2.height == 4)
sz.width = 7
sz.height = 8
assert(sz.width == 7)
assert(sz.height == 8)
sz = Size{width=10, height=20}
assert(sz.width == 10)
assert(sz.height == 20)
sz = Size{45, 25}
assert(sz.width == 45)
assert(sz.height == 25)
sz = -sz
assert(sz.width == -45)
assert(sz.height == -25)
-- add/sub/mul/div/mod/pow/idiv
sz = Size(1, 2) + 4
sz2 = 4 + Size(1, 2)
assert(sz.width == 5)
assert(sz.height == 6)
assert(sz == sz2)
sz = Size(1, 2) + Size(3, 4)
assert(sz.width == 4)
assert(sz.height == 6)
sz = Size(3, 4) - 1
assert(sz.width == 2)
assert(sz.height == 3)
sz = Size(8, 5) - Size(3, 2)
assert(sz.width == 5)
assert(sz.height == 3)
sz = Size(6, 10) * 2
assert(sz.width == 12)
assert(sz.height == 20)
sz = Size(6, 10) / 2
assert(sz.width == 3)
assert(sz.height == 5)
sz = Size(10, 5) % 2
assert(sz.width == 0)
assert(sz.height == 1)
sz = Size(2, 5) ^ 2
assert(sz.width == 4)
assert(sz.height == 25)
sz = Size(31, 10) // 3
assert(sz.width == 10)
assert(sz.height == 3)

27
tests/scripts/slice.lua Normal file
View File

@ -0,0 +1,27 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 32)
local a = s:newSlice(0, 0, 32, 32)
assert(a.bounds == Rectangle(0, 0, 32, 32))
assert(a.sprite == s)
assert(a.name == "Slice")
a.name = "Slice A"
assert(a.name == "Slice A")
assert(a.center == nil)
a.center = Rectangle(2, 3, 28, 20)
assert(a.center == Rectangle(2, 3, 28, 20))
assert(a.pivot == nil)
a.pivot = Point(16, 17)
assert(a.pivot == Point(16, 17))
a.data = "Data"
assert(a.data == "Data")
end

40
tests/scripts/slices.lua Normal file
View File

@ -0,0 +1,40 @@
-- Copyright (C) 2022 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 32)
local a = s:newSlice()
local b = s:newSlice(0, 2, 8, 10)
local c = s:newSlice{ x=0, y=0, width=32, height=32 }
assert(a.bounds == nil)
assert(b.bounds == Rectangle(0, 2, 8, 10))
assert(c.bounds == Rectangle(0, 0, 32, 32))
local bounds = { nil, Rectangle(0, 2, 8, 10), Rectangle(0, 0, 32, 32) }
local i = 1
for k,v in ipairs(s.slices) do
assert(i == k)
assert(v == s.slices[k])
assert(bounds[i] == s.slices[k].bounds)
i = i+1
end
s:deleteSlice(b)
assert(a == s.slices[1])
assert(c == s.slices[2])
assert(2 == #s.slices)
app.undo()
assert(3 == #s.slices)
app.undo()
assert(2 == #s.slices)
app.undo()
assert(1 == #s.slices)
app.undo()
assert(0 == #s.slices)
end

208
tests/scripts/sprite.lua Normal file
View File

@ -0,0 +1,208 @@
-- Copyright (C) 2019-2022 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local a = Sprite(32, 64)
assert(a.width == 32)
assert(a.height == 64)
assert(a.colorMode == ColorMode.RGB) -- RGB by default
assert(a.bounds == Rectangle{x=0, y=0, width=32, height=64})
-- Crop and resize
a.selection:select(2, 3, 4, 5)
a:crop()
assert(a.width == 4)
assert(a.height == 5)
assert(a.cels[1].image.width == 32)
assert(a.cels[1].image.height == 64)
a:resize(6, 8)
assert(a.width == 6)
assert(a.height == 8)
assert(a.cels[1].image.width == 32 * 6 / 4) -- Check that the image was resized (not only the canvas)
assert(a.cels[1].image.height == 64 * 8 / 5)
a:crop{x=-1, y=-1, width=20, height=30}
assert(a.width == 20)
assert(a.height == 30)
-- Resize sprite setting width/height (just changing canvas size)
a.width = 8
a.height = 10
assert(a.width == 8)
assert(a.height == 10)
-- Test other Sprite() constructors
local b = Sprite(4, 8, ColorMode.INDEXED)
assert(b.width == 4)
assert(b.height == 8)
assert(b.colorMode == ColorMode.INDEXED)
local c = Sprite{ colorMode=ColorMode.INDEXED, width=10, height=20 }
assert(c.width == 10)
assert(c.height == 20)
assert(c.colorMode == ColorMode.INDEXED)
local d = Sprite{ fromFile="sprites/abcd.aseprite" }
assert(#d.layers == 4)
assert(d.width == 32)
assert(d.height == 32)
assert(d.colorMode == ColorMode.INDEXED)
end
-- Transparent color
do
local a = Sprite(32, 32, ColorMode.INDEXED)
assert(a.transparentColor == 0)
a.transparentColor = 8
assert(a.transparentColor == 8)
end
-- Palette
do
local a = Sprite(32, 32, ColorMode.INDEXED)
assert(#a.palettes == 1)
assert(#a.palettes[1] == 256)
local p = Palette(3)
p:setColor(0, Color(255, 0, 0))
p:setColor(1, Color(0, 255, 0))
p:setColor(2, Color(0, 0, 255))
a:setPalette(p)
assert(#a.palettes == 1)
assert(#a.palettes[1] == 3)
assert(a.palettes[1]:getColor(0) == Color(255, 0, 0))
assert(a.palettes[1]:getColor(1) == Color(0, 255, 0))
assert(a.palettes[1]:getColor(2) == Color(0, 0, 255))
end
-- Duplicate & Flatten
do
local a = Sprite(32, 32)
a:newLayer()
a:newLayer()
assert(#a.layers == 3)
local b = Sprite(a) -- Clone a
a:flatten() -- Flatten a
assert(#a.layers == 1)
assert(#b.layers == 3)
end
-- Resize non-active sprite
do
local a = Sprite(32, 32)
local b = Sprite(64, 64)
app.activeSprite = a
a:resize(10, 10)
b:resize(20, 20)
assert(a.width == 10)
assert(a.height == 10)
assert(b.width == 20)
assert(b.height == 20)
app.undo()
assert(a.width == 32)
assert(a.height == 32)
app.activeSprite = b
app.undo()
assert(b.width == 64)
assert(b.height == 64)
end
-- Grid bounds
do
local s = Sprite(32, 32)
assert(s.gridBounds == Rectangle{0, 0, 16, 16})
s.gridBounds = Rectangle{2, 3, 8, 4}
assert(s.gridBounds == Rectangle{2, 3, 8, 4})
s:saveAs("_test_sprite_gridbounds.aseprite")
local s2 = Sprite{ fromFile="_test_sprite_gridbounds.aseprite" }
assert(s2.gridBounds == Rectangle{2, 3, 8, 4})
end
-- Pixel ratio
do
local s = Sprite(32, 32)
assert(s.pixelRatio == Size{1, 1})
s.pixelRatio = Size{3, 2}
assert(s.pixelRatio == Size{3, 2})
s:saveAs("_test_sprite_pixelratio.aseprite")
local s2 = Sprite{ fromFile="_test_sprite_pixelratio.aseprite" }
assert(s2.pixelRatio == Size{3, 2})
end
-- Sprite{ fromFile, oneFrame }
do
local s = Sprite(32, 32)
s:newFrame()
s:saveAs("_test1.png")
assert(#s.frames == 2)
s = Sprite{ fromFile="_test1.png" }
assert(#s.frames == 2)
s = Sprite{ fromFile="_test1.png", oneFrame=true }
assert(#s.frames == 1)
s = Sprite{ fromFile="_test1.png", oneFrame=false }
assert(#s.frames == 2)
end
-- Issues with sprites having pixel with indexes out of palette bounds:
-- Saving png failed (https://github.com/aseprite/aseprite/issues/2842)
do
local s = Sprite(2, 2, ColorMode.INDEXED)
assert(#s.palettes == 1)
s.transparentColor = 1
s.palettes[1]:resize(8)
assert(#s.palettes[1] == 8)
s.cels[1].image:clear(2)
s.cels[1].image:putPixel(0, 0, 7)
s:saveAs("_test1_.png") -- OK
s.palettes[1]:resize(4)
assert(#s.palettes[1] == 4)
local result = s:saveAs("_test2_palerr_.png") -- Used to fail
-- If result=false we got a "libpng: Wrote palette index exceeding num_palette"
assert(result)
local s2 = app.open("_test2_palerr_.png")
assert(s2 ~= nil)
print(s2.cels[1].image:getPixel(0, 0))
assert(s2.cels[1].image:getPixel(0, 0) == 1)
end
-- Flatten visible layers uses indices outside the palette range as opaque colors instead of transparent color (https://github.com/aseprite/aseprite/issues/2912)
do
local s = Sprite(2, 2, ColorMode.INDEXED)
s.transparentColor = 0
s.palettes[1]:resize(4)
s.cels[1].image:clear(1)
local l = s:newLayer()
s:newCel(l)
s.cels[2].image:putPixel(0, 0, 2)
s.cels[2].image:putPixel(1, 0, 7)
s:flatten()
assert(s.cels[1].image:getPixel(0, 0) == 2)
assert(s.cels[1].image:getPixel(1, 0) == 1) -- Get the color of the first layer
end
-- Compare sprite IDs
do
local a = Sprite(1, 1)
local b = Sprite(1, 1)
assert(a == a)
assert(a ~= b) -- Compares IDs, not sprite size
end

23
tests/scripts/string.lua Normal file
View File

@ -0,0 +1,23 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert(72 == string.byte("Hello", 1))
assert(101 == string.byte("Hello", 2))
assert(111 == string.byte("Hello", 5))
assert("Hello" == string.char(72, 101, 108, 108, 111))
local s = "Hello"
assert(111 == s:byte(5))
assert(5 == string.len(s))
assert("olleH" == string.reverse(s))
assert("hello" == string.lower(s))
assert("HELLO" == string.upper(s))
assert("Simple int 32" == string.format("Simple int %d", 32))
assert("Simple int 0032" == string.format("Simple int %04d", 32))
assert(7 == string.find("Hello World!", "W"))
assert("-- hi 1000 --" == string.format("-- %s %d --", "hi", 1000))

45
tests/scripts/tag.lua Normal file
View File

@ -0,0 +1,45 @@
-- Copyright (C) 2020 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 32)
for i = 1,7 do s:newFrame() end
assert(#s.frames == 8)
a = s:newTag(1, 8)
assert(a.sprite == s)
assert(a.fromFrame.frameNumber == 1)
assert(a.toFrame.frameNumber == 8)
assert(a.frames == 8)
a.fromFrame = 2
a.toFrame = 5
assert(a.fromFrame.frameNumber == 2)
assert(a.toFrame.frameNumber == 5)
assert(a.name == "Tag")
a.name = "Tag A"
assert(a.name == "Tag A")
assert(a.aniDir == AniDir.FORWARD) -- Default AniDir is FORWARD
a.aniDir = AniDir.REVERSE
assert(a.aniDir == AniDir.REVERSE)
a.aniDir = AniDir.PING_PONG
assert(a.aniDir == AniDir.PING_PONG)
a.aniDir = AniDir.FORWARD
assert(a.aniDir == AniDir.FORWARD)
assert(a.color == Color(0, 0, 0))
a.color = Color(255, 0, 0)
assert(a.color == Color(255, 0, 0))
assert(a.repeats == 0)
a.repeats = 1
assert(a.repeats == 1)
a.data = "Data"
assert(a.data == "Data")
end

36
tests/scripts/tags.lua Normal file
View File

@ -0,0 +1,36 @@
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
do
local s = Sprite(32, 32)
for i = 1,7 do s:newFrame() end
assert(#s.frames == 8)
a = s:newTag(1, 2)
b = s:newTag(3, 4)
c = s:newTag(5, 8)
assert(a.frames == 2)
assert(b.frames == 2)
assert(c.frames == 4)
assert(a == s.tags[1])
assert(b == s.tags[2])
assert(c == s.tags[3])
local i = 1
for k,v in ipairs(s.tags) do
assert(i == k)
assert(v == s.tags[k])
i = i+1
end
s:deleteTag(b)
assert(a == s.tags[1])
assert(c == s.tags[2])
assert(c.fromFrame.frameNumber == 5)
assert(c.toFrame.frameNumber == 8)
end

View File

@ -0,0 +1,134 @@
-- Copyright (C) 2019-2020 Igara Studio S.A.
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
function expect_eq(a, b)
if a ~= b then
print(debug.traceback())
print('Expected A == B but:')
print(' - Value A = ' .. tostring(a))
print(' - Value B = ' .. tostring(b))
assert(a == b)
end
end
local function dump_img(image)
local w = image.width
local h = image.height
print('Image(' .. tostring(w) .. 'x' .. tostring(h) .. ') = {')
for v=0,h-1 do
local lineStr = ' '
for u=0,w-1 do
lineStr = lineStr .. image:getPixel(u, v) .. ','
end
print(lineStr)
end
print('}')
end
function expect_img(image, expectedPixels)
local w = image.width
local h = image.height
if w*h ~= #expectedPixels then
print(debug.traceback())
print('Expected pixels: #=' .. #expectedPixels)
print('Image size: w=' .. w .. ' h=' .. h .. ' #=' .. w*h)
dump_img(image)
assert(w*h == #expectedPixels)
end
for y=0,h-1 do
for x=0,w-1 do
local value = image:getPixel(x, y)
local expected = expectedPixels[1+y*w+x]
if value ~= expected then
dump_img(image)
print('In pixel (' .. x .. ', ' .. y .. '):')
local a = value
local b = expected
print(debug.traceback())
print('Expected A == B but:')
if image.colorMode == ColorMode.RGB then
print(string.format(' - Value A = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(a),
app.pixelColor.rgbaG(a),
app.pixelColor.rgbaB(a),
app.pixelColor.rgbaA(a)))
print(string.format(' - Value B = rgba(%d,%d,%d,%d)',
app.pixelColor.rgbaR(b),
app.pixelColor.rgbaG(b),
app.pixelColor.rgbaB(b),
app.pixelColor.rgbaA(b)))
elseif image.colorMode == ColorMode.GRAY then
print(string.format(' - Value A = gray(%d,%d)',
app.pixelColor.grayaV(a),
app.pixelColor.grayaA(a)))
print(string.format(' - Value B = gray(%d,%d)',
app.pixelColor.grayaV(b),
app.pixelColor.grayaA(b)))
else
print(' - Value A = ' .. tostring(a))
print(' - Value B = ' .. tostring(b))
end
assert(a == b)
end
end
end
end
function expect_img_msg(image, expectedPixels, msg)
local status, err = pcall(expect_img, image, expectedPixels)
if not status then
print(msg)
error(err)
end
end
function array_to_pixels(array, image)
local w = image.width
local h = image.height
assert(w*h == #array)
local i = 1
for y=0,h-1 do
for x=0,w-1 do
image:drawPixel(x, y, array[i])
i = i+1
end
end
end
-- Returns true if the given array (layers) of layers
function expect_rendered_layers(expectedImage, sprite, layerNames, frame)
function contains_layer(name)
for _,n in ipairs(layerNames) do
if name == n then return true end
end
return false
end
if frame == nil then frame = 1 end
local render = Image(sprite.spec)
function render_layers(prefix, layers)
for _,layer in ipairs(layers) do
if layer.isGroup then
render_layers(layer.name.."/", layer.layers)
end
if contains_layer(prefix..layer.name) then
local cel = layer:cel(frame)
if cel then
render:drawImage(cel.image, cel.position)
end
end
end
end
render_layers("", sprite.layers)
if not expectedImage:isEqual(render) then
print("Rendering:")
for _,n in ipairs(layerNames) do
print(" - " .. n)
end
error("render doesn't match to the expected image")
end
end

1119
tests/scripts/tilemap.lua Normal file

File diff suppressed because it is too large Load Diff

684
tests/scripts/tools.lua Normal file
View File

@ -0,0 +1,684 @@
-- Copyright (C) 2019-2020 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 rgba = app.pixelColor.rgba
local gray = app.pixelColor.graya
----------------------------------------------------------------------
-- activeTool
----------------------------------------------------------------------
local pencil = app.activeTool -- pencil is the default tool
assert(pencil ~= nil)
assert(pencil.id == 'pencil')
app.activeTool = 'line'
assert(app.activeTool.id == 'line')
app.activeTool = pencil
assert(app.activeTool.id == 'pencil')
-- default brush is a circle of 1x1 when there is no UI
assert(app.activeBrush.type == BrushType.CIRCLE)
assert(app.activeBrush.size == 1)
assert(app.activeBrush.angle == 0)
----------------------------------------------------------------------
-- create sprite for testing
----------------------------------------------------------------------
local spr = Sprite(4, 4)
local cel = spr.cels[1]
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
----------------------------------------------------------------------
-- pencil and eraser
----------------------------------------------------------------------
app.useTool{
tool='pencil',
color=Color{ r=0, g=0, b=0 },
points={ Point(2, 2),
Point(3, 2) }}
expect_eq(cel.bounds, Rectangle(2, 2, 2, 1))
app.useTool{
tool='eraser',
points={ Point(2, 2) }}
expect_eq(cel.bounds, Rectangle(3, 2, 1, 1))
app.useTool{
tool='eraser',
points={ Point(3, 2) }}
-- This must fail because cel is pointing to an invalid cel now.
-- TODO: In a future this could change if this issue:
-- https://github.com/aseprite/aseprite/issues/1833
-- is implemented.
assert(not pcall(function() print(cel.bounds) end))
----------------------------------------------------------------------
-- line
----------------------------------------------------------------------
local red = Color{ r=255, g=0, b=0 }
app.useTool{
tool='line',
color=red,
points={ Point(0, 0), Point(3, 3) }}
local cel = spr.cels[1]
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
do
local r = red.rgbaPixel
local expected = { r, 0, 0, 0,
0, r, 0, 0,
0, 0, r, 0,
0, 0, 0, r }
assert(cel.image.width == 4)
assert(cel.image.height == 4)
for v=0,3 do
for u=0,3 do
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
end
end
end
----------------------------------------------------------------------
-- paint_bucket
----------------------------------------------------------------------
app.useTool{
tool='paint_bucket',
color=red,
points={ Point(3, 0) }}
local cel = spr.cels[1]
do
local r = red.rgbaPixel
local expected = { r, r, r, r,
0, r, r, r,
0, 0, r, r,
0, 0, 0, r }
assert(cel.image.width == 4)
assert(cel.image.height == 4)
for v=0,3 do
for u=0,3 do
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
end
end
end
----------------------------------------------------------------------
-- rectangle
----------------------------------------------------------------------
local blue = Color{ r=0, g=0, b=255 }
app.useTool{
tool='rectangle',
color=blue,
points={ Point(0, 0), Point(3, 3) }}
local cel = spr.cels[1]
do
local r = red.rgbaPixel
local b = blue.rgbaPixel
local expected = { b, b, b, b,
b, r, r, b,
b, 0, r, b,
b, b, b, b }
assert(cel.image.width == 4)
assert(cel.image.height == 4)
for v=0,3 do
for u=0,3 do
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
end
end
end
----------------------------------------------------------------------
-- ellipse
----------------------------------------------------------------------
local yellow = Color{ r=255, g=255, b=0 }
app.useTool{
tool='ellipse',
color=yellow,
points={ Point(0, 0), Point(3, 3) }}
local cel = spr.cels[1]
do
local r = red.rgbaPixel
local b = blue.rgbaPixel
local y = yellow.rgbaPixel
local expected = { b, y, y, b,
y, r, r, y,
y, 0, r, y,
b, y, y, b }
assert(cel.image.width == 4)
assert(cel.image.height == 4)
for v=0,3 do
for u=0,3 do
assert(cel.image:getPixel(u, v) == expected[1+v*4+u])
end
end
end
----------------------------------------------------------------------
-- draw in several cels
----------------------------------------------------------------------
do
local spr2 = Sprite(4, 4)
spr2:newFrame()
local bgLay = spr2.layers[1]
local fgLay = spr2:newLayer()
local bgCel1 = spr2:newCel(fgLay, 1, Image(spr2.spec))
local fgCel1 = spr2:newCel(bgLay, 1, Image(spr2.spec))
local bgCel2 = spr2:newCel(fgLay, 2, Image(spr2.spec))
local fgCel2 = spr2:newCel(bgLay, 2, Image(spr2.spec))
expect_eq(fgCel1.bounds, Rectangle(0, 0, 4, 4))
expect_eq(bgCel1.bounds, Rectangle(0, 0, 4, 4))
expect_eq(fgCel2.bounds, Rectangle(0, 0, 4, 4))
expect_eq(bgCel2.bounds, Rectangle(0, 0, 4, 4))
-- After each useTool(), the cels will be shrunken to the minimum
-- required size.
app.activeTool = 'pencil'
app.useTool{ color=red, cel=bgCel1, points={ Point(0, 0) }}
app.useTool{ color=red, layer=bgCel2.layer, frame=bgCel2.frame, points={ Point(1, 0) }}
-- After using the tool in bgCel2, the activeFrame is the frame
-- number 2.
assert(bgCel2.frame == app.activeFrame)
assert(bgCel2.frame == fgCel2.frame)
app.activeFrame = fgCel1.frame
app.useTool{ color=yellow, layer=fgCel1.layer, points={ Point(1, 1) }}
app.useTool{ color=yellow, cel=fgCel2, points={ Point(2, 1) }}
expect_eq(bgCel1.bounds, Rectangle(0, 0, 1, 1))
expect_eq(bgCel2.bounds, Rectangle(1, 0, 1, 1))
expect_eq(fgCel1.bounds, Rectangle(1, 1, 1, 1))
expect_eq(fgCel2.bounds, Rectangle(2, 1, 1, 1))
assert(bgCel1.image:getPixel(0, 0) == red.rgbaPixel)
assert(bgCel2.image:getPixel(0, 0) == red.rgbaPixel)
assert(fgCel1.image:getPixel(0, 0) == yellow.rgbaPixel)
assert(fgCel2.image:getPixel(0, 0) == yellow.rgbaPixel)
end
----------------------------------------------------------------------
-- draw with brushes
----------------------------------------------------------------------
function drawing_with_simple_brushes(colorMode, a, b, c)
print("drawing_with_simple_brushes", colorMode)
local expectedImages = {
{ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 },
{ 0, 0, 0, 0,
0, a, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 },
{ 0, 0, 0, 0,
0, b, b, 0,
0, b, b, 0,
0, 0, 0, 0 },
{ c, c, c, 0,
c, c, c, c,
c, c, c, c,
0, c, c, c }
}
local s = Sprite(4, 4, colorMode)
assert(s == app.activeSprite)
assert(s.cels[1] == app.activeCel)
function expect_cel_is_image(imageIndex)
local a = Image(s.spec)
a:drawSprite(s, 1, Point(0, 0))
local b = expectedImages[imageIndex]
expect_img(a, b)
end
expect_cel_is_image(1)
app.useTool{ tool='pencil', color=a, points={ Point(1, 1) } }
assert(#s.cels == 1)
expect_cel_is_image(2)
app.undo()
expect_cel_is_image(1)
app.useTool{ tool='pencil',
brush=Brush{ size=2, type=BrushType.SQUARE },
color=b, points={ Point(2, 2) } }
expect_cel_is_image(3)
app.undo()
expect_cel_is_image(1)
app.useTool{ tool='pencil',
brush=Brush{ size=2, type=BrushType.SQUARE, center=Point(0, 0) },
color=b, points={ Point(1, 1) } }
expect_cel_is_image(3)
app.undo()
expect_cel_is_image(1)
app.useTool{ tool='line',
brush={ size=3, type=BrushType.SQUARE },
color=c, points={ Point(1, 1), Point(2, 2) } }
expect_cel_is_image(4)
app.undo()
end
do
drawing_with_simple_brushes(ColorMode.RGB, red.rgbaPixel, blue.rgbaPixel, yellow.rgbaPixel)
drawing_with_simple_brushes(ColorMode.GRAY, gray(255), gray(128), gray(32))
drawing_with_simple_brushes(ColorMode.INDEXED, 1, 2, 3)
end
----------------------------------------------------------------------
-- draw with special image brushes + patterns
----------------------------------------------------------------------
function drawing_with_image_brushes(imageColorMode, colorInImage,
brushColorMode, colorInBrush, palette)
print("drawing_with_image_brushes", imageColorMode, brushColorMode)
local s = Sprite(4, 4, imageColorMode)
local c = colorInImage
cel = s.cels[1]
if palette then
s:setPalette(palette)
end
-- Brush image with BrushPattern.ORIGIN
local bi = Image(2, 2, brushColorMode)
bi:clear(0)
bi:putPixel(0, 0, colorInBrush)
bi:putPixel(1, 1, colorInBrush)
local b = Brush { image=bi,
center=Point(0, 0),
pattern=BrushPattern.ORIGIN,
patternOrigin=Point(0, 0) }
expect_img(app.activeImage,
{ 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0 })
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0) } }
expect_eq(cel.bounds, Rectangle(0, 0, 2, 2))
expect_img(app.activeImage,
{ c, 0,
0, c })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0), Point(1, 1) } }
expect_eq(cel.bounds, Rectangle(0, 0, 3, 3))
expect_img(app.activeImage,
{ c, 0, 0,
0, c, 0,
0, 0, c })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(0, 1) } }
expect_eq(cel.bounds, Rectangle(0, 1, 2, 2))
expect_img(app.activeImage,
{ 0, c,
c, 0 })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0), Point(2, 0),
Point(0, 0), Point(0, 1) } }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 3))
expect_img(app.activeImage,
{ c, 0, c, 0,
0, c, 0, c,
c, 0, 0, 0 })
app.undo()
app.useTool{ tool='paint_bucket', brush=b, points={ Point(0, 0) } }
expect_eq(cel.bounds, Rectangle(0, 0, 4, 4))
expect_img(app.activeImage,
{ c, 0, c, 0,
0, c, 0, c,
c, 0, c, 0,
0, c, 0, c })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
assert(app.activeImage ~= nil)
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
expect_img(app.activeImage,
{ 0, c,
c, 0 })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0),
Point(1, 0)} }
assert(app.activeImage ~= nil)
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
expect_img(app.activeImage,
{ 0, c,
c, 0 })
app.undo()
-- Change brush pattern to BrushPattern.TARGET
b = Brush { image=bi,
center=Point(0, 0),
pattern=BrushPattern.TARGET,
patternOrigin=Point(0, 0) }
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
expect_eq(cel.bounds, Rectangle(1, 0, 2, 2))
expect_img(app.activeImage,
{ c, 0,
0, c })
app.undo()
end
do
drawing_with_image_brushes(ColorMode.RGB, rgba(255, 0, 0),
ColorMode.RGB, rgba(255, 0, 0))
end
----------------------------------------------------------------------
-- draw with symmetry
----------------------------------------------------------------------
function drawing_with_symmetry(imageColorMode, colorInImage,
brushColorMode, colorInBrush, palette)
print("drawing_with_symmetry", imageColorMode, brushColorMode)
local s = Sprite(8, 3, imageColorMode)
local c = colorInImage
cel = s.cels[1]
if palette then
s:setPalette(palette)
end
-- Enable symmetry
local pref = app.preferences
local docPref = pref.document(s)
pref.symmetry_mode.enabled = true
docPref.symmetry.mode = 1 -- TODO use SymmetryMode.HORIZONTAL when it's available
docPref.symmetry.x_axis = 4
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
expect_img(cel.image,
{ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 })
local b = Brush { size=1 }
app.fgColor = c
app.useTool{ tool=pencil, brush=b, points={ Point(0, 0) } }
expect_eq(cel.bounds, Rectangle(0, 0, 8, 1))
expect_img(cel.image,
{ c, 0, 0, 0, 0, 0, 0, c })
app.undo()
app.useTool{ tool=pencil, brush=b, points={ Point(2, 0) } }
expect_eq(cel.bounds, Rectangle(2, 0, 4, 1))
expect_img(cel.image,
{ c, 0, 0, c })
app.undo()
-- Brush size 2x2 center=(1,1)
b = Brush { size=2 }
assert(b.center.x == 1)
assert(b.center.y == 1)
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
expect_eq(cel.bounds, Rectangle(0, 0, 8, 2))
expect_img(cel.image,
{ c, c, 0, 0, 0, 0, c, c,
c, c, 0, 0, 0, 0, c, c })
app.undo()
-- Brush size 2x2 center=(0,0)
b = Brush { size=2, center=Point(0, 0) }
assert(b.center.x == 0)
assert(b.center.y == 0)
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
expect_eq(cel.bounds, Rectangle(1, 0, 6, 2))
expect_img(cel.image,
{ c, c, 0, 0, c, c,
c, c, 0, 0, c, c })
app.undo()
-- Brush size 3x3
b = Brush { size=3 }
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
expect_img(cel.image,
{ 0, c, 0, 0, 0, 0, c, 0,
c, c, c, 0, 0, c, c, c,
0, c, 0, 0, 0, 0, c, 0 })
app.undo()
-- Brush size 3x3
b = Brush { size=3, center=Point(1, 1) }
app.useTool{ tool=pencil, brush=b, points={ Point(2, 1) } }
expect_eq(cel.bounds, Rectangle(1, 0, 6, 3))
expect_img(cel.image,
{ 0, c, 0, 0, c, 0,
c, c, c, c, c, c,
0, c, 0, 0, c, 0 })
app.undo()
-- Brush size 4x4 center=(2,2)
b = Brush { size=4 }
assert(b.center.x == 2)
assert(b.center.y == 2)
app.useTool{ tool=pencil, brush=b, points={ Point(1, 1) } }
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
expect_img(cel.image,
{ c, c, c, 0, 0, c, c, c,
c, c, c, 0, 0, c, c, c,
c, c, 0, 0, 0, 0, c, c })
app.undo()
-- Brush size 4x4 center=(1,1)
b = Brush { size=4, center=Point(1, 1) }
app.useTool{ tool=pencil, brush=b, points={ Point(1, 0) } }
expect_eq(cel.bounds, Rectangle(0, 0, 8, 3))
expect_img(cel.image,
{ c, c, c, c, c, c, c, c,
c, c, c, c, c, c, c, c,
0, c, c, 0, 0, c, c, 0 })
app.undo()
-- Odd symmetry
docPref.symmetry.x_axis = 4.5
b = Brush { size=1 }
app.useTool{ tool=pencil, brush=b, points={ Point(4, 0) } }
expect_eq(cel.bounds, Rectangle(4, 0, 1, 1))
expect_img(cel.image,
{ c })
app.undo()
b = Brush { size=1 }
app.useTool{ tool=pencil, brush=b, points={ Point(3, 0) } }
expect_eq(cel.bounds, Rectangle(3, 0, 3, 1))
expect_img(cel.image,
{ c, 0, c })
app.undo()
b = Brush { size=2 }
app.useTool{ tool=pencil, brush=b, points={ Point(2, 0) } }
expect_eq(cel.bounds, Rectangle(1, 0, 7, 1))
expect_img(cel.image,
{ c, c, 0, 0, 0, c, c })
app.undo()
end
do
drawing_with_symmetry(ColorMode.RGB, rgba(255, 0, 0),
ColorMode.RGB, rgba(255, 0, 0))
end
----------------------------------------------------------------------
-- useTool in a transaction
----------------------------------------------------------------------
do
local s = Sprite(2, 2)
local r = red.rgbaPixel
local y = yellow.rgbaPixel
app.fgColor = r
local cel = s.cels[1]
expect_img(cel.image, { 0, 0,
0, 0 })
app.transaction(
function()
app.useTool{ tool=pencil,
color=r, brush=Brush{ size=1 },
points={ Point(0, 0) } }
app.useTool{ tool=pencil,
color=y, brush=Brush{ size=1 },
points={ Point(1, 1) } }
end)
expect_img(cel.image, { r, 0,
0, y })
app.undo() -- Undo the whole transaction (two useTool grouped in one transaction)
expect_img(cel.image, { 0, 0,
0, 0 })
end
----------------------------------------------------------------------
-- draw with tiled mode + image brush
-- test for: https://community.aseprite.org/t/tile-mode-glitch/1183
----------------------------------------------------------------------
function drawing_with_tiled_mode_and_image_brush()
print("drawing_with_tiled_mode_and_image_brush")
local spr = Sprite(8, 3, ColorMode.INDEXED)
local cel = spr.cels[1]
-- enable tiled mode
local pref = app.preferences
local docPref = pref.document(spr)
docPref.tiled.mode = 3 -- both
expect_img(cel.image,
{ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 })
-- Create brush
local brushImg = Image(5, 2, ColorMode.INDEXED)
array_to_pixels({ 1, 2, 3, 2, 1,
0, 1, 2, 1, 0 }, brushImg)
local bru = Brush { image=brushImg }
-- Without overflow
app.useTool{ tool=pencil, brush=bru, points={ Point(2, 1) } }
expect_img(cel.image,
{ 1, 2, 3, 2, 1,
0, 1, 2, 1, 0 })
app.undo()
-- Overflow at the left-side
app.useTool{ tool=pencil, brush=bru, points={ Point(1, 1) } }
expect_img(cel.image,
{ 2, 3, 2, 1, 0, 0, 0, 1,
1, 2, 1, 0, 0, 0, 0, 0 })
app.undo()
-- Overflow at the right-side
app.useTool{ tool=pencil, brush=bru, points={ Point(9, 1) } }
expect_img(cel.image,
{ 2, 3, 2, 1, 0, 0, 0, 1,
1, 2, 1, 0, 0, 0, 0, 0 })
app.undo()
-- Overflow at the top
app.useTool{ tool=pencil, brush=bru, points={ Point(0, 0) } }
expect_img(cel.image,
{ 2, 1, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0,
3, 2, 1, 0, 0, 0, 1, 2 })
app.undo()
-- Overflow at the bottom
app.useTool{ tool=pencil, brush=bru, points={ Point(1, 3) } }
expect_img(cel.image,
{ 1, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
2, 3, 2, 1, 0, 0, 0, 1 })
app.undo()
docPref.tiled.mode = 0 -- none (disable tiled mode)
end
drawing_with_tiled_mode_and_image_brush()
----------------------------------------------------------------------
-- countour with pixel perfect
----------------------------------------------------------------------
do
local s = Sprite(3, 3, ColorMode.INDEXED)
local i = app.activeImage
i:clear(1)
expect_img(i,
{ 1, 1, 1,
1, 1, 1,
1, 1, 1 })
app.useTool{
tool='contour',
brush=Brush(1),
color=2,
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
points={ { 1, 1 }, { 2, 1 }, { 2, 2 }
}
}
expect_img(app.activeImage,
{ 1, 1, 1,
1, 2, 1,
1, 1, 2 })
app.undo()
-- Test one pixel when using one point
app.useTool{
tool='contour',
brush=Brush(1),
color=2,
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
points={ { 1, 1 } }
}
expect_img(app.activeImage,
{ 1, 1, 1,
1, 2, 1,
1, 1, 1 })
app.undo()
-- Test bug where one click doesn't draw with the contour tool with
-- pixel perfect algorith.
-- Report: https://community.aseprite.org/t/13149
expect_img(app.activeImage,
{ 1, 1, 1,
1, 1, 1,
1, 1, 1 })
app.useTool{
tool='contour',
brush=Brush(1),
color=2,
freehandAlgorithm=1, -- 1=FreehandAlgorithm.PIXEL_PERFECT
-- Two points in the same spot, this happens in the UI, one
-- created in mouse down, other in mouse up.
points={ { 1, 1 }, { 1, 1 } }
}
expect_img(app.activeImage,
{ 1, 1, 1,
1, 2, 1,
1, 1, 1 })
end

41
tests/scripts/version.lua Normal file
View File

@ -0,0 +1,41 @@
-- Copyright (C) 2019-2021 Igara Studio S.A.
-- Copyright (C) 2018 David Capello
--
-- This file is released under the terms of the MIT license.
-- Read LICENSE.txt for more information.
assert(string.sub(tostring(app.version), 1, 1) == "1")
assert(string.sub(tostring(app.version), 2, 2) == ".")
assert(app.version.major == 1)
-- We cannot test the specific app.version from the "main" branch
-- because it's "1.x-dev" (which is converted to "1.0-dev" as Version object)
--assert(app.version > Version("1.2.10-beta4"))
assert(Version("1") == Version("1"))
assert(Version("1.1") > Version("1"))
assert(Version("0.1") < Version("0.2"))
assert(Version("1.0.1") > Version("1"))
assert(Version("1.0.1") < Version("1.1"))
assert(Version("1.0.1") == Version("1.0.1"))
assert(Version("1.0.1") ~= Version("1.0.2"))
assert(Version("1.0.1") > Version("1.0.1-beta"))
assert(Version("1.0.1") > Version("1.0.1-dev"))
assert(Version("1.0.1-beta") > Version("1.0.1-alpha"))
assert(Version("1.0.1-beta50") < Version("1.0.1-beta100"))
assert(Version("1.0.1-beta50") <= Version("1.0.1-beta100"))
assert(Version("1.0.1-beta100") <= Version("1.0.1-beta100"))
local v = Version()
assert(v.major == 0)
assert(v.minor == 0)
assert(v.patch == 0)
assert(v.prereleaseLabel == "")
assert(v.prereleaseNumber == 0)
v = Version("1.2.10-beta4")
assert(v.major == 1)
assert(v.minor == 2)
assert(v.patch == 10)
assert(v.prereleaseLabel == "beta")
assert(v.prereleaseNumber == 4)

Binary file not shown.

Binary file not shown.

27
tests/sprites/README.md Normal file
View File

@ -0,0 +1,27 @@
# Files
* `abcd.aseprite`: Indexed, 32x32, four layers ("a", "b", "c", "d")
* `1empty3.aseprite`: RGB, 32x32, two layers ("fg", "bg"), 2nd frame
completelly empty, two tags ("a", "b")
* `groups2.aseprite`: Indexed, 8x8, two groups ("items", "player"),
two layers per group ("items/gun", "items/sword", "player/head",
"player/body"), with one layer hidden ("items/gun").
* `groups3abc.aseprite`: RGB, 9x11, three groups ("a", "b", "c"), with
three layers each one (called "a", "b", "c" too). There is a
combination of visibilities ("b/b", "c", "c/a", and "c/b" are
hidden).
* `bg-index-3.aseprite`: Indexed, 4x4, two layers ("fg" and "bg")
with a special transparent index color (= palette index 3).
* `tags3.aseprite`: 3 tags ("forward", "reverse", "pingpong") and 3
layers ("a", "b", "c"), 4x4, several linked cels + layer "c" with
empty cels.
* `point4frames.aseprite`: Indexed, 4 frames, 2 layers, same cel
content but different positions, can be used to test
`-merge-duplicates` to check if all cels go to the same sprite sheet
position.
* `point2frames.aseprite`: Indexed, 2 frames, 1 layer, same cel
content as in `point4frames.aseprite`. Useful to test if
`"sourceSize"` is different when two cels from different sprites are
merged in the same texture atlas.
* `2f-index-3x3.aseprite`: Indexed, 2 frames, 1 layer, mask color set
to index 21.

BIN
tests/sprites/abcd.aseprite Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tests/sprites/link.aseprite Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
tests/third_party/json vendored Submodule

@ -0,0 +1 @@
Subproject commit dbf4b2dd2eb7c23be2773c89eb059dadd6436f94