Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 andreas 1
/*
21 andreas 2
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
4 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
5 andreas 19
#include <iostream>
20
#include <iomanip>
21
 
4 andreas 22
#include "tcolor.h"
23
#include "terror.h"
24
 
25
TPalette *TColor::mPalette = nullptr;
26
 
27
using std::string;
40 andreas 28
using std::vector;
5 andreas 29
using std::setw;
30
using std::setfill;
31
using std::hex;
32
using std::dec;
33
using std::resetiosflags;
4 andreas 34
 
35
TColor::COLOR_T TColor::getAMXColor(const string& color)
36
{
37
    DECL_TRACER("TColor::getAMXColor(const string& color)");
38
 
39
    if (color.empty())
137 andreas 40
    {
41
        MSG_WARNING("Empty color name is ignored!");
4 andreas 42
        return TColor::COLOR_T();
137 andreas 43
    }
4 andreas 44
 
146 andreas 45
    // Check if we've an index number
46
    if (color.length() <= 2 && isdigit(color[0]))
47
    {
48
        int idx = atoi(color.c_str());
49
 
50
        if (idx >= 0 && idx <= 88)
51
        {
52
            PDATA_T pd = mPalette->findColor(idx);
53
 
54
            if (!pd.name.empty())
55
                return splitColors(pd);
56
        }
57
    }
58
 
4 andreas 59
    size_t pos = color.find('#');
60
 
61
    if (pos == string::npos)
62
    {
63
        if (!mPalette)
64
        {
65
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
66
            TError::setError();
67
            return TColor::COLOR_T();
68
        }
69
 
70
        PDATA_T pd = mPalette->findColor(color);
71
 
72
        if (!pd.name.empty())
73
            return splitColors(pd);
74
 
137 andreas 75
        MSG_DEBUG("Color " << color << " not found in table!");
4 andreas 76
        return TColor::COLOR_T();
77
    }
78
 
79
    TColor::COLOR_T ct;
80
    ct.red = (int)strtol(color.substr(pos+1, 2).c_str(), NULL, 16);
81
    ct.green = (int)strtol(color.substr(pos+3, 2).c_str(), NULL, 16);
82
    ct.blue = (int)strtol(color.substr(pos+5, 2).c_str(), NULL, 16);
83
 
84
    if (color.length() > 7)
85
        ct.alpha = (int)strtol(color.substr(pos+7).c_str(), NULL, 16);
86
    else
87
        ct.alpha = 0x00ff;
88
 
89
    return ct;
90
}
91
 
92
TColor::COLOR_T TColor::splitColors(PDATA_T& pd)
93
{
94
    DECL_TRACER("TColor::splitColors(PDATA_T& pd)");
95
 
96
    TColor::COLOR_T ct;
97
 
98
    if (pd.color > 0x00ffffff)
99
    {
100
        ct.red = (pd.color & 0xff000000) >> 24;
101
        ct.green = (pd.color & 0x00ff0000) >> 16;
102
        ct.blue = (pd.color & 0x0000ff00) >> 8;
103
        ct.alpha = (pd.color & 0x000000ff);
104
    }
105
    else
106
    {
107
        ct.red = (pd.color & 0xff000000) >> 24;
108
        ct.green = (pd.color & 0x00ff0000) >> 16;
109
        ct.blue = (pd.color & 0x0000ff00) >> 8;
110
        ct.alpha = 0x00ff;
111
    }
112
 
113
    return ct;
114
}
115
 
116
SkColor TColor::getSkiaColor(const std::string& color)
117
{
118
    DECL_TRACER("TColor::getSkiaColor(const std::string& color)");
119
 
120
    COLOR_T col = getAMXColor(color);
59 andreas 121
#ifdef __ANDROID__
122
    return SkColorSetARGB(col.alpha, col.blue, col.green, col.red); // Workaround for a bug in Skia
123
#else
4 andreas 124
    return SkColorSetARGB(col.alpha, col.red, col.green, col.blue);
59 andreas 125
#endif
4 andreas 126
}
5 andreas 127
 
128
ulong TColor::getColor(const std::string& color)
129
{
130
    DECL_TRACER("TColor::getColor(const std::string& color)");
131
 
132
    TColor::COLOR_T ct = getAMXColor(color);
133
    ulong col = ((ct.red << 24) & 0xff000000) | ((ct.green << 16) & 0x00ff0000) | ((ct.blue << 8) & 0x0000ff00) | (ct.alpha & 0x000000ff);
134
    return col;
135
}
7 andreas 136
 
137
std::string TColor::colorToString(ulong color)
138
{
139
    PDATA_T pd;
140
    pd.color = color;
141
    TColor::COLOR_T col = splitColors(pd);
142
    std::stringstream s;
143
    s << std::setw(2) << std::setfill('0') << std::hex << col.red << ":";
144
    s << std::setw(2) << std::setfill('0') << std::hex << col.green << ":";
145
    s << std::setw(2) << std::setfill('0') << std::hex << col.blue << ":";
146
    s << std::setw(2) << std::setfill('0') << std::hex << col.alpha;
147
    std::string ret = s.str();
148
    return ret;
149
}
150
 
151
std::string TColor::colorToString(SkColor color)
152
{
153
    std::stringstream s;
154
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetR(color) << ":";
155
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetG(color) << ":";
156
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetB(color) << ":";
157
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetA(color);
158
    std::string ret = s.str();
159
    return ret;
160
}
8 andreas 161
 
40 andreas 162
std::vector<SkColor> TColor::colorRange(SkColor col, int width, int bandwidth, DIRECTION_t dir)
163
{
164
    DECL_TRACER("TColor::colorRange(SkColor col, int width, int bandwidth)");
165
 
166
    int red, green, blue, alpha, colStep;
167
    vector<SkColor> colRange;
168
    SkColor color;
169
 
170
    alpha = SkColorGetA(col);
171
    // Define the start color
172
    if (dir == DIR_LIGHT_DARK || dir == DIR_LIGHT_DARK_LIGHT)
173
    {
174
        red = std::max((int)SkColorGetR(col) - bandwidth, 0);
175
        green = std::max((int)SkColorGetG(col) - bandwidth, 0);
176
        blue = std::max((int)SkColorGetB(col) - bandwidth, 0);
177
 
178
        if (dir == DIR_LIGHT_DARK)
179
            colStep = bandwidth / width;
180
        else
181
            colStep = bandwidth / (width / 2);
182
    }
183
    else
184
    {
185
        red = std::min((int)SkColorGetR(col) + bandwidth, 255);
186
        green = std::min((int)SkColorGetG(col) + bandwidth, 255);
187
        blue = std::min((int)SkColorGetB(col) + bandwidth, 255);
188
 
189
        if (dir == DIR_DARK_LIGHT)
190
            colStep = bandwidth / width;
191
        else
192
            colStep = bandwidth / (width / 2);
193
    }
194
 
195
    if (colStep <= 1)
196
    {
197
        colRange.push_back(col);
198
        return colRange;
199
    }
200
 
201
    switch(dir)
202
    {
203
        case DIR_LIGHT_DARK:
204
            for (int i = 0; i < width; i++)
205
            {
206
                red -= colStep * i;
207
                green -= colStep * i;
208
                blue -= colStep * i;
209
                color = SkColorSetARGB(alpha, red, green, blue);
210
                colRange.push_back(color);
211
            }
212
        break;
213
 
214
        case DIR_DARK_LIGHT:
215
            for (int i = 0; i < width; i++)
216
            {
217
                red += colStep * i;
218
                green += colStep * i;
219
                blue += colStep * i;
220
                color = SkColorSetARGB(alpha, red, green, blue);
221
                colRange.push_back(color);
222
            }
223
        break;
224
 
225
        case DIR_LIGHT_DARK_LIGHT:
226
            for (int i = 0; i < (width / 2); i++)
227
            {
228
                red -= colStep * i;
229
                green -= colStep * i;
230
                blue -= colStep * i;
231
                color = SkColorSetARGB(alpha, red, green, blue);
232
                colRange.push_back(color);
233
            }
234
 
235
            for (int i = 0; i < (width / 2); i++)
236
            {
237
                red += colStep * i;
238
                green += colStep * i;
239
                blue += colStep * i;
240
                color = SkColorSetARGB(alpha, red, green, blue);
241
                colRange.push_back(color);
242
            }
243
        break;
244
 
245
        case DIR_DARK_LIGHT_DARK:
246
            for (int i = 0; i < (width / 2); i++)
247
            {
248
                red += colStep * i;
249
                green += colStep * i;
250
                blue += colStep * i;
251
                color = SkColorSetARGB(alpha, red, green, blue);
252
                colRange.push_back(color);
253
            }
254
 
255
            for (int i = 0; i < (width / 2); i++)
256
            {
257
                red -= colStep * i;
258
                green -= colStep * i;
259
                blue -= colStep * i;
260
                color = SkColorSetARGB(alpha, red, green, blue);
261
                colRange.push_back(color);
262
            }
263
        break;
264
    }
265
 
266
    return colRange;
267
}
268
 
108 andreas 269
bool TColor::isValidAMXcolor(const string& color)
270
{
271
    DECL_TRACER("TColor::isValidAMXcolor(const string& color)");
272
 
273
    if (color.empty())
274
        return false;
275
 
276
    size_t pos = color.find('#');
277
 
278
    if (pos == string::npos)
279
    {
280
        if (!mPalette)
281
        {
282
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
283
            return false;
284
        }
285
 
286
        PDATA_T pd = mPalette->findColor(color);
287
 
288
        if (!pd.name.empty())
289
            return true;
290
 
291
        return false;
292
    }
293
 
294
    // Check if we've an index number
295
    if (color.length() <= 2 && isdigit(color[0]))
296
    {
297
        int idx = atoi(color.c_str());
298
 
299
        if (idx < 0 || idx > 88)
300
            return false;
301
 
302
        return true;
303
    }
304
 
305
    if (color.length() >= 7)    // #RRGGBBAA
306
        return true;
307
 
308
    return false;
309
}
310
 
8 andreas 311
int TColor::setAlpha(ulong color, int alpha)
312
{
313
    DECL_TRACER("TColor::setAlpha(ulong color, int alpha)");
314
 
315
    if (alpha > 0x00ff)
316
        alpha = 0x00ff;
317
    else if (alpha < 0)
318
        alpha = 0;
319
 
320
    return ((color & 0xffffff00) | (alpha & 0x00ff));
321
}
322
 
323
SkColor TColor::setAlpha(SkColor color, int alpha)
324
{
325
    DECL_TRACER("TColor::setAlpha(SkColor color, int alpha)");
326
 
327
    if (alpha > 0x00ff)
328
        alpha = 0x00ff;
329
    else if (alpha < 0)
330
        alpha = 0;
331
 
332
    SkColor red = SkColorGetR(color);
333
    SkColor green = SkColorGetG(color);
334
    SkColor blue = SkColorGetB(color);
335
    return SkColorSetARGB(alpha, red, green, blue);
336
}
337
 
338
int TColor::calcAlpha(int alpha1, int alpha2)
339
{
340
    DECL_TRACER("TColor::calcAlpha(int alpha1, int alpha2)");
341
 
342
    return (alpha1 + alpha2) / 2;
343
}
344
 
345
ulong TColor::setAlphaTreshold(ulong color, int alpha)
346
{
347
    DECL_TRACER("TColor::setAlphaTreshold(ulong color, int alpha)");
348
 
349
    uint al = color & 0x000000ff;
350
 
351
    if (al > (uint)alpha)
352
        return (color & 0xffffff00) | (alpha & 0x00ff);
353
 
354
    return color;
355
}
356
 
357
SkColor TColor::setAlphaTreshold(SkColor color, int alpha)
358
{
359
    DECL_TRACER("TColor::setAlphaTreshold(SkColor color, int alpha)");
360
 
361
    int al = SkColorGetA(color);
362
 
363
    if (al > alpha)
364
        return SkColorSetA(color, alpha);
365
 
366
    return color;
367
}