Subversion Repositories tpanel

Rev

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;
}