From d1a7c4225df97e21ae38871d9b6e593ab2f002d8 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 5 Oct 2019 23:44:28 +0200
Subject: [PATCH] - added a texture class for ART-format hightiles.

This allows to treat them like all other image formats.
---
 source/CMakeLists.txt                         |   1 +
 source/build/include/build.h                  |   1 -
 source/build/src/defs.cpp                     |  57 +------
 source/build/src/tiles.cpp                    |  25 ---
 source/common/textures/formats/arttexture.cpp | 146 ++++++++++++++++++
 source/common/textures/image.cpp              |   3 +-
 6 files changed, 157 insertions(+), 76 deletions(-)
 create mode 100644 source/common/textures/formats/arttexture.cpp

diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 5277f6fb2..f63ce05f9 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -982,6 +982,7 @@ set (PCH_SOURCES
 	common/textures/formats/pcxtexture.cpp
 	common/textures/formats/pngtexture.cpp
 	common/textures/formats/tgatexture.cpp
+	common/textures/formats/arttexture.cpp
 	
 )
 
diff --git a/source/build/include/build.h b/source/build/include/build.h
index 3a60775c7..f02cb6edf 100644
--- a/source/build/include/build.h
+++ b/source/build/include/build.h
@@ -1086,7 +1086,6 @@ void    artSetupMapArt(const char *filename);
 bool    tileLoad(int16_t tilenume);
 void    tileLoadData(int16_t tilenume, int32_t dasiz, char *buffer);
 int32_t tileCRC(int16_t tileNum);
-void    artConvertRGB(palette_t *pic, uint8_t const *buf, int32_t bufsizx, int32_t sizx, int32_t sizy);
 void    tileUpdatePicSiz(int32_t picnum);
 
 int32_t   qloadkvx(int32_t voxindex, const char *filename);
diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp
index f3b90864b..59297c7aa 100644
--- a/source/build/src/defs.cpp
+++ b/source/build/src/defs.cpp
@@ -17,6 +17,7 @@
 #include "mdsprite.h"  // md3model_t
 #include "colmatch.h"
 #include "textures.h"
+#include "bitmap.h"
 
 #ifdef USE_OPENGL
 # include "hightile.h"
@@ -252,52 +253,9 @@ static int32_t Defs_ImportTileFromTexture(char const * const fn, int32_t const t
     if (check_file_exist(fn))
         return -1;
 
-    int32_t xsiz = 0, ysiz = 0;
-    palette_t *picptr = NULL;
 
 	FTexture* tex = FTexture::GetTexture(fn);
-
-	// This should be implemented as a separate texture type to avoid maintenance problems elsewhere.
-    if (!tex)
-    {
-		auto fr = kopenFileReader(fn, 0);
-		auto data = fr.Read();
-        int32_t const artstatus = artCheckUnitFileHeader(data.Data(), data.Size());
-        if (artstatus < 0)
-            return artstatus<<8;
-
-        int32_t picanmdisk;
-        Bmemcpy(&picanmdisk, &kpzbuf[20], sizeof(int32_t));
-        picanmdisk = B_LITTLE32(picanmdisk);
-        tileConvertAnimFormat(tile, picanmdisk);
-
-        int32_t const xsiz = B_LITTLE16(B_UNBUF16(&kpzbuf[16]));
-        int32_t const ysiz = B_LITTLE16(B_UNBUF16(&kpzbuf[18]));
-
-        if (EDUKE32_PREDICT_FALSE(xsiz <= 0 || ysiz <= 0))
-        {
-            tileDelete(tile);
-            return 2;
-        }
-
-        tileSetSize(tile, xsiz, ysiz);
-        int32_t const dasiz = xsiz * ysiz;
-
-        if (EDUKE32_PREDICT_FALSE(ARTv1_UNITOFFSET + dasiz > (int)data.Size()))
-        {
-            tileSetupDummy(tile);
-            return 3;
-        }
-
-        tileSetData(tile, dasiz, &kpzbuf[ARTv1_UNITOFFSET]);
-
-#ifdef USE_OPENGL
-        if (istexture)
-            hicsetsubsttex(tile, 0, fn, (float)(255-alphacut) * (1.f/255.f), 1.0f, 1.0f, 1.0f, 1.0f, HICR_ARTIMMUNITY);
-#endif
-
-        return 1;
-    }
+	int32_t xsiz = tex->GetWidth(), ysiz = tex->GetHeight();
 
     if (EDUKE32_PREDICT_FALSE(xsiz <= 0 || ysiz <= 0))
         return -2;
@@ -305,11 +263,12 @@ static int32_t Defs_ImportTileFromTexture(char const * const fn, int32_t const t
     if (!(paletteloaded & PALETTE_MAIN))
         return -3;
 
-    tileSetSize(tile, tex->GetWidth(), tex->GetHeight());
-
-    tile_from_truecolpic(tile, picptr, alphacut);
-
-    Xfree(picptr);
+	if (videoGetRenderMode() < REND_POLYMOST)
+	{
+		tileSetSize(tile, tex->GetWidth(), tex->GetHeight());
+		auto image = tex->GetBgraBitmap(nullptr, nullptr);
+		tile_from_truecolpic(tile, (const palette_t*)image.GetPixels(), alphacut);
+	}
 
 #ifdef USE_OPENGL
     if (istexture)
diff --git a/source/build/src/tiles.cpp b/source/build/src/tiles.cpp
index 10f4b0f22..f71b8cce4 100644
--- a/source/build/src/tiles.cpp
+++ b/source/build/src/tiles.cpp
@@ -796,31 +796,6 @@ int32_t tileCRC(int16_t tileNum)
     return crc;
 }
 
-// Assumes pic has been initialized to zero.
-void artConvertRGB(palette_t * const pic, uint8_t const * const buf, int32_t const bufsizx, int32_t const sizx, int32_t const sizy)
-{
-    for (bssize_t y = 0; y < sizy; ++y)
-    {
-        palette_t * const picrow = &pic[bufsizx * y];
-
-        for (bssize_t x = 0; x < sizx; ++x)
-        {
-            uint8_t index = buf[sizy * x + y];
-
-            if (index == 255)
-                continue;
-
-            index *= 3;
-
-            // pic is BGRA
-            picrow[x].r = palette[index+2];
-            picrow[x].g = palette[index+1];
-            picrow[x].b = palette[index];
-            picrow[x].f = 255;
-        }
-    }
-}
-
 //
 // allocatepermanenttile
 //
diff --git a/source/common/textures/formats/arttexture.cpp b/source/common/textures/formats/arttexture.cpp
new file mode 100644
index 000000000..0092b32b2
--- /dev/null
+++ b/source/common/textures/formats/arttexture.cpp
@@ -0,0 +1,146 @@
+/*
+** arttexture.cpp
+** Texture class for ART-based hightiles
+**
+**---------------------------------------------------------------------------
+** Copyright 2019 Christoph Oelckers
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** 1. Redistributions of source code must retain the above copyright
+**    notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+**    notice, this list of conditions and the following disclaimer in the
+**    documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+**    derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**---------------------------------------------------------------------------
+**
+**
+*/
+
+#include "files.h"
+#include "templates.h"
+#include "bitmap.h"
+#include "image.h"
+#include "cache1d.h"
+#include "build.h"
+
+
+//==========================================================================
+//
+// an AET texture
+//
+//==========================================================================
+
+class FArtTexture : public FImageSource
+{
+
+public:
+	FArtTexture (int width, int height, int p);
+	int CopyPixels(FBitmap *bmp, int conversion) override;
+	int32_t picanmdisk;	// Todo: Get this out again on the other side.
+};
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+FImageSource *ArtImage_TryCreate(FileReader & file)
+{
+	auto buffer = file.Read();
+	int32_t const artstatus = artCheckUnitFileHeader(buffer.Data(), buffer.Size());
+	if (artstatus < 0) return nullptr;
+
+	int32_t picanmdisk;
+	memcpy(&picanmdisk, &buffer[20], sizeof(int32_t));
+	picanmdisk = B_LITTLE32(picanmdisk);
+	//tileConvertAnimFormat(tile, picanmdisk);
+
+	int Width = B_LITTLE16(B_UNBUF16(&buffer[16]));
+	int Height = B_LITTLE16(B_UNBUF16(&buffer[18]));
+
+	if (Width <= 0 || Height <= 0)
+	{
+		return nullptr;
+	}
+
+	int32_t NumPixels = Width * Height;
+
+	if (ARTv1_UNITOFFSET + NumPixels > (int)buffer.Size())
+	{
+		return nullptr;
+	}
+	
+	return new FArtTexture(Width, Height, picanmdisk);
+}
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+FArtTexture::FArtTexture(int width, int height, int p)
+{
+	Width = width;
+	Height = height;
+	picanmdisk = p;
+}
+
+//===========================================================================
+//
+// FArtTexture::CopyPixels
+//
+// This format is special because it ignores the game palettes and
+// only outputs a true color image with the primary palette.
+//
+//===========================================================================
+
+int FArtTexture::CopyPixels(FBitmap *bmp, int conversion)
+{
+	// Treat both buffer as linear contiguous blocks.
+	// Both Src and Dst are ordered the same with no padding.
+	int numpixels = Width * Height;
+	bool hasalpha = false;
+	FileReader fr = kopenFileReader(Name, 0);
+	if (!fr.isOpen()) return 0;
+	TArray<uint8_t> source(numpixels, true);
+	fr.Read(source.Data(), numpixels);
+	auto dest = bmp->GetPixels();
+	
+    for (int y = 0; y < numpixels; ++y)
+    {
+		int index = source[y];
+        if (index == 255)
+		{
+			hasalpha = true;
+            continue;
+		}
+		
+		dest[0] = palette[index];
+		dest[1] = palette[index+1];
+		dest[2] = palette[index+2];
+		dest[3] = 255;
+		dest += 4;
+    }
+	bMasked = hasalpha;
+	return 0;
+}	 
+
diff --git a/source/common/textures/image.cpp b/source/common/textures/image.cpp
index 6ea28820c..a13d3837c 100644
--- a/source/common/textures/image.cpp
+++ b/source/common/textures/image.cpp
@@ -99,6 +99,7 @@ FImageSource *JPEGImage_TryCreate(FileReader &);
 FImageSource *DDSImage_TryCreate(FileReader &);
 FImageSource *PCXImage_TryCreate(FileReader &);
 FImageSource *TGAImage_TryCreate(FileReader &);
+FImageSource *ArtImage_TryCreate(FileReader &);
 
 
 // Examines the lump contents to decide what type of texture to create,
@@ -110,7 +111,7 @@ FImageSource * FImageSource::GetImage(const char *name)
 		{ JPEGImage_TryCreate },
 		{ DDSImage_TryCreate },
 		{ PCXImage_TryCreate },
-		{ TGAImage_TryCreate },
+		{ ArtImage_TryCreate },
 		{ nullptr }
 	};