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);
250 andreas 121
#if defined(__ANDROID__) || defined(TARGET_OS_IPHONE) || defined(TARGET_OS_IOS)
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);
250 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;
191 andreas 209
 
210
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
211
                if (green < 0) green = 0; else if (green > 255) green = 255;
212
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
213
 
40 andreas 214
                color = SkColorSetARGB(alpha, red, green, blue);
215
                colRange.push_back(color);
216
            }
217
        break;
218
 
219
        case DIR_DARK_LIGHT:
220
            for (int i = 0; i < width; i++)
221
            {
222
                red += colStep * i;
223
                green += colStep * i;
224
                blue += colStep * i;
191 andreas 225
 
226
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
227
                if (green < 0) green = 0; else if (green > 255) green = 255;
228
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
229
 
40 andreas 230
                color = SkColorSetARGB(alpha, red, green, blue);
231
                colRange.push_back(color);
232
            }
233
        break;
234
 
235
        case DIR_LIGHT_DARK_LIGHT:
236
            for (int i = 0; i < (width / 2); i++)
237
            {
238
                red -= colStep * i;
239
                green -= colStep * i;
240
                blue -= colStep * i;
191 andreas 241
 
242
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
243
                if (green < 0) green = 0; else if (green > 255) green = 255;
244
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
245
 
40 andreas 246
                color = SkColorSetARGB(alpha, red, green, blue);
247
                colRange.push_back(color);
248
            }
249
 
250
            for (int i = 0; i < (width / 2); i++)
251
            {
252
                red += colStep * i;
253
                green += colStep * i;
254
                blue += colStep * i;
191 andreas 255
 
256
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
257
                if (green < 0) green = 0; else if (green > 255) green = 255;
258
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
259
 
40 andreas 260
                color = SkColorSetARGB(alpha, red, green, blue);
261
                colRange.push_back(color);
262
            }
263
        break;
264
 
265
        case DIR_DARK_LIGHT_DARK:
266
            for (int i = 0; i < (width / 2); i++)
267
            {
268
                red += colStep * i;
269
                green += colStep * i;
270
                blue += colStep * i;
191 andreas 271
 
272
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
273
                if (green < 0) green = 0; else if (green > 255) green = 255;
274
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
275
 
40 andreas 276
                color = SkColorSetARGB(alpha, red, green, blue);
277
                colRange.push_back(color);
278
            }
279
 
280
            for (int i = 0; i < (width / 2); i++)
281
            {
282
                red -= colStep * i;
283
                green -= colStep * i;
284
                blue -= colStep * i;
191 andreas 285
 
286
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
287
                if (green < 0) green = 0; else if (green > 255) green = 255;
288
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
289
 
40 andreas 290
                color = SkColorSetARGB(alpha, red, green, blue);
291
                colRange.push_back(color);
292
            }
293
        break;
294
    }
295
 
296
    return colRange;
297
}
298
 
108 andreas 299
bool TColor::isValidAMXcolor(const string& color)
300
{
301
    DECL_TRACER("TColor::isValidAMXcolor(const string& color)");
302
 
303
    if (color.empty())
304
        return false;
305
 
306
    size_t pos = color.find('#');
307
 
308
    if (pos == string::npos)
309
    {
310
        if (!mPalette)
311
        {
312
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
313
            return false;
314
        }
315
 
316
        PDATA_T pd = mPalette->findColor(color);
317
 
318
        if (!pd.name.empty())
319
            return true;
320
 
321
        return false;
322
    }
323
 
324
    // Check if we've an index number
325
    if (color.length() <= 2 && isdigit(color[0]))
326
    {
327
        int idx = atoi(color.c_str());
328
 
329
        if (idx < 0 || idx > 88)
330
            return false;
331
 
332
        return true;
333
    }
334
 
335
    if (color.length() >= 7)    // #RRGGBBAA
336
        return true;
337
 
338
    return false;
339
}
340
 
8 andreas 341
int TColor::setAlpha(ulong color, int alpha)
342
{
343
    DECL_TRACER("TColor::setAlpha(ulong color, int alpha)");
344
 
345
    if (alpha > 0x00ff)
346
        alpha = 0x00ff;
347
    else if (alpha < 0)
348
        alpha = 0;
349
 
350
    return ((color & 0xffffff00) | (alpha & 0x00ff));
351
}
352
 
353
SkColor TColor::setAlpha(SkColor color, int alpha)
354
{
355
    DECL_TRACER("TColor::setAlpha(SkColor color, int alpha)");
356
 
357
    if (alpha > 0x00ff)
358
        alpha = 0x00ff;
359
    else if (alpha < 0)
360
        alpha = 0;
361
 
362
    SkColor red = SkColorGetR(color);
363
    SkColor green = SkColorGetG(color);
364
    SkColor blue = SkColorGetB(color);
365
    return SkColorSetARGB(alpha, red, green, blue);
366
}
367
 
368
int TColor::calcAlpha(int alpha1, int alpha2)
369
{
370
    DECL_TRACER("TColor::calcAlpha(int alpha1, int alpha2)");
371
 
372
    return (alpha1 + alpha2) / 2;
373
}
374
 
375
ulong TColor::setAlphaTreshold(ulong color, int alpha)
376
{
377
    DECL_TRACER("TColor::setAlphaTreshold(ulong color, int alpha)");
378
 
379
    uint al = color & 0x000000ff;
380
 
381
    if (al > (uint)alpha)
382
        return (color & 0xffffff00) | (alpha & 0x00ff);
383
 
384
    return color;
385
}
386
 
387
SkColor TColor::setAlphaTreshold(SkColor color, int alpha)
388
{
389
    DECL_TRACER("TColor::setAlphaTreshold(SkColor color, int alpha)");
390
 
391
    int al = SkColorGetA(color);
392
 
393
    if (al > alpha)
394
        return SkColorSetA(color, alpha);
395
 
396
    return color;
397
}