Rev 11 | Blame | Last modification | View Log | RSS feed
/*
* Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
*
* 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 3 of the License, 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 this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <include/core/SkBitmap.h>
#include <include/core/SkData.h>
#include <include/core/SkImage.h>
#include <include/core/SkImageGenerator.h>
#include <include/core/SkStream.h>
#include <include/core/SkTypeface.h>
#include <iconv.h>
#include "tresources.h"
#include "terror.h"
#include "tconfig.h"
sk_sp<SkData> (*gResourceFactory)(const char*) = nullptr;
using std::string;
using std::endl;
using std::vector;
typedef struct
{
unsigned char ch;
short byte;
}CHTABLE;
static CHTABLE __cht[] = {
{0x80, 0x20AC},
{0x81, 0x0081},
{0x82, 0x201A},
{0x83, 0x0192},
{0x84, 0x201E},
{0x85, 0x2026},
{0x86, 0x2020},
{0x87, 0x2021},
{0x88, 0x02C6},
{0x89, 0x2030},
{0x8A, 0x0160},
{0x8B, 0x2039},
{0x8C, 0x0152},
{0x8D, 0x008d},
{0x8E, 0x017D},
{0x8F, 0x008f},
{0x90, 0x0090},
{0x91, 0x2018},
{0x92, 0x2019},
{0x93, 0x201C},
{0x94, 0x201D},
{0x95, 0x2022},
{0x96, 0x2013},
{0x97, 0x2014},
{0x98, 0x02DC},
{0x99, 0x2122},
{0x9A, 0x0161},
{0x9B, 0x203A},
{0x9C, 0x0153},
{0x9D, 0x009d},
{0x9E, 0x017E},
{0x9F, 0x0178},
{0xA0, 0x00A0},
{0xA1, 0x00A1},
{0xA2, 0x00A2},
{0xA3, 0x00A3},
{0xA4, 0x00A4},
{0xA5, 0x00A5},
{0xA6, 0x00A6},
{0xA7, 0x00A7},
{0xA8, 0x00A8},
{0xA9, 0x00A9},
{0xAA, 0x00AA},
{0xAB, 0x00AB},
{0xAC, 0x00AC},
{0xAD, 0x00AD},
{0xAE, 0x00AE},
{0xAF, 0x00AF},
{0xB0, 0x00B0},
{0xB1, 0x00B1},
{0xB2, 0x00B2},
{0xB3, 0x00B3},
{0xB4, 0x00B4},
{0xB5, 0x00B5},
{0xB6, 0x00B6},
{0xB7, 0x00B7},
{0xB8, 0x00B8},
{0xB9, 0x00B9},
{0xBA, 0x00BA},
{0xBB, 0x00BB},
{0xBC, 0x00BC},
{0xBD, 0x00BD},
{0xBE, 0x00BE},
{0xBF, 0x00BF},
{0xC0, 0x00C0},
{0xC1, 0x00C1},
{0xC2, 0x00C2},
{0xC3, 0x00C3},
{0xC4, 0x00C4},
{0xC5, 0x00C5},
{0xC6, 0x00C6},
{0xC7, 0x00C7},
{0xC8, 0x00C8},
{0xC9, 0x00C9},
{0xCA, 0x00CA},
{0xCB, 0x00CB},
{0xCC, 0x00CC},
{0xCD, 0x00CD},
{0xCE, 0x00CE},
{0xCF, 0x00CF},
{0xD0, 0x00D0},
{0xD1, 0x00D1},
{0xD2, 0x00D2},
{0xD3, 0x00D3},
{0xD4, 0x00D4},
{0xD5, 0x00D5},
{0xD6, 0x00D6},
{0xD7, 0x00D7},
{0xD8, 0x00D8},
{0xD9, 0x00D9},
{0xDA, 0x00DA},
{0xDB, 0x00DB},
{0xDC, 0x00DC},
{0xDD, 0x00DD},
{0xDE, 0x00DE},
{0xDF, 0x00DF},
{0xE0, 0x00E0},
{0xE1, 0x00E1},
{0xE2, 0x00E2},
{0xE3, 0x00E3},
{0xE4, 0x00E4},
{0xE5, 0x00E5},
{0xE6, 0x00E6},
{0xE7, 0x00E7},
{0xE8, 0x00E8},
{0xE9, 0x00E9},
{0xEA, 0x00EA},
{0xEB, 0x00EB},
{0xEC, 0x00EC},
{0xED, 0x00ED},
{0xEE, 0x00EE},
{0xEF, 0x00EF},
{0xF0, 0x00F0},
{0xF1, 0x00F1},
{0xF2, 0x00F2},
{0xF3, 0x00F3},
{0xF4, 0x00F4},
{0xF5, 0x00F5},
{0xF6, 0x00F6},
{0xF7, 0x00F7},
{0xF8, 0x00F8},
{0xF9, 0x00F9},
{0xFA, 0x00FA},
{0xFB, 0x00FB},
{0xFC, 0x00FC},
{0xFD, 0x00FD},
{0xFE, 0x00FE},
{0xFF, 0x00FF}
};
SkString GetResourcePath(const char* resource)
{
string path = TConfig::getProjectPath() + "/images/" + resource;
return SkString(path);
}
bool DecodeDataToBitmap(sk_sp<SkData> data, SkBitmap* dst)
{
std::unique_ptr<SkImageGenerator> gen(SkImageGenerator::MakeFromEncoded(std::move(data)));
return gen && dst->tryAllocPixels(gen->getInfo()) &&
gen->getPixels(gen->getInfo().makeColorSpace(nullptr), dst->getPixels(), dst->rowBytes());
}
std::unique_ptr<SkStreamAsset> GetResourceAsStream(const char* resource)
{
sk_sp<SkData> data = GetResourceAsData(resource);
return data ? std::unique_ptr<SkStreamAsset>(new SkMemoryStream(std::move(data)))
: nullptr;
}
sk_sp<SkData> GetResourceAsData(const char* resource)
{
if (sk_sp<SkData> data = gResourceFactory ? gResourceFactory(resource) : SkData::MakeFromFileName(GetResourcePath(resource).c_str()))
{
return data;
}
MSG_ERROR("GetResourceAsData: Resource \"" << GetResourcePath(resource).c_str() << "\" not found." << endl);
TError::setError();
#ifdef SK_TOOLS_REQUIRE_RESOURCES
SK_ABORT("GetResourceAsData: missing resource");
#endif
return nullptr;
}
sk_sp<SkTypeface> MakeResourceAsTypeface(const char* resource, int ttcIndex)
{
return SkTypeface::MakeFromStream(GetResourceAsStream(resource), ttcIndex);
}
/*
* Read the image from a file and save it into a data buffer. This is the base
* to convert the image.
*/
sk_sp<SkData> readImage(const string& fname)
{
sk_sp<SkData> data = GetResourceAsData(fname.c_str());
if (!data)
{
MSG_ERROR("readImage: Error loading the image " << fname);
TError::setError();
}
return data;
}
vector<string> StrSplit(const string& str, const string& seps, const bool trimEmpty)
{
size_t pos = 0, mark = 0;
vector<string> parts;
string::const_iterator it, sepIt;
for (it = str.begin(); it != str.end(); ++it)
{
for (sepIt = seps.begin(); sepIt != seps.end(); ++sepIt)
{
if (pos > 0 && *it == *sepIt)
{
size_t len = pos - mark;
if (len > 0)
parts.push_back(str.substr(mark, len));
else
parts.push_back(string());
mark = pos + 1;
break;
}
else if (*it == *sepIt)
mark = pos + 1;
}
pos++;
}
parts.push_back(str.substr(mark));
if (trimEmpty)
{
vector<string> nparts;
for (auto it = parts.begin(); it != parts.end(); ++it)
{
if (it->empty())
continue;
nparts.push_back(*it);
}
return nparts;
}
return parts;
}
string latin1ToUTF8(const string& str)
{
DECL_TRACER("NameFormat::latin1ToUTF8(const string& str)");
string out;
for (size_t i = 0; i < str.length(); i++)
{
uint8_t ch = str.at(i);
if (ch < 0x80)
{
out.push_back(ch);
}
else
{
out.push_back(0xc0 | ch >> 6);
out.push_back(0x80 | (ch & 0x3f));
}
}
return out;
}
string cp1250ToUTF8(const string& str)
{
DECL_TRACER("cp1250ToUTF8(const string& str)");
string out;
for (size_t j = 0; j < str.length(); j++)
{
int i = -1;
unsigned char ch = str.at(j);
short utf = -1;
if (ch < 0x80)
{
do
{
i++;
if (__cht[i].ch == ch)
{
utf = __cht[i].byte;
break;
}
}
while (__cht[i].ch != 0xff);
if (utf < 0)
utf = ch;
}
else
utf = ch;
if (utf > 0x00ff)
{
out.push_back((utf >> 8) & 0x00ff);
out.push_back(utf & 0x00ff);
}
else if (ch > 0x7f)
{
out.push_back(0xc0 | ch >> 6);
out.push_back(0x80 | (ch & 0x3f));
}
else
out.push_back(ch);
}
return out;
}
string UTF8ToCp1250(const string& str)
{
DECL_TRACER("UTF8ToCp1250(const string& str)");
char dst[1024];
size_t srclen = 0;
char* pIn, *pInSave;
srclen = str.length();
memset(&dst[0], 0, sizeof(dst));
try
{
pIn = new char[srclen + 1];
memcpy(pIn, str.c_str(), srclen);
*(pIn+srclen) = 0;
pInSave = pIn;
}
catch(std::exception& e)
{
MSG_ERROR("Error: " << e.what());
return "";
}
size_t dstlen = sizeof(dst) - 1;
char* pOut = (char *)dst;
iconv_t conv = iconv_open("CP1250", "UTF-8");
if (conv == (iconv_t)-1)
{
MSG_ERROR("Error opening iconv!");
delete[] pInSave;
return str;
}
size_t ret = iconv(conv, &pIn, &srclen, &pOut, &dstlen);
iconv_close(conv);
delete[] pInSave;
if (ret == (size_t)-1)
{
MSG_ERROR("Error converting a string!");
return str;
}
return string(dst);
}
void *renew(void *mem, size_t old_size, size_t new_size)
{
if (old_size == new_size)
return mem;
try
{
void *memory = new char[new_size];
size_t len = (new_size < old_size) ? new_size : old_size;
memcpy(memory, mem, len);
delete[] (char *)mem;
mem = memory;
return memory;
}
catch(std::exception& e)
{
MSG_ERROR(e.what());
throw e;
}
return nullptr;
}
string toUpper(string& str)
{
string::iterator iter;
for (iter = str.begin(); iter != str.end(); iter++)
*iter = std::toupper(*iter);
return str;
}
string toLower(string& str)
{
string::iterator iter;
for (iter = str.begin(); iter != str.end(); iter++)
*iter = std::tolower(*iter);
return str;
}