summaryrefslogtreecommitdiffstats
path: root/tools/depends/native/TexturePacker
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/depends/native/TexturePacker/CMakeLists.txt54
-rw-r--r--tools/depends/native/TexturePacker/Makefile62
-rw-r--r--tools/depends/native/TexturePacker/src/DecoderManager.cpp88
-rw-r--r--tools/depends/native/TexturePacker/src/DecoderManager.h37
-rw-r--r--tools/depends/native/TexturePacker/src/Makefile.am29
-rw-r--r--tools/depends/native/TexturePacker/src/SimpleFS.h107
-rw-r--r--tools/depends/native/TexturePacker/src/TexturePacker.cpp420
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln22
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj144
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters101
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/dirent.c145
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/dirent.h53
-rw-r--r--tools/depends/native/TexturePacker/src/Win32/version.rcbin0 -> 5582 bytes
-rw-r--r--tools/depends/native/TexturePacker/src/XBTFWriter.cpp164
-rw-r--r--tools/depends/native/TexturePacker/src/XBTFWriter.h48
-rwxr-xr-xtools/depends/native/TexturePacker/src/autogen.sh3
-rw-r--r--tools/depends/native/TexturePacker/src/cmdlineargs.h148
-rw-r--r--tools/depends/native/TexturePacker/src/configure.ac41
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp79
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp493
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/GifHelper.h220
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/IDecoder.h99
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp137
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp244
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h36
-rw-r--r--tools/depends/native/TexturePacker/src/md5.cpp231
-rw-r--r--tools/depends/native/TexturePacker/src/md5.h38
29 files changed, 3315 insertions, 0 deletions
diff --git a/tools/depends/native/TexturePacker/CMakeLists.txt b/tools/depends/native/TexturePacker/CMakeLists.txt
new file mode 100644
index 0000000..97dc1d3
--- /dev/null
+++ b/tools/depends/native/TexturePacker/CMakeLists.txt
@@ -0,0 +1,54 @@
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
+
+if(APPLE)
+ set(CMAKE_FIND_ROOT_PATH ${NATIVEPREFIX})
+endif()
+
+find_package(Lzo2 REQUIRED)
+find_package(PNG REQUIRED)
+find_package(GIF REQUIRED)
+find_package(JPEG REQUIRED)
+
+if(GIF_VERSION LESS 4)
+ message(FATAL_ERROR "giflib < 4 not supported")
+else()
+ file(STRINGS ${GIF_INCLUDE_DIR}/gif_lib.h GIFSTRINGS)
+ string(REGEX MATCH "GIFLIB_MAJOR ([0-9])" GIFLIB_MAJOR ${GIFSTRINGS})
+ if(GIFLIB_MAJOR)
+ string(REPLACE " " ";" GIFLIB_MAJOR ${GIFLIB_MAJOR})
+ list(GET GIFLIB_MAJOR 1 GIFLIB_MAJOR)
+ else()
+ set(GIFLIB_MAJOR ${GIF_VERSION})
+ endif()
+ if(NOT GIFLIB_MAJOR OR GIFLIB_MAJOR LESS 5)
+ message(WARNING "giflib${GIFLIB_MAJOR} support is experimental. Consider updating to giflib5")
+ endif()
+endif()
+
+set(SOURCES src/md5.cpp
+ src/DecoderManager.cpp
+ src/TexturePacker.cpp
+ src/XBTFWriter.cpp
+ src/decoder/GIFDecoder.cpp
+ src/decoder/GifHelper.cpp
+ src/decoder/JPGDecoder.cpp
+ src/decoder/PNGDecoder.cpp
+ ${CMAKE_SOURCE_DIR}/xbmc/guilib/XBTF.cpp)
+
+set(CMAKE_POSITITION_INDEPENDENT_CODE 1)
+
+add_executable(TexturePacker ${SOURCES})
+target_include_directories(TexturePacker
+ PRIVATE ${PNG_INCLUDE_DIRS}
+ ${JPEG_INCLUDE_DIR}
+ ${GIF_INCLUDE_DIR}
+ ${CMAKE_SOURCE_DIR}/xbmc
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/decoder)
+target_link_libraries(TexturePacker
+ PRIVATE ${SYSTEM_LDFLAGS}
+ ${GIF_LIBRARIES}
+ ${PNG_LIBRARIES}
+ ${JPEG_LIBRARIES}
+ ${LZO2_LIBRARIES})
+target_compile_options(TexturePacker PRIVATE ${ARCH_DEFINES} ${SYSTEM_DEFINES})
diff --git a/tools/depends/native/TexturePacker/Makefile b/tools/depends/native/TexturePacker/Makefile
new file mode 100644
index 0000000..f50dc87
--- /dev/null
+++ b/tools/depends/native/TexturePacker/Makefile
@@ -0,0 +1,62 @@
+ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+-include ../../Makefile.include
+DEPS=Makefile
+
+ifeq ($(NATIVEPREFIX),)
+ PREFIX = $(ROOT_DIR)
+else
+ PREFIX = $(NATIVEPREFIX)
+endif
+
+ifeq ($(NATIVEPLATFORM),)
+ PLATFORM = native
+ EXTRA_CONFIGURE = --enable-static
+else
+ PLATFORM = $(NATIVEPLATFORM)
+ DEPS += ../../Makefile.include
+endif
+
+ifeq ($(NATIVE_OS), linux)
+ EXTRA_CONFIGURE = --enable-static
+endif
+ifeq ($(NATIVE_OS), android)
+ EXTRA_CONFIGURE = --enable-static
+endif
+
+ifeq ($(CMAKE_SOURCE_DIR),)
+ CMAKE_SOURCE_DIR = $(ROOT_DIR)/../../../..
+endif
+
+SOURCE=$(ROOT_DIR)/src
+
+APP=$(PLATFORM)/TexturePacker
+APPBIN=$(PREFIX)/bin/TexturePacker
+
+all: .installed-$(PLATFORM)
+
+$(PLATFORM): $(DEPS)
+ -rm -rf $(PLATFORM)/*; mkdir -p $(PLATFORM)
+ cd $(PLATFORM); cp -a $(SOURCE)/* .
+ cd $(PLATFORM); ./autogen.sh
+ cd $(PLATFORM); ./configure --prefix=$(PREFIX) $(EXTRA_CONFIGURE) EXTRA_DEFINES="$(NATIVE_ARCH_DEFINES)"
+
+
+$(APP): $(PLATFORM)
+ $(MAKE) -C $(PLATFORM)
+
+.installed-$(PLATFORM): $(APP)
+ $(MAKE) -C $(PLATFORM) install
+ touch $@
+ #TEMP workaround for skins: create legacy link. Remove me when skins are fixed
+ @mkdir -p $(CMAKE_SOURCE_DIR)/tools/TexturePacker
+ @[ -f $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker ] && rm $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker || :
+ @ln -sf $(APPBIN) $(CMAKE_SOURCE_DIR)/tools/TexturePacker/TexturePacker
+ @echo "all:" > $(CMAKE_SOURCE_DIR)/tools/TexturePacker/Makefile
+ @echo "\t@echo "WARNING: use of tools/TexturePacker/TexturePacker is deprecated, please update your skins Makefile"" >> $(CMAKE_SOURCE_DIR)/tools/TexturePacker/Makefile
+
+clean:
+ $(MAKE) -C $(PLATFORM) clean
+
+distclean::
+ rm -rf $(PLATFORM) .installed-$(PLATFORM)
+ -rm -rf bin
diff --git a/tools/depends/native/TexturePacker/src/DecoderManager.cpp b/tools/depends/native/TexturePacker/src/DecoderManager.cpp
new file mode 100644
index 0000000..8f6a904
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/DecoderManager.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <cstdio>
+#include "DecoderManager.h"
+
+bool DecoderManager::verbose;
+std::vector<IDecoder *> DecoderManager::m_decoders;
+
+// ADD new decoders here
+// include decoders
+#include "PNGDecoder.h"
+#include "JPGDecoder.h"
+#include "GIFDecoder.h"
+
+void DecoderManager::InstantiateDecoders()
+{
+ m_decoders.push_back(new PNGDecoder());
+ m_decoders.push_back(new JPGDecoder());
+ m_decoders.push_back(new GIFDecoder());
+}
+
+void DecoderManager::FreeDecoders()
+{
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ delete m_decoders[i];
+ }
+ m_decoders.clear();
+}
+
+// returns true for png, bmp, tga, jpg and dds files, otherwise returns false
+bool DecoderManager::IsSupportedGraphicsFile(char *strFileName)
+{
+ std::string filename = strFileName;
+ if (filename.length() < 4)
+ return false;
+
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ const std::vector<std::string> extensions = m_decoders[i]->GetSupportedExtensions();
+ for (unsigned int n = 0; n < extensions.size(); n++)
+ {
+ int extLen = extensions[n].length();
+ if (std::string::npos != filename.rfind(extensions[n].c_str(), filename.length() - extLen, extLen))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool DecoderManager::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ for (unsigned int i = 0; i < m_decoders.size(); i++)
+ {
+ if (m_decoders[i]->CanDecode(filename))
+ {
+ if (verbose)
+ fprintf(stdout, "This is a %s - lets load it via %s...\n",
+ m_decoders[i]->GetImageFormatName(), m_decoders[i]->GetDecoderName());
+ return m_decoders[i]->LoadFile(filename, frames);
+ }
+ }
+ return false;
+}
+
+void DecoderManager::FreeDecodedFrames(DecodedFrames &frames)
+{
+ frames.clear();
+}
diff --git a/tools/depends/native/TexturePacker/src/DecoderManager.h b/tools/depends/native/TexturePacker/src/DecoderManager.h
new file mode 100644
index 0000000..2c59aa2
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/DecoderManager.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class DecoderManager
+{
+ public:
+ static void InstantiateDecoders();
+ static void FreeDecoders();
+ static bool IsSupportedGraphicsFile(char *strFileName);
+ static bool LoadFile(const std::string &filename, DecodedFrames &frames);
+ static void FreeDecodedFrames(DecodedFrames &frames);
+ static bool verbose;
+
+ private:
+ static std::vector<IDecoder *> m_decoders;
+};
diff --git a/tools/depends/native/TexturePacker/src/Makefile.am b/tools/depends/native/TexturePacker/src/Makefile.am
new file mode 100644
index 0000000..d6b676f
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Makefile.am
@@ -0,0 +1,29 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+AM_CFLAGS = -DTARGET_POSIX
+AM_CFLAGS += @EXTRA_DEFINES@
+AM_CXXFLAGS = $(AM_CFLAGS) -std=c++0x
+
+AM_CPPFLAGS = \
+ -I. \
+ -I./decoder \
+ -I@KODI_SRC_DIR@/xbmc \
+ -I@KODI_SRC_DIR@/xbmc/guilib \
+ @CPPFLAGS@
+
+AM_LDFLAGS = @LIBS@ @STATIC_FLAG@
+
+
+bin_PROGRAMS = TexturePacker
+TexturePacker_SOURCES = md5.cpp \
+ XBTFWriter.cpp \
+ TexturePacker.cpp \
+ DecoderManager.cpp \
+ decoder/PNGDecoder.cpp \
+ decoder/JPGDecoder.cpp \
+ decoder/GifHelper.cpp \
+ decoder/GIFDecoder.cpp \
+ XBTF.cpp
+
+XBTF.cpp:
+ @cp @KODI_SRC_DIR@/xbmc/guilib/XBTF.cpp .
diff --git a/tools/depends/native/TexturePacker/src/SimpleFS.h b/tools/depends/native/TexturePacker/src/SimpleFS.h
new file mode 100644
index 0000000..69d3342
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/SimpleFS.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstdio>
+#include <string>
+
+class CFile
+{
+public:
+ CFile()
+ {
+ m_file = NULL;
+ }
+
+ ~CFile()
+ {
+ Close();
+ }
+
+ bool Open(const std::string &file)
+ {
+ Close();
+ m_file = fopen(file.c_str(), "rb");
+ return NULL != m_file;
+ }
+
+ bool OpenForWrite(const std::string &file, bool overwrite)
+ {
+ Close();
+ m_file = fopen(file.c_str(), "wb");
+ return NULL != m_file;
+ }
+ void Close()
+ {
+ if (m_file)
+ fclose(m_file);
+ m_file = NULL;
+ }
+
+ uint64_t Read(void *data, uint64_t size)
+ {
+ if (fread(data, (size_t)size, 1, m_file) == 1)
+ return size;
+ return 0;
+ }
+
+ uint64_t Write(const void *data, uint64_t size)
+ {
+ if (fwrite(data, (size_t)size, 1, m_file) == 1)
+ return size;
+ return 0;
+ }
+
+ FILE *getFP()
+ {
+ return m_file;
+ }
+
+ uint64_t GetFileSize()
+ {
+ long curPos = ftell(m_file);
+ uint64_t fileSize = 0;
+ if (fseek(m_file, 0, SEEK_END) == 0)
+ {
+ long size = ftell(m_file);
+ if (size >= 0)
+ fileSize = (uint64_t)size;
+ }
+
+ // restore fileptr
+ Seek(curPos);
+
+ return fileSize;
+ }
+
+ uint64_t Seek(uint64_t offset)
+ {
+ uint64_t seekedBytes = 0;
+ int seekRet = fseek(m_file, offset, SEEK_SET);
+ if (seekRet == 0)
+ seekedBytes = offset;
+ return seekedBytes;
+ }
+
+private:
+ FILE* m_file;
+};
diff --git a/tools/depends/native/TexturePacker/src/TexturePacker.cpp b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
new file mode 100644
index 0000000..a6fd428
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef TARGET_WINDOWS
+#include <sys/types.h>
+#define __STDC_FORMAT_MACROS
+#include <cinttypes>
+#define platform_stricmp _stricmp
+#else
+#include <inttypes.h>
+#define platform_stricmp strcasecmp
+#endif
+#include <cerrno>
+#include <dirent.h>
+#include <map>
+
+#include "guilib/XBTF.h"
+#include "guilib/XBTFReader.h"
+
+#include "DecoderManager.h"
+
+#include "XBTFWriter.h"
+#include "md5.h"
+#include "cmdlineargs.h"
+
+#ifdef TARGET_WINDOWS
+#define strncasecmp _strnicmp
+#endif
+
+#include <lzo/lzo1x.h>
+#include <sys/stat.h>
+
+#define FLAGS_USE_LZO 1
+
+#define DIR_SEPARATOR '/'
+
+const char *GetFormatString(unsigned int format)
+{
+ switch (format)
+ {
+ case XB_FMT_DXT1:
+ return "DXT1 ";
+ case XB_FMT_DXT3:
+ return "DXT3 ";
+ case XB_FMT_DXT5:
+ return "DXT5 ";
+ case XB_FMT_DXT5_YCoCg:
+ return "YCoCg";
+ case XB_FMT_A8R8G8B8:
+ return "ARGB ";
+ case XB_FMT_A8:
+ return "A8 ";
+ default:
+ return "?????";
+ }
+}
+
+void CreateSkeletonHeaderImpl(CXBTFWriter& xbtfWriter,
+ const std::string& fullPath,
+ const std::string& relativePath)
+{
+ struct dirent* dp;
+ struct stat stat_p;
+ DIR *dirp = opendir(fullPath.c_str());
+
+ if (dirp)
+ {
+ for (errno = 0; (dp = readdir(dirp)); errno = 0)
+ {
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ {
+ continue;
+ }
+
+ //stat to check for dir type (reiserfs fix)
+ std::string fileN = fullPath + "/" + dp->d_name;
+ if (stat(fileN.c_str(), &stat_p) == 0)
+ {
+ if (dp->d_type == DT_DIR || stat_p.st_mode & S_IFDIR)
+ {
+ std::string tmpPath = relativePath;
+ if (tmpPath.size() > 0)
+ {
+ tmpPath += "/";
+ }
+
+ CreateSkeletonHeaderImpl(xbtfWriter, fullPath + DIR_SEPARATOR + dp->d_name, tmpPath + dp->d_name);
+ }
+ else if (DecoderManager::IsSupportedGraphicsFile(dp->d_name))
+ {
+ std::string fileName = "";
+ if (relativePath.size() > 0)
+ {
+ fileName += relativePath;
+ fileName += "/";
+ }
+
+ fileName += dp->d_name;
+
+ CXBTFFile file;
+ file.SetPath(fileName);
+ xbtfWriter.AddFile(file);
+ }
+ }
+ }
+ if (errno)
+ fprintf(stderr, "Error reading directory %s (%s)\n", fullPath.c_str(), strerror(errno));
+
+ closedir(dirp);
+ }
+ else
+ {
+ fprintf(stderr, "Error opening %s (%s)\n", fullPath.c_str(), strerror(errno));
+ }
+}
+
+void CreateSkeletonHeader(CXBTFWriter& xbtfWriter, const std::string& fullPath)
+{
+ std::string temp;
+ CreateSkeletonHeaderImpl(xbtfWriter, fullPath, temp);
+}
+
+CXBTFFrame appendContent(CXBTFWriter &writer, int width, int height, unsigned char *data, unsigned int size, unsigned int format, bool hasAlpha, unsigned int flags)
+{
+ CXBTFFrame frame;
+ lzo_uint packedSize = size;
+
+ if ((flags & FLAGS_USE_LZO) == FLAGS_USE_LZO)
+ {
+ // grab a temporary buffer for unpacking into
+ packedSize = size + size / 16 + 64 + 3; // see simple.c in lzo
+ unsigned char *packed = new unsigned char[packedSize];
+ unsigned char *working = new unsigned char[LZO1X_999_MEM_COMPRESS];
+ if (packed && working)
+ {
+ if (lzo1x_999_compress(data, size, packed, &packedSize, working) != LZO_E_OK || packedSize > size)
+ {
+ // compression failed, or compressed size is bigger than uncompressed, so store as uncompressed
+ packedSize = size;
+ writer.AppendContent(data, size);
+ }
+ else
+ { // success
+ lzo_uint optimSize = size;
+ if (lzo1x_optimize(packed, packedSize, data, &optimSize, NULL) != LZO_E_OK || optimSize != size)
+ { //optimisation failed
+ packedSize = size;
+ writer.AppendContent(data, size);
+ }
+ else
+ { // success
+ writer.AppendContent(packed, packedSize);
+ }
+ }
+ delete[] working;
+ delete[] packed;
+ }
+ }
+ else
+ {
+ writer.AppendContent(data, size);
+ }
+ frame.SetPackedSize(packedSize);
+ frame.SetUnpackedSize(size);
+ frame.SetWidth(width);
+ frame.SetHeight(height);
+ frame.SetFormat(hasAlpha ? format : format | XB_FMT_OPAQUE);
+ frame.SetDuration(0);
+ return frame;
+}
+
+bool HasAlpha(unsigned char *argb, unsigned int width, unsigned int height)
+{
+ unsigned char *p = argb + 3; // offset of alpha
+ for (unsigned int i = 0; i < 4*width*height; i += 4)
+ {
+ if (p[i] != 0xff)
+ return true;
+ }
+ return false;
+}
+
+CXBTFFrame createXBTFFrame(RGBAImage &image, CXBTFWriter& writer, double maxMSE, unsigned int flags)
+{
+
+ int width, height;
+ unsigned int format = 0;
+ unsigned char* argb = (unsigned char*)image.pixels;
+
+ width = image.width;
+ height = image.height;
+ bool hasAlpha = HasAlpha(argb, width, height);
+
+ CXBTFFrame frame;
+ format = XB_FMT_A8R8G8B8;
+ frame = appendContent(writer, width, height, argb, (width * height * 4), format, hasAlpha, flags);
+
+ return frame;
+}
+
+void Usage()
+{
+ puts("Usage:");
+ puts(" -help Show this screen.");
+ puts(" -input <dir> Input directory. Default: current dir");
+ puts(" -output <dir> Output directory/filename. Default: Textures.xbt");
+ puts(" -dupecheck Enable duplicate file detection. Reduces output file size. Default: off");
+}
+
+static bool checkDupe(struct MD5Context* ctx,
+ std::map<std::string, unsigned int>& hashes,
+ std::vector<unsigned int>& dupes, unsigned int pos)
+{
+ unsigned char digest[17];
+ MD5Final(digest,ctx);
+ digest[16] = 0;
+ char hex[33];
+ sprintf(hex, "%02X%02X%02X%02X%02X%02X%02X%02X"\
+ "%02X%02X%02X%02X%02X%02X%02X%02X", digest[0], digest[1], digest[2],
+ digest[3], digest[4], digest[5], digest[6], digest[7], digest[8],
+ digest[9], digest[10], digest[11], digest[12], digest[13], digest[14],
+ digest[15]);
+ hex[32] = 0;
+ std::map<std::string, unsigned int>::iterator it = hashes.find(hex);
+ if (it != hashes.end())
+ {
+ dupes[pos] = it->second;
+ return true;
+ }
+
+ hashes.insert(std::make_pair(hex,pos));
+ dupes[pos] = pos;
+
+ return false;
+}
+
+int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags, bool dupecheck)
+{
+ CXBTFWriter writer(OutputFile);
+ if (!writer.Create())
+ {
+ fprintf(stderr, "Error creating file\n");
+ return 1;
+ }
+
+ std::map<std::string, unsigned int> hashes;
+ std::vector<unsigned int> dupes;
+ CreateSkeletonHeader(writer, InputDir);
+
+ std::vector<CXBTFFile> files = writer.GetFiles();
+ dupes.resize(files.size());
+ if (!dupecheck)
+ {
+ for (unsigned int i=0;i<dupes.size();++i)
+ dupes[i] = i;
+ }
+
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ struct MD5Context ctx;
+ MD5Init(&ctx);
+ CXBTFFile& file = files[i];
+
+ std::string fullPath = InputDir;
+ fullPath += file.GetPath();
+
+ std::string output = file.GetPath();
+ output = output.substr(0, 40);
+ while (output.size() < 46)
+ output += ' ';
+
+ DecodedFrames frames;
+ bool loaded = DecoderManager::LoadFile(fullPath, frames);
+
+ if (!loaded)
+ {
+ fprintf(stderr, "...unable to load image %s\n", file.GetPath().c_str());
+ continue;
+ }
+
+ printf("%s\n", output.c_str());
+ bool skip=false;
+ if (dupecheck)
+ {
+ for (unsigned int j = 0; j < frames.frameList.size(); j++)
+ MD5Update(&ctx,
+ (const uint8_t*)frames.frameList[j].rgbaImage.pixels,
+ frames.frameList[j].rgbaImage.height * frames.frameList[j].rgbaImage.pitch);
+
+ if (checkDupe(&ctx,hashes,dupes,i))
+ {
+ printf("**** duplicate of %s\n", files[dupes[i]].GetPath().c_str());
+ file.GetFrames().insert(file.GetFrames().end(),
+ files[dupes[i]].GetFrames().begin(),
+ files[dupes[i]].GetFrames().end());
+ skip = true;
+ }
+ }
+
+ if (!skip)
+ {
+ for (unsigned int j = 0; j < frames.frameList.size(); j++)
+ {
+ printf(" frame %4i (delay:%4i) ", j, frames.frameList[j].delay);
+ CXBTFFrame frame = createXBTFFrame(frames.frameList[j].rgbaImage, writer, maxMSE, flags);
+ frame.SetDuration(frames.frameList[j].delay);
+ file.GetFrames().push_back(frame);
+ printf("%s%c (%d,%d @ %" PRIu64 " bytes)\n", GetFormatString(frame.GetFormat()), frame.HasAlpha() ? ' ' : '*',
+ frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize());
+ }
+ }
+ DecoderManager::FreeDecodedFrames(frames);
+ file.SetLoop(0);
+
+ writer.UpdateFile(file);
+ }
+
+ if (!writer.UpdateHeader(dupes))
+ {
+ fprintf(stderr, "Error writing header to file\n");
+ return 1;
+ }
+
+ if (!writer.Close())
+ {
+ fprintf(stderr, "Error closing file\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ if (lzo_init() != LZO_E_OK)
+ return 1;
+ bool valid = false;
+ unsigned int flags = 0;
+ bool dupecheck = false;
+ CmdLineArgs args(argc, (const char**)argv);
+
+ // setup some defaults, lzo packing,
+ flags = FLAGS_USE_LZO;
+
+ if (args.size() == 1)
+ {
+ Usage();
+ return 1;
+ }
+
+ std::string InputDir;
+ std::string OutputFilename = "Textures.xbt";
+
+ for (unsigned int i = 1; i < args.size(); ++i)
+ {
+ if (!platform_stricmp(args[i], "-help") || !platform_stricmp(args[i], "-h") || !platform_stricmp(args[i], "-?"))
+ {
+ Usage();
+ return 1;
+ }
+ else if (!platform_stricmp(args[i], "-input") || !platform_stricmp(args[i], "-i"))
+ {
+ InputDir = args[++i];
+ valid = true;
+ }
+ else if (!strcmp(args[i], "-dupecheck"))
+ {
+ dupecheck = true;
+ }
+ else if (!strcmp(args[i], "-verbose"))
+ {
+ DecoderManager::verbose = true;
+ }
+ else if (!platform_stricmp(args[i], "-output") || !platform_stricmp(args[i], "-o"))
+ {
+ OutputFilename = args[++i];
+ valid = true;
+#ifdef TARGET_POSIX
+ char *c = NULL;
+ while ((c = (char *)strchr(OutputFilename.c_str(), '\\')) != NULL) *c = '/';
+#endif
+ }
+ else
+ {
+ fprintf(stderr, "Unrecognized command line flag: %s\n", args[i]);
+ }
+ }
+
+ if (!valid)
+ {
+ Usage();
+ return 1;
+ }
+
+ size_t pos = InputDir.find_last_of(DIR_SEPARATOR);
+ if (pos != InputDir.length() - 1)
+ InputDir += DIR_SEPARATOR;
+
+ double maxMSE = 1.5; // HQ only please
+ DecoderManager::InstantiateDecoders();
+ createBundle(InputDir, OutputFilename, maxMSE, flags, dupecheck);
+ DecoderManager::FreeDecoders();
+}
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln
new file mode 100644
index 0000000..07cd920
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TexturePacker", "TexturePacker.vcxproj", "{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.Build.0 = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.ActiveCfg = Release|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj
new file mode 100644
index 0000000..8f540ed
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}</ProjectGuid>
+ <RootNamespace>TexturePacker</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\..\project\BuildDependencies\include</IncludePath>
+ <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;..\..\..\..\..\..\project\BuildDependencies\lib</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\..\project\BuildDependencies\include</IncludePath>
+ <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;..\..\..\..\..\..\project\BuildDependencies\lib</LibraryPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;..\decoder;..\..\..\..\..\..\xbmc;..\..\..\..\..\..\project\BuildDependencies\win32\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;TARGET_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>jpeg-staticd.lib;libpng16_staticd.lib;gifd.lib;zlibstaticd.lib;lzo2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libcmtd.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>..\..\..\..\..\..\project\BuildDependencies\win32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>.;..;..\decoder;..\..\..\..\..\..\xbmc;..\..\..\..\..\..\project\BuildDependencies\win32\include</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;TARGET_WINDOWS;_ITERATOR_DEBUG_LEVEL=0;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>jpeg-static.lib;libpng16_static.lib;gif.lib;zlibstatic.lib;lzo2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <IgnoreSpecificDefaultLibraries>libc.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>..\..\..\..\..\..\project\BuildDependencies\win32\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\DecoderManager.cpp" />
+ <ClCompile Include="..\decoder\GIFDecoder.cpp" />
+ <ClCompile Include="..\decoder\GifHelper.cpp" />
+ <ClCompile Include="..\decoder\JPGDecoder.cpp" />
+ <ClCompile Include="..\decoder\PNGDecoder.cpp" />
+ <ClCompile Include="..\md5.cpp" />
+ <ClCompile Include="..\TexturePacker.cpp" />
+ <ClCompile Include="dirent.c" />
+ <ClCompile Include="..\..\..\..\..\..\xbmc\guilib\XBTF.cpp" />
+ <ClCompile Include="..\XBTFWriter.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\cmdlineargs.h" />
+ <ClInclude Include="..\DecoderManager.h" />
+ <ClInclude Include="..\decoder\GIFDecoder.h" />
+ <ClInclude Include="..\decoder\GifHelper.h" />
+ <ClInclude Include="..\decoder\IDecoder.h" />
+ <ClInclude Include="..\decoder\JPGDecoder.h" />
+ <ClInclude Include="..\decoder\PNGDecoder.h" />
+ <ClInclude Include="..\rgbaimage.h" />
+ <ClInclude Include="dirent.h" />
+ <ClInclude Include="..\md5.h" />
+ <ClInclude Include="..\..\..\..\..\..\xbmc\guilib\XBTF.h" />
+ <ClInclude Include="..\XBTFWriter.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters
new file mode 100644
index 0000000..f045d9c
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/TexturePacker.vcxproj.filters
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ <Filter Include="decoder">
+ <UniqueIdentifier>{c79bff3f-9118-4c2d-bc31-68b25f7dfbba}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dirent.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\..\xbmc\guilib\XBTF.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\XBTFWriter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\md5.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\GIFDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\GifHelper.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\JPGDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\decoder\PNGDecoder.cpp">
+ <Filter>decoder</Filter>
+ </ClCompile>
+ <ClCompile Include="..\TexturePacker.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\DecoderManager.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\cmdlineargs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="dirent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\md5.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\..\..\xbmc\guilib\XBTF.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\XBTFWriter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\rgbaimage.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\GIFDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\GifHelper.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\IDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\JPGDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\decoder\PNGDecoder.h">
+ <Filter>decoder</Filter>
+ </ClInclude>
+ <ClInclude Include="..\DecoderManager.h">
+ <Filter>Source Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/tools/depends/native/TexturePacker/src/Win32/dirent.c b/tools/depends/native/TexturePacker/src/Win32/dirent.c
new file mode 100644
index 0000000..7598516
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/dirent.c
@@ -0,0 +1,145 @@
+/*
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003 and July 2012.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dirent.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
+
+struct DIR
+{
+ handle_type handle; /* -1 for failed rewind */
+ struct _finddata_t info;
+ struct dirent result; /* d_name null iff first time */
+ char *name; /* null-terminated char string */
+};
+
+DIR *opendir(const char *name)
+{
+ DIR *dir = 0;
+
+ if(name && name[0])
+ {
+ size_t base_length = strlen(name);
+ const char *all = /* search pattern must end with suitable wildcard */
+ strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+ (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+ {
+ strcat(strcpy(dir->name, name), all);
+
+ if ((dir->handle = (handle_type)_findfirst(dir->name, &dir->info)) != -1)
+ {
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else /* rollback */
+ {
+ free(dir->name);
+ free(dir);
+ dir = 0;
+ }
+ }
+ else /* rollback */
+ {
+ free(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ }
+ else
+ {
+ errno = EINVAL;
+ }
+
+ return dir;
+}
+
+int closedir(DIR *dir)
+{
+ int result = -1;
+
+ if(dir)
+ {
+ if(dir->handle != -1)
+ {
+ result = _findclose(dir->handle);
+ }
+
+ free(dir->name);
+ free(dir);
+ }
+
+ if(result == -1) /* map all errors to EBADF */
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *result = 0;
+
+ if(dir && dir->handle != -1)
+ {
+ if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+ {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ result->d_type = (dir->info.attrib == _A_SUBDIR) ? DT_DIR : DT_UNKNOWN;
+ }
+ }
+ else
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+void rewinddir(DIR *dir)
+{
+ if(dir && dir->handle != -1)
+ {
+ _findclose(dir->handle);
+ dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else
+ {
+ errno = EBADF;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tools/depends/native/TexturePacker/src/Win32/dirent.h b/tools/depends/native/TexturePacker/src/Win32/dirent.h
new file mode 100644
index 0000000..e57b250
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/dirent.h
@@ -0,0 +1,53 @@
+/*
+
+ Declaration of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct DIR DIR;
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+struct dirent
+{
+ char *d_name;
+ unsigned char d_type;
+};
+
+DIR *opendir(const char *);
+int closedir(DIR *);
+struct dirent *readdir(DIR *);
+void rewinddir(DIR *);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/tools/depends/native/TexturePacker/src/Win32/version.rc b/tools/depends/native/TexturePacker/src/Win32/version.rc
new file mode 100644
index 0000000..7ccb57f
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/Win32/version.rc
Binary files differ
diff --git a/tools/depends/native/TexturePacker/src/XBTFWriter.cpp b/tools/depends/native/TexturePacker/src/XBTFWriter.cpp
new file mode 100644
index 0000000..1607db1
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/XBTFWriter.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <cinttypes>
+#if defined(TARGET_FREEBSD) || defined(TARGET_DARWIN)
+#include <cstdlib>
+#elif !defined(TARGET_DARWIN)
+#include <malloc.h>
+#endif
+#include <memory.h>
+#include <cstring>
+
+#include "XBTFWriter.h"
+#include "guilib/XBTFReader.h"
+#include "utils/EndianSwap.h"
+
+
+#define WRITE_STR(str, size, file) fwrite(str, size, 1, file)
+#define WRITE_U32(i, file) { uint32_t _n = Endian_SwapLE32(i); fwrite(&_n, 4, 1, file); }
+#define WRITE_U64(i, file) { uint64_t _n = i; _n = Endian_SwapLE64(i); fwrite(&_n, 8, 1, file); }
+
+CXBTFWriter::CXBTFWriter(const std::string& outputFile)
+ : m_outputFile(outputFile),
+ m_file(nullptr),
+ m_data(nullptr),
+ m_size(0)
+{ }
+
+CXBTFWriter::~CXBTFWriter()
+{
+ Close();
+}
+
+bool CXBTFWriter::Create()
+{
+ m_file = fopen(m_outputFile.c_str(), "wb");
+ if (m_file == nullptr)
+ return false;
+
+ return true;
+}
+
+bool CXBTFWriter::Close()
+{
+ if (m_file == nullptr || m_data == nullptr)
+ return false;
+
+ fwrite(m_data, 1, m_size, m_file);
+
+ Cleanup();
+
+ return true;
+}
+
+void CXBTFWriter::Cleanup()
+{
+ free(m_data);
+ m_data = nullptr;
+ m_size = 0;
+ if (m_file)
+ {
+ fclose(m_file);
+ m_file = nullptr;
+ }
+}
+
+bool CXBTFWriter::AppendContent(unsigned char const* data, size_t length)
+{
+ unsigned char *new_data = (unsigned char *)realloc(m_data, m_size + length);
+
+ if (new_data == nullptr)
+ { // OOM - cleanup and fail
+ Cleanup();
+ return false;
+ }
+
+ m_data = new_data;
+
+ memcpy(m_data + m_size, data, length);
+ m_size += length;
+
+ return true;
+}
+
+bool CXBTFWriter::UpdateHeader(const std::vector<unsigned int>& dupes)
+{
+ if (m_file == nullptr)
+ return false;
+
+ uint64_t headerSize = GetHeaderSize();
+ uint64_t offset = headerSize;
+
+ WRITE_STR(XBTF_MAGIC.c_str(), 4, m_file);
+ WRITE_STR(XBTF_VERSION.c_str(), 1, m_file);
+
+ auto files = GetFiles();
+ WRITE_U32(files.size(), m_file);
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ CXBTFFile& file = files[i];
+
+ // Convert path to lower case and store it into a fixed size array because
+ // we need to store the path as a fixed length 256 byte character array.
+ std::string path = file.GetPath();
+ char pathMem[CXBTFFile::MaximumPathLength];
+ memset(pathMem, 0, sizeof(pathMem));
+
+ for (std::string::iterator ch = path.begin(); ch != path.end(); ++ch)
+ pathMem[std::distance(path.begin(), ch)] = tolower(*ch);
+
+ WRITE_STR(pathMem, CXBTFFile::MaximumPathLength, m_file);
+ WRITE_U32(file.GetLoop(), m_file);
+
+ std::vector<CXBTFFrame>& frames = file.GetFrames();
+ WRITE_U32(frames.size(), m_file);
+ for (size_t j = 0; j < frames.size(); j++)
+ {
+ CXBTFFrame& frame = frames[j];
+ if (dupes[i] != i)
+ frame.SetOffset(files[dupes[i]].GetFrames()[j].GetOffset());
+ else
+ {
+ frame.SetOffset(offset);
+ offset += frame.GetPackedSize();
+ }
+
+ WRITE_U32(frame.GetWidth(), m_file);
+ WRITE_U32(frame.GetHeight(), m_file);
+ WRITE_U32(frame.GetFormat(true), m_file);
+ WRITE_U64(frame.GetPackedSize(), m_file);
+ WRITE_U64(frame.GetUnpackedSize(), m_file);
+ WRITE_U32(frame.GetDuration(), m_file);
+ WRITE_U64(frame.GetOffset(), m_file);
+ }
+ }
+
+ // Sanity check
+ int64_t pos = ftell(m_file);
+ if (pos != static_cast<int64_t>(headerSize))
+ {
+ printf("Expected header size (%" PRIu64 ") != actual size (%" PRId64 ")\n", headerSize, pos);
+ return false;
+ }
+
+ return true;
+}
diff --git a/tools/depends/native/TexturePacker/src/XBTFWriter.h b/tools/depends/native/TexturePacker/src/XBTFWriter.h
new file mode 100644
index 0000000..1e6496d
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/XBTFWriter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "guilib/XBTF.h"
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+class CXBTFWriter : public CXBTFBase
+{
+public:
+ CXBTFWriter(const std::string& outputFile);
+ ~CXBTFWriter() override;
+
+ bool Create();
+ bool Close();
+ bool AppendContent(unsigned char const* data, size_t length);
+ bool UpdateHeader(const std::vector<unsigned int>& dupes);
+
+private:
+ void Cleanup();
+
+ std::string m_outputFile;
+ FILE* m_file;
+ unsigned char *m_data;
+ size_t m_size;
+};
+
diff --git a/tools/depends/native/TexturePacker/src/autogen.sh b/tools/depends/native/TexturePacker/src/autogen.sh
new file mode 100755
index 0000000..bbec436
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/autogen.sh
@@ -0,0 +1,3 @@
+#/bin/sh
+
+autoreconf -vif
diff --git a/tools/depends/native/TexturePacker/src/cmdlineargs.h b/tools/depends/native/TexturePacker/src/cmdlineargs.h
new file mode 100644
index 0000000..d0b9d03
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/cmdlineargs.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#ifdef TARGET_POSIX
+char* GetCommandLine();
+#define _snprintf snprintf
+#else
+#include <windows.h>
+#endif
+#include <vector>
+#include <string>
+
+class CmdLineArgs : public std::vector<char*>
+{
+public:
+ CmdLineArgs ()
+ {
+ // Save local copy of the command line string, because
+ // ParseCmdLine() modifies this string while parsing it.
+ char* cmdline = GetCommandLine();
+ m_cmdline = new char [strlen (cmdline) + 1];
+ if (m_cmdline)
+ {
+ strcpy (m_cmdline, cmdline);
+ ParseCmdLine();
+ } else {
+#ifdef TARGET_POSIX
+ delete[] cmdline;
+#endif
+ }
+ }
+
+ CmdLineArgs (const int argc, const char **argv)
+ {
+ std::string cmdline;
+#ifdef TARGET_POSIX
+ cmdline = "\"";
+#endif
+ for (int i = 0 ; i<argc ; i++)
+ {
+ cmdline += std::string(argv[i]);
+ if ( i != (argc-1) )
+ {
+#ifdef TARGET_POSIX
+ cmdline += "\" \"";
+#else
+ cmdline += " ";
+#endif
+ }
+ }
+#ifdef TARGET_POSIX
+ cmdline += "\"";
+#endif
+ m_cmdline = new char [cmdline.length() + 1];
+ if (m_cmdline)
+ {
+ strcpy(m_cmdline, cmdline.c_str());
+ ParseCmdLine();
+ }
+ }
+
+ ~CmdLineArgs()
+ {
+ delete[] m_cmdline;
+ }
+
+private:
+ char* m_cmdline; // the command line string
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Parse m_cmdline into individual tokens, which are delimited by spaces. If a
+ // token begins with a quote, then that token is terminated by the next quote
+ // followed immediately by a space or terminator. This allows tokens to contain
+ // spaces.
+ // This input string: This "is" a ""test"" "of the parsing" alg"o"rithm.
+ // Produces these tokens: This, is, a, "test", of the parsing, alg"o"rithm
+ ////////////////////////////////////////////////////////////////////////////////
+ void ParseCmdLine ()
+ {
+ enum { TERM = '\0',
+ QUOTE = '\"' };
+
+ bool bInQuotes = false;
+ char* pargs = m_cmdline;
+
+ while (*pargs)
+ {
+ while (isspace (*pargs)) // skip leading whitespace
+ pargs++;
+
+ bInQuotes = (*pargs == QUOTE); // see if this token is quoted
+
+ if (bInQuotes) // skip leading quote
+ pargs++;
+
+ push_back (pargs); // store position of current token
+
+ // Find next token.
+ // NOTE: Args are normally terminated by whitespace, unless the
+ // arg is quoted. That's why we handle the two cases separately,
+ // even though they are very similar.
+ if (bInQuotes)
+ {
+ // find next quote followed by a space or terminator
+ while (*pargs &&
+ !(*pargs == QUOTE && (isspace (pargs[1]) || pargs[1] == TERM)))
+ pargs++;
+ if (*pargs)
+ {
+ *pargs = TERM; // terminate token
+ if (pargs[1]) // if quoted token not followed by a terminator
+ pargs += 2; // advance to next token
+ }
+ }
+ else
+ {
+ // skip to next non-whitespace character
+ while (*pargs && !isspace (*pargs))
+ pargs++;
+ if (*pargs && isspace (*pargs)) // end of token
+ {
+ *pargs = TERM; // terminate token
+ pargs++; // advance to next token or terminator
+ }
+ }
+ } // while (*pargs)
+ } // ParseCmdLine()
+}; // class CmdLineArgs
+
diff --git a/tools/depends/native/TexturePacker/src/configure.ac b/tools/depends/native/TexturePacker/src/configure.ac
new file mode 100644
index 0000000..4b83b5e
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/configure.ac
@@ -0,0 +1,41 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(TexturePacker, 1.0)
+AC_CONFIG_AUX_DIR(config)
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_SRCDIR(TexturePacker.cpp)
+AM_INIT_AUTOMAKE([foreign])
+AC_PROG_CXX
+AC_LANG([C++])
+AC_C_BIGENDIAN
+
+abs_top_srcdir=${abs_top_srcdir=$(cd $srcdir; pwd)}
+KODI_SRC_DIR=${KODI_SRC_DIR:-"${abs_top_srcdir}/../../../../.."}
+
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static],
+ [build static TexturePacker (default is no)])],
+ [STATIC_FLAG="-static"],
+ [STATIC_FLAG=""])
+
+
+PKG_CHECK_MODULES([PNG], [libpng],
+ [INCLUDES="$PNG_CFLAGS"; LIBS="$LIBS $(${PKG_CONFIG} --silence-errors --static --libs libpng)"],
+ AC_MSG_ERROR("libpng not found"))
+
+AC_CHECK_HEADER([gif_lib.h],, AC_MSG_ERROR("gif_lib.h not found"))
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <gif_lib.h>]], [[
+#if !defined GIFLIB_MAJOR || GIFLIB_MAJOR < 5
+#error libgif version < 5;
+#endif ]])], [], [AC_MSG_NOTICE([[WARNING: libgif version is unsupported, please consider upgrading to 5.0.5 or higher.]])])
+
+AC_CHECK_LIB([gif],[main],, AC_MSG_ERROR("libgif not found"))
+AC_CHECK_HEADER([jpeglib.h],, AC_MSG_ERROR("jpeglib.h not found"))
+AC_CHECK_LIB([jpeg],[main],, AC_MSG_ERROR("libjpeg not found"))
+AC_CHECK_HEADER([lzo/lzo1x.h],, AC_MSG_ERROR("lzo/lzo1x.h not found"))
+AC_CHECK_LIB([lzo2],[main],, AC_MSG_ERROR("liblzo2 not found"))
+
+AC_SUBST(KODI_SRC_DIR)
+AC_SUBST(STATIC_FLAG)
+AC_SUBST(EXTRA_DEFINES)
+
+AC_OUTPUT(Makefile)
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
new file mode 100644
index 0000000..5bdfacd
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GIFDecoder.h"
+
+#include "GifHelper.h"
+
+#include <cstring>
+
+// returns true for gif files, otherwise returns false
+bool GIFDecoder::CanDecode(const std::string &filename)
+{
+ return std::string::npos != filename.rfind(".gif",filename.length() - 4, 4);
+}
+
+bool GIFDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ int n = 0;
+ bool result = false;
+
+ GifHelper *gifImage = new GifHelper();
+ if (gifImage->LoadGif(filename.c_str()))
+ {
+ auto extractedFrames = gifImage->GetFrames();
+ n = extractedFrames.size();
+ if (n > 0)
+ {
+ unsigned int height = gifImage->GetHeight();
+ unsigned int width = gifImage->GetWidth();
+ unsigned int pitch = gifImage->GetPitch();
+ unsigned int frameSize = pitch * height;
+ for (unsigned int i = 0; i < extractedFrames.size(); i++)
+ {
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)new char[frameSize];
+ memcpy(frame.rgbaImage.pixels, extractedFrames[i]->m_pImage, frameSize);
+ frame.rgbaImage.height = height;
+ frame.rgbaImage.width = width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = pitch;
+ frame.delay = extractedFrames[i]->m_delay;
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+ }
+ }
+ result = true;
+ }
+ delete gifImage;
+ return result;
+}
+
+void GIFDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void GIFDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".gif");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h
new file mode 100644
index 0000000..8f0b42d
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GIFDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class GIFDecoder : public IDecoder
+{
+ public:
+ ~GIFDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "GIF"; }
+ const char* GetDecoderName() override { return "libgif"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
new file mode 100644
index 0000000..41ca270
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GifHelper.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+
+#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
+#define GIF_MAX_MEMORY 82944000U // about 79 MB, which is equivalent to 10 full hd frames.
+
+class Gifreader
+{
+public:
+ unsigned char* buffer = nullptr;
+ unsigned int buffSize = 0;
+ unsigned int readPosition = 0;
+
+ Gifreader() = default;
+};
+
+int ReadFromVfs(GifFileType* gif, GifByteType* gifbyte, int len)
+{
+ CFile *gifFile = static_cast<CFile*>(gif->UserData);
+ return gifFile->Read(gifbyte, len);
+}
+
+GifHelper::GifHelper()
+{
+ m_gifFile = new CFile();
+}
+
+GifHelper::~GifHelper()
+{
+ Close(m_gif);
+ Release();
+ delete m_gifFile;
+}
+
+bool GifHelper::Open(GifFileType*& gif, void *dataPtr, InputFunc readFunc)
+{
+ int err = 0;
+#if GIFLIB_MAJOR == 5
+ gif = DGifOpen(dataPtr, readFunc, &err);
+#else
+ gif = DGifOpen(dataPtr, readFunc);
+ if (!gif)
+ err = GifLastError();
+#endif
+
+ if (!gif)
+ {
+ fprintf(stderr, "Gif::Open(): Could not open file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(err));
+ return false;
+ }
+
+ return true;
+}
+
+void GifHelper::Close(GifFileType* gif)
+{
+ int err = 0;
+ int reason = 0;
+#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
+ err = DGifCloseFile(gif, &reason);
+#else
+ err = DGifCloseFile(gif);
+#if GIFLIB_MAJOR < 5
+ reason = GifLastError();
+#endif
+ if (err == GIF_ERROR)
+ free(gif);
+#endif
+ if (err == GIF_ERROR)
+ {
+ fprintf(stderr, "GifHelper::Close(): closing file %s failed. Reason: %s\n", m_filename.c_str(), Reason(reason));
+ }
+}
+
+const char* GifHelper::Reason(int reason)
+{
+ const char* err = GifErrorString(reason);
+ if (err)
+ return err;
+
+ return "unknown";
+
+}
+
+void GifHelper::Release()
+{
+ delete[] m_pTemplate;
+ m_pTemplate = nullptr;
+ m_globalPalette.clear();
+ m_frames.clear();
+}
+
+void GifHelper::ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size)
+{
+ for (unsigned int i = 0; i < size; ++i)
+ {
+ GifColor c;
+
+ c.r = src->Colors[i].Red;
+ c.g = src->Colors[i].Green;
+ c.b = src->Colors[i].Blue;
+ c.a = 0xff;
+ dest.push_back(c);
+ }
+}
+
+bool GifHelper::LoadGifMetaData(GifFileType* gif)
+{
+ if (!Slurp(gif))
+ return false;
+
+ m_height = gif->SHeight;
+ m_width = gif->SWidth;
+ if (!m_height || !m_width)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Zero sized image. File %s\n", m_filename.c_str());
+ return false;
+ }
+
+ m_numFrames = gif->ImageCount;
+ if (m_numFrames > 0)
+ {
+ ExtensionBlock* extb = gif->SavedImages[0].ExtensionBlocks;
+ if (extb && extb->Function == APPLICATION_EXT_FUNC_CODE)
+ {
+ // Read number of loops
+ if (++extb && extb->Function == CONTINUE_EXT_FUNC_CODE)
+ {
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ m_loops = UNSIGNED_LITTLE_ENDIAN(low, high);
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Gif::LoadGif(): No images found in file %s\n", m_filename.c_str());
+ return false;
+ }
+
+ m_pitch = m_width * sizeof(GifColor);
+ m_imageSize = m_pitch * m_height;
+ unsigned long memoryUsage = m_numFrames * m_imageSize;
+ if (memoryUsage > GIF_MAX_MEMORY)
+ {
+ // at least 1 image
+ m_numFrames = std::max(1U, GIF_MAX_MEMORY / m_imageSize);
+ fprintf(stderr, "Gif::LoadGif(): Memory consumption too high: %lu bytes. Restricting animation to %u. File %s\n", memoryUsage, m_numFrames, m_filename.c_str());
+ }
+
+ return true;
+}
+
+bool GifHelper::LoadGifMetaData(const char* file)
+{
+ m_gifFile->Close();
+ if (!m_gifFile->Open(file) || !Open(m_gif, m_gifFile, ReadFromVfs))
+ return false;
+
+ return LoadGifMetaData(m_gif);
+}
+
+bool GifHelper::Slurp(GifFileType* gif)
+{
+ if (DGifSlurp(gif) == GIF_ERROR)
+ {
+ int reason = 0;
+#if GIFLIB_MAJOR == 5
+ reason = gif->Error;
+#else
+ reason = GifLastError();
+#endif
+ fprintf(stderr, "Gif::LoadGif(): Could not read file %s. Reason: %s\n", m_filename.c_str(), GifErrorString(reason));
+ return false;
+ }
+
+ return true;
+}
+
+bool GifHelper::LoadGif(const char* file)
+{
+ m_filename = file;
+ if (!LoadGifMetaData(m_filename.c_str()))
+ return false;
+
+ try
+ {
+ InitTemplateAndColormap();
+
+ int extractedFrames = ExtractFrames(m_numFrames);
+ if (extractedFrames < 0)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could not extract any frame. File %s\n", m_filename.c_str());
+ return false;
+ }
+ else if (extractedFrames < (int)m_numFrames)
+ {
+ fprintf(stderr, "Gif::LoadGif(): Could only extract %d/%d frames. File %s\n", extractedFrames, m_numFrames, m_filename.c_str());
+ m_numFrames = extractedFrames;
+ }
+
+ return true;
+ }
+ catch (std::bad_alloc& ba)
+ {
+ fprintf(stderr, "Gif::Load(): Out of memory while reading file %s - %s\n", m_filename.c_str(), ba.what());
+ Release();
+ return false;
+ }
+}
+
+void GifHelper::InitTemplateAndColormap()
+{
+ m_pTemplate = new unsigned char[m_imageSize];
+ memset(m_pTemplate, 0, m_imageSize);
+
+ if (m_gif->SColorMap)
+ {
+ m_globalPalette.clear();
+ ConvertColorTable(m_globalPalette, m_gif->SColorMap, m_gif->SColorMap->ColorCount);
+ }
+ else
+ m_globalPalette.clear();
+}
+
+bool GifHelper::GcbToFrame(GifFrame &frame, unsigned int imgIdx)
+{
+ int transparent = -1;
+ frame.m_delay = 0;
+ frame.m_disposal = 0;
+
+ if (m_gif->ImageCount > 0)
+ {
+#if GIFLIB_MAJOR == 5
+ GraphicsControlBlock gcb;
+ if (DGifSavedExtensionToGCB(m_gif, imgIdx, &gcb))
+ {
+ // delay in ms
+ frame.m_delay = gcb.DelayTime * 10;
+ frame.m_disposal = gcb.DisposalMode;
+ transparent = gcb.TransparentColor;
+ }
+#else
+ ExtensionBlock* extb = m_gif->SavedImages[imgIdx].ExtensionBlocks;
+ while (extb && extb->Function != GRAPHICS_EXT_FUNC_CODE)
+ extb++;
+
+ if (extb && extb->ByteCount == 4)
+ {
+ uint8_t low = static_cast<uint8_t>(extb->Bytes[1]);
+ uint8_t high = static_cast<uint8_t>(extb->Bytes[2]);
+ frame.m_delay = UNSIGNED_LITTLE_ENDIAN(low, high) * 10;
+ frame.m_disposal = (extb->Bytes[0] >> 2) & 0x07;
+ if (extb->Bytes[0] & 0x01)
+ {
+ transparent = static_cast<uint8_t>(extb->Bytes[3]);
+ }
+ else
+ transparent = -1;
+ }
+#endif
+ }
+
+ if (transparent >= 0 && (unsigned)transparent < frame.m_palette.size())
+ frame.m_palette[transparent].a = 0;
+ return true;
+}
+
+int GifHelper::ExtractFrames(unsigned int count)
+{
+ if (!m_gif)
+ return -1;
+
+ if (!m_pTemplate)
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): No frame template available\n");
+ return -1;
+ }
+
+ int extracted = 0;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ FramePtr frame(new GifFrame);
+ SavedImage savedImage = m_gif->SavedImages[i];
+ GifImageDesc imageDesc = m_gif->SavedImages[i].ImageDesc;
+ frame->m_height = imageDesc.Height;
+ frame->m_width = imageDesc.Width;
+ frame->m_top = imageDesc.Top;
+ frame->m_left = imageDesc.Left;
+
+ if (frame->m_top + frame->m_height > m_height || frame->m_left + frame->m_width > m_width
+ || !frame->m_width || !frame->m_height
+ || frame->m_width > m_width || frame->m_height > m_height)
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Illegal frame dimensions: width: %d, height: %d, left: %d, top: %d instead of (%d,%d), skip it\n",
+ frame->m_width, frame->m_height, frame->m_left, frame->m_top, m_width, m_height);
+ continue;
+ }
+
+ if (imageDesc.ColorMap)
+ {
+ frame->m_palette.clear();
+ ConvertColorTable(frame->m_palette, imageDesc.ColorMap, imageDesc.ColorMap->ColorCount);
+ // TODO save a backup of the palette for frames without a table in case there's no global table.
+ }
+ else if (m_gif->SColorMap)
+ {
+ frame->m_palette = m_globalPalette;
+ }
+ else
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): No color map found for frame %d, skip it\n", i);
+ continue;
+ }
+
+ // fill delay, disposal and transparent color into frame
+ if (!GcbToFrame(*frame, i))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Corrupted Graphics Control Block for frame %d, skip it\n", i);
+ continue;
+ }
+
+ frame->m_pImage = new unsigned char[m_imageSize];
+ frame->m_imageSize = m_imageSize;
+ memcpy(frame->m_pImage, m_pTemplate, m_imageSize);
+
+ ConstructFrame(*frame, savedImage.RasterBits);
+
+ if (!PrepareTemplate(*frame))
+ {
+ fprintf(stderr, "Gif::ExtractFrames(): Could not prepare template after frame %d, skip it\n", i);
+ continue;
+ }
+
+ extracted++;
+ m_frames.push_back(frame);
+ }
+ return extracted;
+}
+
+void GifHelper::ConstructFrame(GifFrame &frame, const unsigned char* src) const
+{
+ size_t paletteSize = frame.m_palette.size();
+
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = frame.m_pImage + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+
+ const unsigned char *from = src + (src_y * frame.m_width);
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ unsigned char index = *from++;
+
+ if (index >= paletteSize)
+ {
+ fprintf(stderr, "Gif::ConstructFrame(): Pixel (%d,%d) has no valid palette entry, skip it\n", src_x, src_y);
+ continue;
+ }
+
+ GifColor col = frame.m_palette[index];
+ if (col.a != 0)
+ memcpy(to, &col, sizeof(GifColor));
+
+ to += 4;
+ }
+ }
+}
+
+bool GifHelper::PrepareTemplate(GifFrame &frame)
+{
+ switch (frame.m_disposal)
+ {
+ /* No disposal specified. */
+ case DISPOSAL_UNSPECIFIED:
+ /* Leave image in place */
+ case DISPOSE_DO_NOT:
+ memcpy(m_pTemplate, frame.m_pImage, m_imageSize);
+ break;
+
+ /*
+ Clear the frame's area to transparency.
+ The disposal names is misleading. Do not restore to the background color because
+ this part of the specification is ignored by all browsers/image viewers.
+ */
+ case DISPOSE_BACKGROUND:
+ {
+ ClearFrameAreaToTransparency(m_pTemplate, frame);
+ break;
+ }
+ /* Restore to previous content */
+ case DISPOSE_PREVIOUS:
+ {
+
+ /*
+ * This disposal method makes no sense for the first frame
+ * Since browsers etc. handle that too, we'll fall back to DISPOSE_DO_NOT
+ */
+ if (m_frames.empty())
+ {
+ frame.m_disposal = DISPOSE_DO_NOT;
+ return PrepareTemplate(frame);
+ }
+
+ bool valid = false;
+
+ for (int i = m_frames.size() - 1; i >= 0; --i)
+ {
+ if (m_frames[i]->m_disposal != DISPOSE_PREVIOUS)
+ {
+ memcpy(m_pTemplate, m_frames[i]->m_pImage, m_imageSize);
+ valid = true;
+ break;
+ }
+ }
+ if (!valid)
+ {
+ fprintf(stderr, "Gif::PrepareTemplate(): Disposal method DISPOSE_PREVIOUS encountered, but could not find a suitable frame.\n");
+ return false;
+ }
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Gif::PrepareTemplate(): Unknown disposal method: %d. Using DISPOSAL_UNSPECIFIED, the animation might be wrong now.\n", frame.m_disposal);
+ frame.m_disposal = DISPOSAL_UNSPECIFIED;
+ return PrepareTemplate(frame);
+ }
+ }
+ return true;
+}
+
+void GifHelper::ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame)
+{
+ for (unsigned int dest_y = frame.m_top, src_y = 0; src_y < frame.m_height; ++dest_y, ++src_y)
+ {
+ unsigned char *to = dest + (dest_y * m_pitch) + (frame.m_left * sizeof(GifColor));
+ for (unsigned int src_x = 0; src_x < frame.m_width; ++src_x)
+ {
+ to += 3;
+ *to++ = 0;
+ }
+ }
+}
+
+GifFrame::GifFrame(const GifFrame& src)
+ : m_delay(src.m_delay),
+ m_top(src.m_top),
+ m_left(src.m_left),
+ m_disposal(src.m_disposal),
+ m_height(src.m_height),
+ m_width(src.m_width),
+ m_imageSize(src.m_imageSize)
+{
+ if (src.m_pImage)
+ {
+ m_pImage = new unsigned char[m_imageSize];
+ memcpy(m_pImage, src.m_pImage, m_imageSize);
+ }
+
+ if (src.m_palette.size())
+ {
+ m_palette = src.m_palette;
+ }
+}
+
+GifFrame::~GifFrame()
+{
+ delete[] m_pImage;
+ m_pImage = nullptr;
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/GifHelper.h b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
new file mode 100644
index 0000000..1e897a7
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/GifHelper.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gif_lib.h>
+#ifndef CONTINUE_EXT_FUNC_CODE
+#define CONTINUE_EXT_FUNC_CODE 0
+#endif
+
+#ifndef DISPOSAL_UNSPECIFIED
+#define DISPOSAL_UNSPECIFIED 0
+#endif
+
+#ifndef DISPOSE_DO_NOT
+#define DISPOSE_DO_NOT 1
+#endif
+
+#ifndef DISPOSE_BACKGROUND
+#define DISPOSE_BACKGROUND 2
+#endif
+
+#ifndef DISPOSE_PREVIOUS
+#define DISPOSE_PREVIOUS 3
+#endif
+
+#include <vector>
+#include <string>
+#include <memory>
+#include "SimpleFS.h"
+
+#pragma pack(1)
+struct GifColor
+{
+ uint8_t b, g, r, a;
+};
+#pragma pack()
+
+class CFile;
+
+class GifFrame
+{
+ friend class GifHelper;
+public:
+
+ GifFrame() = default;
+ virtual ~GifFrame();
+
+ unsigned char* m_pImage = nullptr;
+ unsigned int m_delay = 0;
+
+private:
+ GifFrame(const GifFrame& src);
+
+ unsigned int m_top = 0;
+ unsigned int m_left = 0;
+ unsigned int m_disposal = 0;
+ unsigned int m_height = 0;
+ unsigned int m_width = 0;
+ unsigned int m_imageSize = 0;
+ std::vector<GifColor> m_palette;
+};
+
+
+
+class GifHelper
+{
+ friend class GifFrame;
+
+ typedef std::shared_ptr<GifFrame> FramePtr;
+
+public:
+ GifHelper();
+ virtual ~GifHelper();
+
+
+ bool LoadGif(const char* file);
+
+ std::vector<FramePtr>& GetFrames() { return m_frames; }
+ unsigned int GetPitch() const { return m_pitch; }
+ unsigned int GetNumLoops() const { return m_loops; }
+ unsigned int GetWidth() const { return m_width; }
+ unsigned int GetHeight() const { return m_height; }
+
+private:
+ std::vector<FramePtr> m_frames;
+ unsigned int m_imageSize = 0;
+ unsigned int m_pitch = 0;
+ unsigned int m_loops = 0;
+ unsigned int m_numFrames = 0;
+
+ std::string m_filename;
+ GifFileType* m_gif = nullptr;
+ std::vector<GifColor> m_globalPalette;
+ unsigned char* m_pTemplate = nullptr;
+ CFile* m_gifFile;
+
+ unsigned int m_width;
+ unsigned int m_height;
+
+ bool Open(GifFileType *& gif, void * dataPtr, InputFunc readFunc);
+ void Close(GifFileType * gif);
+
+ const char* Reason(int reason);
+
+ bool LoadGifMetaData(const char* file);
+ bool Slurp(GifFileType* gif);
+ void InitTemplateAndColormap();
+ bool LoadGifMetaData(GifFileType* gif);
+ static void ConvertColorTable(std::vector<GifColor> &dest, ColorMapObject* src, unsigned int size);
+ bool GcbToFrame(GifFrame &frame, unsigned int imgIdx);
+ int ExtractFrames(unsigned int count);
+ void ClearFrameAreaToTransparency(unsigned char* dest, const GifFrame &frame);
+ void ConstructFrame(GifFrame &frame, const unsigned char* src) const;
+ bool PrepareTemplate(GifFrame &frame);
+ void Release();
+
+#if GIFLIB_MAJOR != 5
+ /*
+ taken from giflib 5.1.0
+ */
+ const char* GifErrorString(int ErrorCode)
+ {
+ const char *Err;
+
+ switch (ErrorCode) {
+ case E_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case E_GIF_ERR_WRITE_FAILED:
+ Err = "Failed to write to given file";
+ break;
+ case E_GIF_ERR_HAS_SCRN_DSCR:
+ Err = "Screen descriptor has already been set";
+ break;
+ case E_GIF_ERR_HAS_IMAG_DSCR:
+ Err = "Image descriptor is still active";
+ break;
+ case E_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case E_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case E_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case E_GIF_ERR_DISK_IS_FULL:
+ Err = "Write failed (disk full?)";
+ break;
+ case E_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case E_GIF_ERR_NOT_WRITEABLE:
+ Err = "Given file was not opened for write";
+ break;
+ case D_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case D_GIF_ERR_READ_FAILED:
+ Err = "Failed to read from given file";
+ break;
+ case D_GIF_ERR_NOT_GIF_FILE:
+ Err = "Data is not in GIF format";
+ break;
+ case D_GIF_ERR_NO_SCRN_DSCR:
+ Err = "No screen descriptor detected";
+ break;
+ case D_GIF_ERR_NO_IMAG_DSCR:
+ Err = "No Image Descriptor detected";
+ break;
+ case D_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither global nor local color map";
+ break;
+ case D_GIF_ERR_WRONG_RECORD:
+ Err = "Wrong record type detected";
+ break;
+ case D_GIF_ERR_DATA_TOO_BIG:
+ Err = "Number of pixels bigger than width * height";
+ break;
+ case D_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Failed to allocate required memory";
+ break;
+ case D_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case D_GIF_ERR_NOT_READABLE:
+ Err = "Given file was not opened for read";
+ break;
+ case D_GIF_ERR_IMAGE_DEFECT:
+ Err = "Image is defective, decoding aborted";
+ break;
+ case D_GIF_ERR_EOF_TOO_SOON:
+ Err = "Image EOF detected before image complete";
+ break;
+ default:
+ Err = NULL;
+ break;
+ }
+ return Err;
+ }
+#endif
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
new file mode 100644
index 0000000..673ff1a
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+/* forward declarations */
+
+class DecodedFrame;
+class DecodedFrames;
+
+class IDecoder
+{
+ public:
+ virtual ~IDecoder() = default;
+ virtual bool CanDecode(const std::string &filename) = 0;
+ virtual bool LoadFile(const std::string &filename, DecodedFrames &frames) = 0;
+ virtual void FreeDecodedFrame(DecodedFrame &frame) = 0;
+ virtual const char* GetImageFormatName() = 0;
+ virtual const char* GetDecoderName() = 0;
+
+ const std::vector<std::string>& GetSupportedExtensions()
+ {
+ m_supportedExtensions.clear();
+ FillSupportedExtensions();
+ return m_supportedExtensions;
+ }
+
+ protected:
+ virtual void FillSupportedExtensions() = 0;
+ //fill this with extensions in FillSupportedExtensions like ".png"
+ std::vector<std::string> m_supportedExtensions;
+};
+
+class RGBAImage
+{
+public:
+ RGBAImage() = default;
+
+ char* pixels = nullptr; // image data
+ int width = 0; // width
+ int height = 0; // height
+ int bbp = 0; // bits per pixel
+ int pitch = 0; // rowsize in bytes
+};
+
+class DecodedFrame
+{
+public:
+ DecodedFrame() = default;
+ RGBAImage rgbaImage; /* rgbaimage for this frame */
+ int delay = 0; /* Frame delay in ms */
+ IDecoder* decoder = nullptr; /* Pointer to decoder */
+};
+
+class DecodedFrames
+{
+ public:
+ DecodedFrames() = default;
+ std::vector<DecodedFrame> frameList;
+
+ void clear()
+ {
+ for (auto f : frameList)
+ {
+ if (f.decoder != NULL)
+ {
+ f.decoder->FreeDecodedFrame(f);
+ }
+ else
+ {
+ fprintf(stderr,
+ "ERROR: %s - can not determine decoder type for frame!\n",
+ __FUNCTION__);
+ }
+ }
+ frameList.clear();
+ }
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
new file mode 100644
index 0000000..ce06d28
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "JPGDecoder.h"
+
+#include "SimpleFS.h"
+
+#include <jpeglib.h>
+
+bool JPGDecoder::CanDecode(const std::string &filename)
+{
+ CFile *fp = new CFile();
+ bool ret = false;
+ unsigned char magic[2];
+ if (fp->Open(filename))
+ {
+
+ //JPEG image files begin with FF D8 and end with FF D9.
+ // check for FF D8 big + little endian on start
+ uint64_t readbytes = fp->Read(magic, 2);
+ if (readbytes == 2)
+ {
+ if ((magic[0] == 0xd8 && magic[1] == 0xff) ||
+ (magic[1] == 0xd8 && magic[0] == 0xff))
+ ret = true;
+ }
+
+ if (ret)
+ {
+ ret = false;
+ //check on FF D9 big + little endian on end
+ uint64_t fileSize = fp->GetFileSize();
+ fp->Seek(fileSize - 2);
+ readbytes = fp->Read(magic, 2);
+ if (readbytes == 2)
+ {
+ if ((magic[0] == 0xd9 && magic[1] == 0xff) ||
+ (magic[1] == 0xd9 && magic[0] == 0xff))
+ ret = true;
+ }
+ }
+ }
+ delete fp;
+ return ret;
+}
+
+bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
+ CFile *arq = new CFile();
+ if (!arq->Open(filename))
+ {
+ delete arq;
+ return false;
+ }
+
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ int ImageSize;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ jpeg_stdio_src(&cinfo, arq->getFP());
+ jpeg_read_header(&cinfo, TRUE);
+ jpeg_start_decompress(&cinfo);
+
+ // Image Size is calculated as (width * height * bytes per pixel = 4
+ ImageSize = cinfo.image_width * cinfo.image_height * 4;
+
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)new char[ImageSize];
+
+ unsigned char *scanlinebuff = new unsigned char[3 * cinfo.image_width];
+ unsigned char *dst = (unsigned char *)frame.rgbaImage.pixels;
+ while (cinfo.output_scanline < cinfo.output_height)
+ {
+ jpeg_read_scanlines(&cinfo,&scanlinebuff,1);
+
+ unsigned char *src2 = scanlinebuff;
+ unsigned char *dst2 = dst;
+ for (unsigned int x = 0; x < cinfo.image_width; x++, src2 += 3)
+ {
+ *dst2++ = src2[2];
+ *dst2++ = src2[1];
+ *dst2++ = src2[0];
+ *dst2++ = 0xff;
+ }
+ dst += cinfo.image_width * 4;
+ }
+ delete [] scanlinebuff;
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ frame.rgbaImage.height = cinfo.image_height;
+ frame.rgbaImage.width = cinfo.image_width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = 4 * cinfo.image_width;
+
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+
+ delete arq;
+ return true;
+}
+
+void JPGDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void JPGDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".jpg");
+ m_supportedExtensions.emplace_back(".jpeg");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h
new file mode 100644
index 0000000..bbf23ba
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/JPGDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class JPGDecoder : public IDecoder
+{
+ public:
+ ~JPGDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "JPG"; }
+ const char* GetDecoderName() override { return "libjpeg"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp
new file mode 100644
index 0000000..f327400
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "PNGDecoder.h"
+
+#include "SimpleFS.h"
+
+#include <png.h>
+
+#ifndef png_jmpbuf
+# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
+ * returns zero if the image is a PNG and nonzero if it isn't a PNG.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, 0 (false) otherwise.
+ *
+ * If this call is successful, and you are going to keep the file open,
+ * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
+ * you have created the png_ptr, so that libpng knows your application
+ * has read that many bytes from the start of the file. Make sure you
+ * don't call png_set_sig_bytes() with more than 8 bytes read or give it
+ * an incorrect number of bytes read, or you will either have read too
+ * many bytes (your fault), or you are telling libpng to read the wrong
+ * number of magic bytes (also your fault).
+ *
+ * Many applications already read the first 2 or 4 bytes from the start
+ * of the image to determine the file type, so it would be easiest just
+ * to pass the bytes to png_sig_cmp() or even skip that if you know
+ * you have a PNG file, and call png_set_sig_bytes().
+ */
+bool PNGDecoder::CanDecode(const std::string &filename)
+{
+ #define PNG_BYTES_TO_CHECK 4
+ CFile fp;
+ char buf[PNG_BYTES_TO_CHECK];
+
+ /* Open the prospective PNG file. */
+ if (!fp.Open(filename))
+ return false;
+
+ /* Read in some of the signature bytes */
+ if (fp.Read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK)
+ {
+ fprintf(stderr, "error reading header ...\n");
+ return false;
+ }
+ fp.Close();
+
+ /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+ Return nonzero (true) if they match */
+ return(!png_sig_cmp((png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
+}
+
+bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
+{
+ png_byte header[8];
+
+ CFile fp;
+ if (!fp.Open(filename))
+ {
+ perror(filename.c_str());
+ return false;
+ }
+
+ // read the header
+ fp.Read(header, 8);
+
+ if (png_sig_cmp(header, 0, 8))
+ {
+ fprintf(stderr, "error: %s is not a PNG.\n", filename.c_str());
+ return false;
+ }
+
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ fprintf(stderr, "error: png_create_read_struct returned 0.\n");
+ return false;
+ }
+
+ // create png info struct
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ fprintf(stderr, "error: png_create_info_struct returned 0.\n");
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return false;
+ }
+
+ // create png info struct
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ fprintf(stderr, "error: png_create_info_struct returned 0.\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+ return false;
+ }
+
+ // the code in this if statement gets called if libpng encounters an error
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fprintf(stderr, "error from libpng\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return false;
+ }
+
+ // init png reading
+ png_init_io(png_ptr, fp.getFP());
+
+ // let libpng know you already read the first 8 bytes
+ png_set_sig_bytes(png_ptr, 8);
+
+ // read all the info up to the image data
+ png_read_info(png_ptr, info_ptr);
+
+ // variables to pass to get info
+ int bit_depth, color_type;
+ png_uint_32 temp_width, temp_height;
+
+ // get info about png
+ png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type,
+ NULL, NULL, NULL);
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ {
+ png_set_tRNS_to_alpha(png_ptr);
+ }
+
+ //set it to 32bit pixeldepth
+ png_color_8 sig_bit;
+ sig_bit.red = 32;
+ sig_bit.green = 32;
+ sig_bit.blue = 32;
+ // if the image has an alpha channel then
+ sig_bit.alpha = 32;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+
+ /* Add filler (or alpha) byte (before/after each RGB triplet) */
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_bgr(png_ptr);
+
+ // convert indexed color to rgb
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+ //png_set_swap_alpha(png_ptr);
+
+ //libsquish only eats 32bit RGBA, must convert grayscale into this format
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ png_set_gray_to_rgb(png_ptr);
+ }
+
+ // Update the png info struct.
+ png_read_update_info(png_ptr, info_ptr);
+
+ // Row size in bytes.
+ int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ // glTexImage2d requires rows to be 4-byte aligned
+ // rowbytes += 3 - ((rowbytes-1) % 4);
+
+ // Allocate the image_data as a big block, to be given to opengl
+ png_byte * image_data;
+ image_data = (png_byte*)new png_byte[rowbytes * temp_height * sizeof(png_byte)+15];
+ if (image_data == NULL)
+ {
+ fprintf(stderr, "error: could not allocate memory for PNG image data\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ return false;
+ }
+
+ // row_pointers is for pointing to image_data for reading the png with libpng
+ png_bytep * row_pointers = (png_bytep*) new png_bytep[temp_height * sizeof(png_bytep)];
+ if (row_pointers == NULL)
+ {
+ fprintf(stderr, "error: could not allocate memory for PNG row pointers\n");
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ delete [] image_data;
+ return false;
+ }
+
+ // set the individual row_pointers to point at the correct offsets of image_data
+ for (unsigned int i = 0; i < temp_height; i++)
+ {
+ row_pointers[i] = image_data + i * rowbytes;
+ }
+
+ // read the png into image_data through row_pointers
+ png_read_image(png_ptr, row_pointers);
+
+ DecodedFrame frame;
+
+ frame.rgbaImage.pixels = (char *)image_data;
+ frame.rgbaImage.height = temp_height;
+ frame.rgbaImage.width = temp_width;
+ frame.rgbaImage.bbp = 32;
+ frame.rgbaImage.pitch = 4 * temp_width;
+
+ frame.decoder = this;
+
+ frames.frameList.push_back(frame);
+ // clean up
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ delete [] row_pointers;
+ return true;
+}
+
+void PNGDecoder::FreeDecodedFrame(DecodedFrame &frame)
+{
+ delete [] frame.rgbaImage.pixels;
+}
+
+void PNGDecoder::FillSupportedExtensions()
+{
+ m_supportedExtensions.emplace_back(".png");
+}
diff --git a/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h
new file mode 100644
index 0000000..c7dba76
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/decoder/PNGDecoder.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 Team Kodi
+ * http://kodi.tv
+ *
+ * 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, or (at your option)
+ * 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include "IDecoder.h"
+
+class PNGDecoder : public IDecoder
+{
+ public:
+ ~PNGDecoder() override = default;
+ bool CanDecode(const std::string &filename) override;
+ bool LoadFile(const std::string &filename, DecodedFrames &frames) override;
+ void FreeDecodedFrame(DecodedFrame &frame) override;
+ const char* GetImageFormatName() override { return "PNG"; }
+ const char* GetDecoderName() override { return "libpng"; }
+ protected:
+ void FillSupportedExtensions() override;
+};
diff --git a/tools/depends/native/TexturePacker/src/md5.cpp b/tools/depends/native/TexturePacker/src/md5.cpp
new file mode 100644
index 0000000..b9788dd
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/md5.cpp
@@ -0,0 +1,231 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions; now uses stuff from dpkg's config.h.
+ * - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#include "md5.h"
+
+
+#ifdef WORDS_BIGENDIAN
+void
+byteSwap(uint32_t *buf, unsigned words)
+{
+ uint8_t *p = (uint8_t*)buf;
+
+ do {
+ *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+ ((unsigned)p[1] << 8 | p[0]);
+ p += 4;
+ } while (--words);
+}
+#else
+#define byteSwap(buf,words)
+#endif
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(uint32_t buf[4], uint32_t const in[16])
+{
+ uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, const uint8_t *buf, unsigned len)
+{
+ uint32_t t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len) {
+ memcpy((uint8_t*)ctx->in + 64 - t, buf, len);
+ return;
+ }
+ /* First chunk is an odd size */
+ memcpy((uint8_t*)ctx->in + 64 - t, buf, t);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(uint8_t digest[16], struct MD5Context *ctx)
+{
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ uint8_t *p = (uint8_t*)ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0) { /* Padding forces an extra block */
+ memset(p, 0, count + 8);
+ byteSwap(ctx->in, 16);
+ MD5Transform(ctx->buf, ctx->in);
+ p = (uint8_t*)ctx->in;
+ count = 56;
+ }
+ memset(p, 0, count);
+ byteSwap(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ MD5Transform(ctx->buf, ctx->in);
+
+ byteSwap(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
diff --git a/tools/depends/native/TexturePacker/src/md5.h b/tools/depends/native/TexturePacker/src/md5.h
new file mode 100644
index 0000000..76475bc
--- /dev/null
+++ b/tools/depends/native/TexturePacker/src/md5.h
@@ -0,0 +1,38 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions; now uses stuff from dpkg's config.h.
+ * - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstring> /* for memcpy() */
+
+struct MD5Context
+{
+ uint32_t buf[4];
+ uint32_t bytes[2];
+ uint32_t in[16];
+};
+
+void MD5Init(struct MD5Context *ctx);
+void MD5Update(struct MD5Context *ctx, const uint8_t *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
+