From 009f1f8585c17ac27087bf96fed27db580bcfdc4 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Tue, 10 Jan 2017 01:24:55 +0300
Subject: Add mock object for Graphics class.

Add tests for MapLayer::draw.
---
 src/Makefile.am                        |   3 +
 src/enums/render/mockdrawtype.h        |  35 +++
 src/render/mockdrawitem.h              |  56 ++++
 src/render/mockgraphics.cc             | 311 +++++++++++++++++++
 src/render/mockgraphics.h              |  54 ++++
 src/resources/map/maplayer_unittest.cc | 552 +++++++++++++++++++++++++++++++++
 6 files changed, 1011 insertions(+)
 create mode 100644 src/enums/render/mockdrawtype.h
 create mode 100644 src/render/mockdrawitem.h
 create mode 100644 src/render/mockgraphics.cc
 create mode 100644 src/render/mockgraphics.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 92a47e25f..581b145f6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1871,6 +1871,8 @@ manaplustests_CXXFLAGS += -DUSE_X11
 endif
 
 manaplustests_SOURCES = ${manaplus_SOURCES} \
+	      render/mockgraphics.cc \
+	      render/mockgraphics.h \
 	      enums/enums_unittest.cc \
 	      utils/checkutils_unittest.cc \
 	      utils/xml_unittest.cc \
@@ -1895,6 +1897,7 @@ manaplustests_SOURCES = ${manaplus_SOURCES} \
 	      gui/windowmanager_unittest.cc
 endif
 
+
 EXTRA_DIST = CMakeLists.txt \
 	     winver.h.in \
 	     manaplus.rc \
diff --git a/src/enums/render/mockdrawtype.h b/src/enums/render/mockdrawtype.h
new file mode 100644
index 000000000..7477684d0
--- /dev/null
+++ b/src/enums/render/mockdrawtype.h
@@ -0,0 +1,35 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ENUMS_RENDER_MOCKDRAWTYPE_H
+#define ENUMS_RENDER_MOCKDRAWTYPE_H
+#ifdef UNITTESTS
+
+#include "enums/simpletypes/enumdefines.h"
+
+enumStart(MockDrawType)
+{
+    DrawImage   = 0,
+    DrawPattern = 1
+}
+enumEnd(MockDrawType);
+
+#endif  // UNITTESTS
+#endif  // ENUMS_RENDER_MOCKDRAWTYPE_H
diff --git a/src/render/mockdrawitem.h b/src/render/mockdrawitem.h
new file mode 100644
index 000000000..94198329a
--- /dev/null
+++ b/src/render/mockdrawitem.h
@@ -0,0 +1,56 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RENDER_MOCKDRAWITEM_H
+#define RENDER_MOCKDRAWITEM_H
+
+#ifdef UNITTESTS
+
+#include "enums/render/mockdrawtype.h"
+
+#include "localconsts.h"
+
+struct MockDrawItem final
+{
+    MockDrawItem(const MockDrawTypeT type,
+                 const Image *const image0,
+                 const int x0,
+                 const int y0,
+                 const int width0,
+                 const int height0) :
+        image(image0),
+        drawType(type),
+        x(x0),
+        y(y0),
+        width(width0),
+        height(height0)
+    {
+    }
+
+    const Image *image;
+    MockDrawTypeT drawType;
+    int x;
+    int y;
+    int width;
+    int height;
+};
+
+#endif  // UNITTESTS
+#endif  // RENDER_MOCKDRAWITEM_H
diff --git a/src/render/mockgraphics.cc b/src/render/mockgraphics.cc
new file mode 100644
index 000000000..273e1f354
--- /dev/null
+++ b/src/render/mockgraphics.cc
@@ -0,0 +1,311 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2004-2009  The Mana World Development Team
+ *  Copyright (C) 2009-2010  The Mana Developers
+ *  Copyright (C) 2011-2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "render/mockgraphics.h"
+
+#include "graphicsmanager.h"
+
+#include "utils/sdlcheckutils.h"
+
+#include "utils/sdlpixel.h"
+
+#include "render/vertexes/imagecollection.h"
+
+#include "resources/imagerect.h"
+
+#include "resources/image/image.h"
+
+#include "debug.h"
+
+#ifndef SDL_BIG_ENDIAN
+#error missing SDL_endian.h
+#endif  // SDL_BYTEORDER
+
+MockGraphics::MockGraphics() :
+    Graphics()
+{
+    mOpenGL = RENDER_SOFTWARE;
+    mName = "Software";
+}
+
+MockGraphics::~MockGraphics()
+{
+}
+
+void MockGraphics::drawRescaledImage(const Image *restrict const image
+                                     A_UNUSED,
+                                     int dstX A_UNUSED,
+                                     int dstY A_UNUSED,
+                                     const int desiredWidth A_UNUSED,
+                                     const int desiredHeight A_UNUSED)
+                                     restrict2
+{
+}
+
+void MockGraphics::drawImage(const Image *restrict const image,
+                             int dstX,
+                             int dstY) restrict2
+{
+    mDraws.push_back(MockDrawItem(MockDrawType::DrawImage,
+        image,
+        dstX,
+        dstY,
+        0,
+        0));
+}
+
+void MockGraphics::drawImageInline(const Image *restrict const image A_UNUSED,
+                                   int dstX A_UNUSED,
+                                   int dstY A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::copyImage(const Image *restrict const image A_UNUSED,
+                             int dstX A_UNUSED,
+                             int dstY A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawImageCached(const Image *restrict const image A_UNUSED,
+                                   int x A_UNUSED,
+                                   int y A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawPatternCached(const Image *restrict const image
+                                     A_UNUSED,
+                                     const int x A_UNUSED,
+                                     const int y A_UNUSED,
+                                     const int w A_UNUSED,
+                                     const int h A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::completeCache() restrict2
+{
+}
+
+void MockGraphics::drawPattern(const Image *restrict const image,
+                               const int x,
+                               const int y,
+                               const int w,
+                               const int h) restrict2
+{
+    mDraws.push_back(MockDrawItem(MockDrawType::DrawPattern,
+        image,
+        x,
+        y,
+        w,
+        h));
+}
+
+void MockGraphics::drawPatternInline(const Image *restrict const image
+                                     A_UNUSED,
+                                     const int x A_UNUSED,
+                                     const int y A_UNUSED,
+                                     const int w A_UNUSED,
+                                     const int h A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawRescaledPattern(const Image *restrict const image
+                                       A_UNUSED,
+                                       const int x A_UNUSED,
+                                       const int y A_UNUSED,
+                                       const int w A_UNUSED,
+                                       const int h A_UNUSED,
+                                       const int scaledWidth A_UNUSED,
+                                       const int scaledHeight A_UNUSED)
+                                       restrict2
+{
+}
+
+void MockGraphics::calcPattern(ImageVertexes *restrict const vert A_UNUSED,
+                               const Image *restrict const image A_UNUSED,
+                               const int x A_UNUSED,
+                               const int y A_UNUSED,
+                               const int w A_UNUSED,
+                               const int h A_UNUSED) const restrict2
+{
+}
+
+void MockGraphics::calcPatternInline(ImageVertexes *restrict const vert
+                                     A_UNUSED,
+                                     const Image *restrict const image
+                                     A_UNUSED,
+                                     const int x A_UNUSED,
+                                     const int y A_UNUSED,
+                                     const int w A_UNUSED,
+                                     const int h A_UNUSED) const restrict2
+{
+}
+
+void MockGraphics::calcPattern(ImageCollection *restrict const vertCol
+                               A_UNUSED,
+                               const Image *restrict const image A_UNUSED,
+                               const int x A_UNUSED,
+                               const int y A_UNUSED,
+                               const int w A_UNUSED,
+                               const int h A_UNUSED) const restrict2
+{
+}
+
+void MockGraphics::calcTileVertexes(ImageVertexes *restrict const vert,
+                                   const Image *restrict const image,
+                                   int x, int y) const restrict2
+{
+    vert->image = image;
+    calcTileSDL(vert, x, y);
+}
+
+void MockGraphics::calcTileVertexesInline(ImageVertexes *restrict const vert
+                                          A_UNUSED,
+                                          const Image *restrict const image
+                                          A_UNUSED,
+                                          int x A_UNUSED,
+                                          int y A_UNUSED) const restrict2
+{
+}
+
+void MockGraphics::calcTileSDL(ImageVertexes *restrict const vert A_UNUSED,
+                               int x A_UNUSED,
+                               int y A_UNUSED) const restrict2
+{
+}
+
+void MockGraphics::calcTileCollection(ImageCollection *restrict const vertCol
+                                      A_UNUSED,
+                                      const Image *restrict const image
+                                      A_UNUSED,
+                                      int x A_UNUSED,
+                                      int y A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawTileCollection(const ImageCollection *restrict const
+                                      vertCol A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawTileVertexes(const ImageVertexes *restrict const
+                                    vert A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::updateScreen() restrict2
+{
+}
+
+void MockGraphics::calcWindow(ImageCollection *restrict const vertCol A_UNUSED,
+                              const int x A_UNUSED,
+                              const int y A_UNUSED,
+                              const int w A_UNUSED,
+                              const int h A_UNUSED,
+                              const ImageRect &restrict imgRect A_UNUSED)
+                              restrict2
+{
+}
+
+void MockGraphics::fillRectangle(const Rect &restrict rectangle A_UNUSED)
+                                 restrict2
+{
+}
+
+void MockGraphics::beginDraw() restrict2
+{
+    pushClipArea(Rect(0, 0, mRect.w, mRect.h));
+}
+
+void MockGraphics::endDraw() restrict2
+{
+    popClipArea();
+}
+
+void MockGraphics::pushClipArea(const Rect &restrict area) restrict2
+{
+    Graphics::pushClipArea(area);
+}
+
+void MockGraphics::popClipArea() restrict2
+{
+    Graphics::popClipArea();
+}
+
+void MockGraphics::drawPoint(int x A_UNUSED,
+                             int y A_UNUSED) restrict2
+{
+}
+
+void MockGraphics::drawRectangle(const Rect &restrict rectangle A_UNUSED)
+                                 restrict2
+{
+}
+
+void MockGraphics::drawLine(int x1 A_UNUSED,
+                            int y1 A_UNUSED,
+                            int x2 A_UNUSED,
+                            int y2 A_UNUSED) restrict2
+{
+}
+
+bool MockGraphics::setVideoMode(const int w, const int h,
+                               const int scale,
+                               const int bpp,
+                               const bool fs,
+                               const bool hwaccel,
+                               const bool resize,
+                               const bool noFrame) restrict2
+{
+    setMainFlags(w, h, scale, bpp, fs, hwaccel, resize, noFrame);
+
+    if (!(mWindow = graphicsManager.createWindow(w, h, bpp,
+        getSoftwareFlags())))
+    {
+        mRect.w = 0;
+        mRect.h = 0;
+        return false;
+    }
+
+    mRect.w = CAST_U16(mWindow->w);
+    mRect.h = CAST_U16(mWindow->h);
+
+    return videoInfo();
+}
+
+void MockGraphics::drawImageRect(const int x A_UNUSED,
+                                 const int y A_UNUSED,
+                                 const int w A_UNUSED,
+                                 const int h A_UNUSED,
+                                 const ImageRect &restrict imgRect A_UNUSED)
+                                 restrict2
+{
+}
+
+void MockGraphics::calcImageRect(ImageVertexes *restrict const vert A_UNUSED,
+                                 const int x A_UNUSED,
+                                 const int y A_UNUSED,
+                                 const int w A_UNUSED,
+                                 const int h A_UNUSED,
+                                 const ImageRect &restrict imgRect A_UNUSED)
+                                 restrict2
+{
+}
diff --git a/src/render/mockgraphics.h b/src/render/mockgraphics.h
new file mode 100644
index 000000000..3d38f4a51
--- /dev/null
+++ b/src/render/mockgraphics.h
@@ -0,0 +1,54 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2004-2009  The Mana World Development Team
+ *  Copyright (C) 2009-2010  The Mana Developers
+ *  Copyright (C) 2011-2017  The ManaPlus Developers
+ *
+ *  This file is part of The ManaPlus Client.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RENDER_MOCKGRAPHICS_H
+#define RENDER_MOCKGRAPHICS_H
+
+#ifdef UNITTESTS
+
+#include "render/graphics.h"
+#include "render/mockdrawitem.h"
+
+#include "localconsts.h"
+
+#include <vector>
+
+class MockGraphics final : public Graphics
+{
+    public:
+        MockGraphics();
+
+        A_DELETE_COPY(MockGraphics)
+
+        ~MockGraphics();
+
+        #include "render/graphicsdef.hpp"
+        RENDER_GRAPHICSDEF_HPP
+
+        #include "render/softwaregraphicsdef.hpp"
+        RENDER_SOFTWAREGRAPHICSDEF_HPP
+
+        std::vector<MockDrawItem> mDraws;
+};
+
+#endif  // UNITTESTS
+#endif  // RENDER_MOCKGRAPHICS_H
diff --git a/src/resources/map/maplayer_unittest.cc b/src/resources/map/maplayer_unittest.cc
index 2cfe7a0f5..4ad264543 100644
--- a/src/resources/map/maplayer_unittest.cc
+++ b/src/resources/map/maplayer_unittest.cc
@@ -22,6 +22,8 @@
 
 #include "enums/resources/map/blockmask.h"
 
+#include "render/mockgraphics.h"
+
 #include "resources/image/image.h"
 
 #include "resources/map/map.h"
@@ -1078,3 +1080,553 @@ TEST_CASE("MapLayer updateConditionTiles")
     delete map;
     delete img1;
 }
+
+TEST_CASE("MapLayer draw")
+{
+    Image *const img1 = new Image(32, 32);
+    Image *const img2 = new Image(32, 32);
+    Image *const img3 = new Image(32, 32);
+    Map *map = nullptr;
+    MapLayer *layer = nullptr;
+    MockGraphics *const mock = new MockGraphics;
+
+    SECTION("simple 1")
+    {
+        map = new Map("map",
+            1, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            1, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(1, 1);
+
+        layer->draw(mock,
+            0, 0,
+            1, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            1, 1,
+            10, 5);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == -10);
+        REQUIRE(mock->mDraws[0].y == -5);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            1, 1,
+            -10, -5);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == 5);
+        REQUIRE(mock->mDraws[0].image == img1);
+    }
+
+    SECTION("simple 2")
+    {
+        map = new Map("map",
+            2, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            2, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(2, 1);
+
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            0, 0);
+
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            10, 5);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == -10);
+        REQUIRE(mock->mDraws[0].y == -5);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            -10, -5);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == 5);
+        REQUIRE(mock->mDraws[0].image == img1);
+    }
+
+    SECTION("simple 3")
+    {
+        map = new Map("map",
+            2, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            2, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(1, 0, img2);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(2, 1);
+
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 32);
+        REQUIRE(mock->mDraws[1].y == 0);
+        REQUIRE(mock->mDraws[1].image == img2);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            -10, -20);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == 20);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 42);
+        REQUIRE(mock->mDraws[1].y == 20);
+        REQUIRE(mock->mDraws[1].image == img2);
+    }
+
+    SECTION("simple 4")
+    {
+        map = new Map("map",
+            2, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            2, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(1, 0, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(2, 1);
+
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            2, 1,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == -20);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+    }
+
+    SECTION("simple 4.2")
+    {
+        map = new Map("map",
+            3, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            3, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(2, 0, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(3, 1);
+
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 64);
+        REQUIRE(mock->mDraws[1].y == 0);
+        REQUIRE(mock->mDraws[1].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            10, -20);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == -10);
+        REQUIRE(mock->mDraws[0].y == 20);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 54);
+        REQUIRE(mock->mDraws[1].y == 20);
+        REQUIRE(mock->mDraws[1].image == img1);
+    }
+
+    SECTION("simple 5")
+    {
+        map = new Map("map",
+            3, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            3, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(1, 0, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(3, 1);
+
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == -20);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+    }
+
+    SECTION("simple 6")
+    {
+        map = new Map("map",
+            3, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            3, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(1, 0, img1);
+        layer->setTile(2, 0, img2);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(3, 1);
+
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 0);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 64);
+        REQUIRE(mock->mDraws[1].y == 0);
+        REQUIRE(mock->mDraws[1].image == img2);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 10);
+        REQUIRE(mock->mDraws[0].y == -20);
+        REQUIRE(mock->mDraws[0].width == 64);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 74);
+        REQUIRE(mock->mDraws[1].y == -20);
+        REQUIRE(mock->mDraws[1].image == img2);
+    }
+
+    SECTION("simple 7")
+    {
+        map = new Map("map",
+            3, 1,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            3, 1,
+            false,
+            0,
+            0);
+        layer->setTile(0, 0, img1);
+        layer->setTile(1, 0, img1);
+        layer->setTile(2, 0, img2);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        tiles[0].isEnabled = false;
+        layer->updateCache(3, 1);
+
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 32);
+        REQUIRE(mock->mDraws[0].y == 0);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 64);
+        REQUIRE(mock->mDraws[1].y == 0);
+        REQUIRE(mock->mDraws[1].image == img2);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            3, 1,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 2);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 42);
+        REQUIRE(mock->mDraws[0].y == -20);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 74);
+        REQUIRE(mock->mDraws[1].y == -20);
+        REQUIRE(mock->mDraws[1].image == img2);
+    }
+
+    SECTION("normal 1")
+    {
+        const int maxX = 100;
+        const int maxY = 100;
+        map = new Map("map",
+            maxX, maxY,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            maxX, maxY,
+            false,
+            0,
+            0);
+        layer->setTile(1, 10, img1);
+        layer->setTile(2, 10, img1);
+        layer->setTile(3, 10, img1);
+        layer->setTile(4, 10, img2);
+        layer->setTile(5, 10, nullptr);
+        layer->setTile(6, 10, img2);
+        layer->setTile(7, 10, nullptr);
+        layer->setTile(8, 10, nullptr);
+        layer->setTile(9, 10, img2);
+        layer->setTile(10, 10, img2);
+        layer->setTile(11, 10, img3);
+        layer->setTile(12, 10, nullptr);
+        layer->setTile(13, 10, nullptr);
+        layer->setTile(14, 10, nullptr);
+        layer->setTile(15, 10, img1);
+        layer->setTile(16, 10, img1);
+        layer->setTile(17, 10, img1);
+        map->addLayer(layer);
+        TileInfo *const tiles = layer->getTiles();
+        layer->updateCache(maxX, maxY);
+
+        layer->draw(mock,
+            0, 0,
+            maxX, maxY,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 6);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 32 * 1);
+        REQUIRE(mock->mDraws[0].y == 32 * 10);
+        REQUIRE(mock->mDraws[0].width == 96);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 32 * 4);
+        REQUIRE(mock->mDraws[1].y == 32 * 10);
+        REQUIRE(mock->mDraws[1].image == img2);
+        REQUIRE(mock->mDraws[2].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[2].x == 32 * 6);
+        REQUIRE(mock->mDraws[2].y == 32 * 10);
+        REQUIRE(mock->mDraws[2].image == img2);
+        REQUIRE(mock->mDraws[3].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[3].x == 32 * 9);
+        REQUIRE(mock->mDraws[3].y == 32 * 10);
+        REQUIRE(mock->mDraws[3].width == 64);
+        REQUIRE(mock->mDraws[3].height == 32);
+        REQUIRE(mock->mDraws[3].image == img2);
+        REQUIRE(mock->mDraws[4].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[4].x == 32 * 11);
+        REQUIRE(mock->mDraws[4].y == 32 * 10);
+        REQUIRE(mock->mDraws[4].image == img3);
+        REQUIRE(mock->mDraws[5].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[5].x == 32 * 15);
+        REQUIRE(mock->mDraws[5].y == 32 * 10);
+        REQUIRE(mock->mDraws[5].width == 96);
+        REQUIRE(mock->mDraws[5].height == 32);
+        REQUIRE(mock->mDraws[5].image == img1);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            maxX, maxY,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 6);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[0].x == 32 * 1 + 10);
+        REQUIRE(mock->mDraws[0].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[0].width == 96);
+        REQUIRE(mock->mDraws[0].height == 32);
+        REQUIRE(mock->mDraws[0].image == img1);
+        REQUIRE(mock->mDraws[1].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[1].x == 32 * 4 + 10);
+        REQUIRE(mock->mDraws[1].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[1].image == img2);
+        REQUIRE(mock->mDraws[2].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[2].x == 32 * 6 + 10);
+        REQUIRE(mock->mDraws[2].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[2].image == img2);
+        REQUIRE(mock->mDraws[3].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[3].x == 32 * 9 + 10);
+        REQUIRE(mock->mDraws[3].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[3].width == 64);
+        REQUIRE(mock->mDraws[3].height == 32);
+        REQUIRE(mock->mDraws[3].image == img2);
+        REQUIRE(mock->mDraws[4].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[4].x == 32 * 11 + 10);
+        REQUIRE(mock->mDraws[4].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[4].image == img3);
+        REQUIRE(mock->mDraws[5].drawType == MockDrawType::DrawPattern);
+        REQUIRE(mock->mDraws[5].x == 32 * 15 + 10);
+        REQUIRE(mock->mDraws[5].y == 32 * 10 - 20);
+        REQUIRE(mock->mDraws[5].width == 96);
+        REQUIRE(mock->mDraws[5].height == 32);
+        REQUIRE(mock->mDraws[5].image == img1);
+    }
+
+    SECTION("normal2")
+    {
+        const int maxX = 100;
+        const int maxY = 100;
+        map = new Map("map",
+            maxX, maxY,
+            32, 32);
+        layer = new MapLayer("test",
+            0, 0,
+            maxX, maxY,
+            false,
+            0,
+            0);
+        TileInfo *const tiles = layer->getTiles();
+        map->addLayer(layer);
+        for (int x = 0; x < maxX; x ++)
+        {
+            for (int y = 0; y < maxY; y ++)
+            {
+                layer->setTile(x, y, img1);
+                tiles[y * maxX + x].isEnabled = false;
+            }
+        }
+        tiles[10 * maxX + 41].isEnabled = true;
+        layer->updateCache(maxX, maxY);
+
+        layer->draw(mock,
+            0, 0,
+            maxX, maxY,
+            0, 0);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 32 * 41);
+        REQUIRE(mock->mDraws[0].y == 32 * 10);
+
+        mock->mDraws.clear();
+        layer->draw(mock,
+            0, 0,
+            maxX, maxY,
+            -10, 20);
+        REQUIRE(mock->mDraws.size() == 1);
+        REQUIRE(mock->mDraws[0].drawType == MockDrawType::DrawImage);
+        REQUIRE(mock->mDraws[0].x == 32 * 41 + 10);
+        REQUIRE(mock->mDraws[0].y == 32 * 10 - 20);
+    }
+
+    delete map;
+    delete img1;
+    delete img2;
+    delete img3;
+    delete mock;
+}
-- 
cgit v1.2.3-70-g09d2