add func to path manager. fix bitmap handler. add general bitmap handler getter

This commit is contained in:
yyc12345 2023-09-07 21:57:48 +08:00
parent f7f1478ecf
commit 54a3dd7776
11 changed files with 264 additions and 66 deletions

View File

@ -21,11 +21,14 @@ namespace LibCmo::CK2 {
m_FileWriteMode(CK_FILE_WRITEMODE::CKFILE_UNCOMPRESSED),
m_GlobalImagesSaveOptions(CK_TEXTURE_SAVEOPTIONS::CKTEXTURE_RAWDATA),
m_GlobalSoundsSaveOptions(CK_SOUND_SAVEOPTIONS::CKSOUND_EXTERNAL),
m_GlobalImagesSaveFormat(nullptr), // todo: setup save format
m_GlobalImagesSaveFormat(),
// misc init
m_NameEncoding(),
m_OutputCallback(nullptr) {
// setup save format
m_GlobalImagesSaveFormat.m_Ext.SetExt("bmp");
// setup managers
m_ObjectManager = new MgrImpls::CKObjectManager(this);
m_ManagerList.emplace_back(m_ObjectManager);
@ -225,12 +228,12 @@ namespace LibCmo::CK2 {
}
}
const CKBitmapProperties* CKContext::GetGlobalImagesSaveFormat() {
const CKBitmapProperties& CKContext::GetGlobalImagesSaveFormat() {
return m_GlobalImagesSaveFormat;
}
void CKContext::SetGlobalImagesSaveFormat(const CKBitmapProperties* Format) {
// todo: copy CKBitmapProperties
void CKContext::SetGlobalImagesSaveFormat(const CKBitmapProperties& Format) {
m_GlobalImagesSaveFormat = Format;
}
CK_SOUND_SAVEOPTIONS CKContext::GetGlobalSoundsSaveOptions() {

View File

@ -85,8 +85,8 @@ namespace LibCmo::CK2 {
CK_TEXTURE_SAVEOPTIONS GetGlobalImagesSaveOptions();
void SetGlobalImagesSaveOptions(CK_TEXTURE_SAVEOPTIONS Options);
const CKBitmapProperties* GetGlobalImagesSaveFormat();
void SetGlobalImagesSaveFormat(const CKBitmapProperties* Format);
const CKBitmapProperties& GetGlobalImagesSaveFormat();
void SetGlobalImagesSaveFormat(const CKBitmapProperties& Format);
CK_SOUND_SAVEOPTIONS GetGlobalSoundsSaveOptions();
void SetGlobalSoundsSaveOptions(CK_SOUND_SAVEOPTIONS Options);
@ -96,7 +96,7 @@ namespace LibCmo::CK2 {
CK_FILE_WRITEMODE m_FileWriteMode;
CK_TEXTURE_SAVEOPTIONS m_GlobalImagesSaveOptions;
CK_SOUND_SAVEOPTIONS m_GlobalSoundsSaveOptions;
CKBitmapProperties* m_GlobalImagesSaveFormat;
CKBitmapProperties m_GlobalImagesSaveFormat;
// ========== Encoding utilities ==========
public:

View File

@ -78,6 +78,32 @@ namespace LibCmo::CK2 {
}
}
bool CKStrEqualI(CKSTRING str1, CKSTRING str2) {
if (str1 == nullptr) {
if (str2 == nullptr) return true;
else return false;
} else {
if (str2 == nullptr) return false;
else {
// do real cmp
size_t i = 0;
while (str1[i] != '\0' && str2[i] != '\0') {
if (std::tolower(str1[i]) != std::tolower(str2[i])) return false;
++str1;
++str2;
}
// !XOR the result, if both of them is zero, return true(1)
return !((str1[i] != '\0') ^ (str2[i] != '\0'));
}
}
}
bool CKStrEmpty(CKSTRING strl) {
if (strl == nullptr) return true;
return strl[0] == '\0';
}
#pragma endregion
#pragma region CKClass Registration

View File

@ -47,7 +47,28 @@ namespace LibCmo::CK2 {
// ========== String Utilities ==========
/**
* @brief Check whether 2 string is equal. Case senstive.
* @param str1[in] String 1
* @param str2[in] String 2
* @return True if 2 string is equal.
* @see CKStrIEqual
*/
bool CKStrEqual(CKSTRING str1, CKSTRING str2);
/**
* @brief Check whther 2 string is equal. Case insenstive.
* @param str1
* @param str2
* @return True if 2 string is equal.
* @see CKStrEqual
*/
bool CKStrEqualI(CKSTRING str1, CKSTRING str2);
/**
* @brief Check whether string is empty
* @param strl
* @return True if string is empty.
*/
bool CKStrEmpty(CKSTRING strl);
// ========== Numberic Utilities ==========

View File

@ -366,6 +366,55 @@ namespace LibCmo::CK2 {
}
};
/**
* @brief Storage class for filename extensions
*/
class CKFileExtension {
public:
CKFileExtension() : m_Data() {
std::memset(m_Data, 0, c_DataLen);
}
CKFileExtension(CKSTRING s) : CKFileExtension() {
SetExt(s);
}
CKFileExtension(const CKFileExtension& rhs) : CKFileExtension() {
std::memcpy(m_Data, rhs.m_Data, c_DataLen);
}
CKFileExtension(CKFileExtension&& rhs) : CKFileExtension() {
std::memmove(m_Data, rhs.m_Data, c_DataLen);
std::memset(rhs.m_Data, 0, c_DataLen);
}
CKFileExtension& operator=(const CKFileExtension& rhs) {
std::memcpy(m_Data, rhs.m_Data, c_DataLen);
}
CKFileExtension& operator=(CKFileExtension&& rhs) {
std::memmove(m_Data, rhs.m_Data, c_DataLen);
std::memset(rhs.m_Data, 0, c_DataLen);
}
void SetExt(CKSTRING s) {
if (s == nullptr) {
m_Data[0] = '\0';
} else {
if (s[0] == '.') ++s; // skip dot
size_t len = std::strlen(s);
if (len > (c_DataLen - 1)) len = c_DataLen - 1;
std::memcpy(m_Data, s, len);
}
}
CKSTRING GetExt() const {
return m_Data;
}
bool operator==(const CKFileExtension& rhs) const {
return CKStrEqualI(m_Data, rhs.m_Data);
}
protected:
static const size_t c_DataLen = 4u;
CKCHAR m_Data[c_DataLen];
};
/**
* The struct describe the bitmap handler's infomation,
@ -374,32 +423,16 @@ namespace LibCmo::CK2 {
* such as jpeg compress level and etc. But currently there are no
* such parameters.
*/
struct CKBitmapProperties {
class CKBitmapProperties {
public:
CKBitmapProperties() :
m_ReaderGuid(), m_Ext(3, '\0') {}
CKBitmapProperties(CKGUID& guid, const char* ext) :
m_ReaderGuid(guid), m_Ext(3, '\0') {
SetExt(ext);
}
m_ReaderGuid(), m_Ext() {}
CKBitmapProperties(const CKGUID& guid, CKSTRING ext) :
m_ReaderGuid(guid), m_Ext(ext) {}
LIBCMO_DEFAULT_COPY_MOVE(CKBitmapProperties);
void SetExt(const char* s) {
if (s == nullptr) {
m_Ext[0] = '\0';
} else {
if (s[0] == '.') ++s; // skip dot
size_t len = std::strlen(s);
if (len > m_Ext.size()) len = m_Ext.size();
std::memcpy(m_Ext.data(), s, len);
}
}
CKSTRING ExtToCKSTRING() {
return m_Ext.c_str();
}
CKGUID m_ReaderGuid; /**< CKGUID that uniquely identifies the reader that created this properties structure */
std::string m_Ext; /**< File Extension of the image being described by this structure */
CKFileExtension m_Ext; /**< File Extension of the image being described by this structure */
};

View File

@ -5,6 +5,8 @@
namespace LibCmo::CK2::DataHandlers {
#pragma region Help Functions
static void RGBAToARGB(CK2::CKDWORD count, const void* _rgba, void* _argb) {
const char* rgba = reinterpret_cast<const char*>(_rgba);
char* argb = reinterpret_cast<char*>(_argb);
@ -66,12 +68,12 @@ namespace LibCmo::CK2::DataHandlers {
STBIR_COLORSPACE_SRGB, nullptr
);
// copy data
RGBAToARGB(read_image->GetPixelCount(), newdata, read_image->GetImage());
RGBAToARGB(read_image->GetPixelCount(), newdata, read_image->GetMutableImage());
// free
delete[] newdata;
} else {
// copy data RGBA -> ARGB
RGBAToARGB(read_image->GetPixelCount(), data, read_image->GetImage());
RGBAToARGB(read_image->GetPixelCount(), data, read_image->GetMutableImage());
}
}
static bool StbReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) {
@ -145,18 +147,17 @@ namespace LibCmo::CK2::DataHandlers {
static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, SaveOperation oper) {
if (u8filename == nullptr || write_image == nullptr) return false;
FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb");
if (fs == nullptr) return;
if (fs == nullptr) return false;
// allocate buffer and convert data from ARGB to RGBA
VxMath::VxImageDescEx* wi = const_cast<VxMath::VxImageDescEx*>(write_image);
CKBYTE* data = new CKBYTE[write_image->GetImageSize()];
ARGBToRGBA(write_image->GetPixelCount(), wi->GetImage(), data);
ARGBToRGBA(write_image->GetPixelCount(), write_image->GetImage(), data);
// write data
FileSaveContext* ctx = new FileSaveContext(fs);
int ret = oper(
&FileWriteFunction, ctx,
static_cast<int>(wi->GetWidth()), static_cast<int>(wi->GetHeight()),
static_cast<int>(write_image->GetWidth()), static_cast<int>(write_image->GetHeight()),
4, data // 4 == RGBA8888
);
@ -171,15 +172,14 @@ namespace LibCmo::CK2::DataHandlers {
if (write_image == nullptr) return 0;
// allocate buffer and convert data from ARGB to RGBA
VxMath::VxImageDescEx* wi = const_cast<VxMath::VxImageDescEx*>(write_image);
CKBYTE* data = new CKBYTE[write_image->GetImageSize()];
ARGBToRGBA(write_image->GetPixelCount(), wi->GetImage(), data);
ARGBToRGBA(write_image->GetPixelCount(), write_image->GetImage(), data);
// write data
MemorySaveContext* ctx = new MemorySaveContext(memory);
int ret = oper(
&FileWriteFunction, ctx,
static_cast<int>(wi->GetWidth()), static_cast<int>(wi->GetHeight()),
static_cast<int>(write_image->GetWidth()), static_cast<int>(write_image->GetHeight()),
4, data // 4 == RGBA8888
);
@ -191,20 +191,20 @@ namespace LibCmo::CK2::DataHandlers {
if (ret == 0) return 0;
else return expected;
}
#pragma endregion
#pragma region CKBitmapBMPHandler
static const CKBitmapProperties g_BMPProperties(CKGUID(0xBCA97223u, 0x48578BCAu), "Bmp");
CKBitmapBMPHandler::CKBitmapBMPHandler() :
CKBitmapHandler(), c_DefaultProp() {
c_DefaultProp.SetExt("Tga");
c_DefaultProp.m_ReaderGuid.d1 = 0xBCA97223u;
c_DefaultProp.m_ReaderGuid.d2 = 0x48578BCAu;
}
CKBitmapHandler() {}
CKBitmapBMPHandler::~CKBitmapBMPHandler() {}
const CKBitmapProperties& CKBitmapBMPHandler::GetBitmapDefaultProperties() {
return c_DefaultProp;
return g_BMPProperties;
}
bool CKBitmapBMPHandler::ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) {
@ -232,18 +232,16 @@ namespace LibCmo::CK2::DataHandlers {
#pragma endregion
#pragma region CKBitmapTGAHandler
static const CKBitmapProperties g_TGAProperties(CKGUID(0x585C7216u, 0x33302657u), "Tga");
CKBitmapTGAHandler::CKBitmapTGAHandler() :
CKBitmapHandler(), c_DefaultProp() {
c_DefaultProp.SetExt("Tga");
c_DefaultProp.m_ReaderGuid.d1 = 0x585C7216u;
c_DefaultProp.m_ReaderGuid.d2 = 0x33302657u;
}
CKBitmapHandler() {}
CKBitmapTGAHandler::~CKBitmapTGAHandler() {}
const CKBitmapProperties& CKBitmapTGAHandler::GetBitmapDefaultProperties() {
return c_DefaultProp;
return g_TGAProperties;
}
bool CKBitmapTGAHandler::ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) {
@ -257,18 +255,51 @@ namespace LibCmo::CK2::DataHandlers {
bool CKBitmapTGAHandler::SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) {
return StbSaveFile(u8filename, write_image,
[&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int {
return stbi_write_bmp_to_func(func, context, w, h, comp, data);
return stbi_write_tga_to_func(func, context, w, h, comp, data);
});
}
CKDWORD CKBitmapTGAHandler::SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) {
return StbSaveMemory(memory, write_image,
[&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int {
return stbi_write_bmp_to_func(func, context, w, h, comp, data);
return stbi_write_tga_to_func(func, context, w, h, comp, data);
});
}
#pragma endregion
#pragma region General Getter Freer
static CKBitmapHandler* FindHandlerByExt(const CKFileExtension& ext) {
if (ext == g_BMPProperties.m_Ext) return new CKBitmapBMPHandler();
if (ext == g_TGAProperties.m_Ext) return new CKBitmapTGAHandler();
return nullptr;
}
static CKBitmapHandler* FindHandlerByGuid(const CKGUID& guid) {
if (guid == g_BMPProperties.m_ReaderGuid) return new CKBitmapBMPHandler();
if (guid == g_TGAProperties.m_ReaderGuid) return new CKBitmapTGAHandler();
return nullptr;
}
CKBitmapHandler* CKBitmapHandler::GetBitmapHandler(const CKFileExtension& ext, const CKGUID& guid) {
CKBitmapHandler* handler = nullptr;
// check ext first
handler = FindHandlerByExt(ext);
if (handler != nullptr) return handler;
// check guid
handler = FindHandlerByGuid(guid);
if (handler != nullptr) return handler;
return nullptr;
}
void CKBitmapHandler::ReleaseBitmapHandler(CKBitmapHandler* handler) {
if (handler != nullptr) delete handler;
}
#pragma endregion
}

View File

@ -15,6 +15,22 @@ namespace LibCmo::CK2::DataHandlers {
virtual ~CKBitmapHandler() {}
LIBCMO_DISABLE_COPY_MOVE(CKBitmapHandler);
/**
* @brief General CKBitmapHandler getter.
* @param ext[in] The file extention help finding corresponding bitmap handler.
* @param guid[in] The GUID of bitmap handler used in fall back finding.
* @remark
* + Returns a reader capable of reading file with the given extension ext
* + It may be several plugins that support the same extension, in which case a preferedGUID identifying the reader that should be returned can be given (optionnal).
* @return The pointer to CKBitmapHandler. nullptr if fail to find.
*/
static CKBitmapHandler* GetBitmapHandler(const CKFileExtension& ext, const CKGUID& guid);
/**
* @brief General CKBitmapHandler disposer
* @param handler[in] The handler need to be free.
*/
static void ReleaseBitmapHandler(CKBitmapHandler* handler);
/**
* @brief Returns the current default bitmap options.
* @return Current default bitmap options
@ -75,8 +91,6 @@ namespace LibCmo::CK2::DataHandlers {
virtual bool SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override;
virtual CKDWORD SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override;
protected:
CKBitmapProperties c_DefaultProp;
};
class CKBitmapTGAHandler : public CKBitmapHandler {
@ -91,8 +105,6 @@ namespace LibCmo::CK2::DataHandlers {
virtual bool SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override;
virtual CKDWORD SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override;
protected:
CKBitmapProperties c_DefaultProp;
};
}

View File

@ -10,7 +10,7 @@ namespace LibCmo::CK2::MgrImpls {
CKPathManager::CKPathManager(CKContext* ctx) :
CKBaseManager(ctx, PATH_MANAGER_GUID, "Path Manager"),
m_TempFolder() {
m_TempFolder(), m_ExtraPathes() {
// preset for temp folder
// todo: add current CKContext pointer as the part of temp path.
// thus multiple CKContext can work.
@ -21,8 +21,15 @@ namespace LibCmo::CK2::MgrImpls {
}
CKPathManager::~CKPathManager() {}
void CKPathManager::SetTempFolder(CKSTRING u8_temp) {
EncodingHelper::U8PathToStdPath(this->m_TempFolder, u8_temp);
bool CKPathManager::SetTempFolder(CKSTRING u8_temp) {
std::filesystem::path cache;
EncodingHelper::U8PathToStdPath(cache, u8_temp);
if (std::filesystem::is_directory(cache)) {
m_TempFolder = cache;
return true;
} else {
return false;
}
}
std::string CKPathManager::GetTempFolder() {
@ -41,8 +48,49 @@ namespace LibCmo::CK2::MgrImpls {
return result;
}
bool CKPathManager::AddPath(CKSTRING u8path) {
if (u8path == nullptr) return;
std::filesystem::path newpath;
EncodingHelper::U8PathToStdPath(newpath, u8path);
if (std::filesystem::is_directory(newpath)) {
m_ExtraPathes.emplace_back(std::move(newpath));
return true;
} else {
return false;
}
}
void CKPathManager::ClearPath() {
m_ExtraPathes.clear();
}
bool CKPathManager::ResolveFileName(std::string& u8_filename) {
// todo: finish resolve file name
std::filesystem::path filepath;
EncodingHelper::U8PathToStdPath(filepath, u8_filename.c_str());
// if it is absolute path, return it directly
if (filepath.is_absolute()) {
return true;
}
// otherwise check it in extra path
for (const auto& extrapath : m_ExtraPathes) {
auto combinedpath = extrapath / filepath;
if (std::filesystem::is_regular_file(combinedpath)) {
// this is correct
EncodingHelper::StdPathToU8Path(u8_filename, combinedpath);
return true;
}
}
// test in temp folder
auto tempfile = m_TempFolder / filepath;
if (std::filesystem::is_regular_file(tempfile)) {
EncodingHelper::StdPathToU8Path(u8_filename, combinedpath);
return true;
}
// failed
return false;
}

View File

@ -14,9 +14,10 @@ namespace LibCmo::CK2::MgrImpls {
/**
* @brief Set the temp folder of current context.
* @param u8_temp
* @param u8_temp The temp folder you need to assign
* @return true if success.
*/
void SetTempFolder(CKSTRING u8_temp);
bool SetTempFolder(CKSTRING u8_temp);
/**
* @brief Get current temp folder.
* @return
@ -29,15 +30,32 @@ namespace LibCmo::CK2::MgrImpls {
*/
std::string GetTempFilePath(CKSTRING u8_filename);
/**
* @brief Add extra path for ResolveFileName
* @param u8path The added path.
* @return true if success.
*/
bool AddPath(CKSTRING u8path);
/**
* @brief Clear all extra path.
*/
void ClearPath();
/**
* @brief Finds a file in the paths
* @param u8_filename[inout] The given file path. overwritten by the final path if success.
* @remark
* We match file in following order.
* + Whether given file is absolute path. return if true.
* + User provided extra path.
* + Virtools temp folder.
* @return true if success
*/
bool ResolveFileName(std::string& u8_filename);
protected:
std::filesystem::path m_TempFolder;
XContainer::XArray<std::filesystem::path> m_ExtraPathes;
};
}

View File

@ -57,7 +57,7 @@ namespace LibCmo::VxMath {
void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE AlphaValue) {
if (dst_desc == nullptr) return;
CK2::CKDWORD* pixels = dst_desc->GetPixels();
CK2::CKDWORD* pixels = dst_desc->GetMutablePixels();
CK2::CKDWORD pixelcount = dst_desc->GetPixelCount();
for (CK2::CKDWORD i = 0; i < pixelcount; ++i) {
@ -81,7 +81,7 @@ namespace LibCmo::VxMath {
void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE* AlphaValues) {
if (dst_desc == nullptr) return;
CK2::CKDWORD* pixels = dst_desc->GetPixels();
CK2::CKDWORD* pixels = dst_desc->GetMutablePixels();
CK2::CKDWORD pixelcount = dst_desc->GetPixelCount();
for (CK2::CKDWORD i = 0; i < pixelcount; ++i) {

View File

@ -92,14 +92,20 @@ namespace LibCmo::VxMath {
CK2::CKDWORD GetImageSize() const {
return static_cast<CK2::CKDWORD>(sizeof(uint32_t) * m_Width * m_Height);
}
CK2::CKBYTE* GetImage() {
const CK2::CKBYTE* GetImage() const {
return m_Image;
}
CK2::CKBYTE* GetMutableImage() {
return m_Image;
}
CK2::CKDWORD GetPixelCount() const {
return static_cast<CK2::CKDWORD>(m_Width * m_Height);
}
CK2::CKDWORD* GetPixels() {
const CK2::CKDWORD* GetPixels() const {
return reinterpret_cast<CK2::CKDWORD*>(m_Image);
}
CK2::CKDWORD* GetMutablePixels() {
return reinterpret_cast<CK2::CKDWORD*>(m_Image);
}