Subversion Repositories tpanel

Rev

Rev 446 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 andreas 1
/*
2
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
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
 
19
#include <iostream>
20
#include <iomanip>
21
 
22
#include "tcolor.h"
23
#include "terror.h"
24
#include "tresources.h"
25
 
26
TPalette *TColor::mPalette = nullptr;
27
 
28
using std::string;
29
using std::vector;
30
using std::setw;
31
using std::setfill;
32
using std::hex;
33
using std::dec;
34
using std::resetiosflags;
35
 
36
TColor::COLOR_T TColor::getAMXColor(const string& color)
37
{
38
    DECL_TRACER("TColor::getAMXColor(const string& color)");
39
 
40
    if (color.empty())
41
    {
42
        MSG_WARNING("Empty color name is ignored!");
43
        return TColor::COLOR_T();
44
    }
45
 
46
    // Check if we've an index number
47
    if (color.length() <= 3 && isdigit(color[0]))
48
    {
49
        int idx = atoi(color.c_str());
50
 
51
        if (idx >= 0 && idx <= 255)
52
        {
53
            PDATA_T pd = mPalette->findColor(idx);
54
 
55
            if (!pd.name.empty())
56
                return splitColors(pd);
57
        }
58
    }
59
 
60
    size_t pos = color.find('#');
61
 
62
    if (pos == string::npos)    // No # found?
63
    {                           // No #, then try to find color in palette
64
        if (!mPalette)
65
        {
66
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
67
            TError::setError();
68
            return TColor::COLOR_T();
69
        }
70
 
71
        PDATA_T pd = mPalette->findColor(color);
72
 
73
        if (!pd.name.empty())
74
            return splitColors(pd);
75
 
76
        // We fill in the default transparent color
77
        TColor::COLOR_T col;
78
        col.red = 0;
79
        col.green = 0;
80
        col.blue = 0;
81
        col.alpha = 0;
82
        return col;
83
    }
84
 
85
    // There was a # in the string. We assume that the color is encoded in hex
86
    // after the # symbol.
87
    string col = color.substr(pos + 1);
88
 
89
    if (col.length() < 6)
90
    {
91
        MSG_WARNING("Invalid color " << col << " found! Ignoring it.");
92
        return TColor::COLOR_T();
93
    }
94
 
95
    TColor::COLOR_T ct;
96
    ct.red = (int)strtol(col.substr(0, 2).c_str(), NULL, 16);
97
    ct.green = (int)strtol(col.substr(2, 2).c_str(), NULL, 16);
98
    ct.blue = (int)strtol(col.substr(4, 2).c_str(), NULL, 16);
99
 
100
    if (col.length() > 6)
101
        ct.alpha = (int)strtol(col.substr(6).c_str(), NULL, 16);
102
    else
103
        ct.alpha = 0x00ff;
104
 
105
    return ct;
106
}
107
 
108
TColor::COLOR_T TColor::splitColors(PDATA_T& pd)
109
{
110
    DECL_TRACER("TColor::splitColors(PDATA_T& pd)");
111
 
112
    TColor::COLOR_T ct;
113
    ct.red = (pd.color & 0xff000000) >> 24;
114
    ct.green = (pd.color & 0x00ff0000) >> 16;
115
    ct.blue = (pd.color & 0x0000ff00) >> 8;
116
    ct.alpha = (pd.color & 0x000000ff);
117
    return ct;
118
}
119
 
486 andreas 120
SkColor TColor::getSkiaColor(const string& color)
446 andreas 121
{
486 andreas 122
    DECL_TRACER("TColor::getSkiaColor(const string& color)");
446 andreas 123
 
124
    COLOR_T col = getAMXColor(color);
125
 
126
    if (col.alpha == 0)
127
        return SK_ColorTRANSPARENT;
128
 
129
    if (isBigEndian())
130
        return SkColorSetARGB(col.alpha, col.blue, col.green, col.red);
131
    else
132
        return SkColorSetARGB(col.alpha, col.red, col.green, col.blue);
133
}
134
 
135
ulong TColor::getColor(const std::string& color)
136
{
137
    DECL_TRACER("TColor::getColor(const std::string& color)");
138
 
139
    TColor::COLOR_T ct = getAMXColor(color);
140
    ulong col = ((ct.red << 24) & 0xff000000) | ((ct.green << 16) & 0x00ff0000) | ((ct.blue << 8) & 0x0000ff00) | (ct.alpha & 0x000000ff);
141
    return col;
142
}
143
 
144
std::string TColor::colorToString(ulong color)
145
{
146
    PDATA_T pd;
147
    pd.color = color;
148
    TColor::COLOR_T col = splitColors(pd);
149
    std::stringstream s;
150
    s << std::setw(2) << std::setfill('0') << std::hex << col.red << ":";
151
    s << std::setw(2) << std::setfill('0') << std::hex << col.green << ":";
152
    s << std::setw(2) << std::setfill('0') << std::hex << col.blue << ":";
153
    s << std::setw(2) << std::setfill('0') << std::hex << col.alpha;
154
    std::string ret = s.str();
155
    return ret;
156
}
157
 
158
std::string TColor::colorToString(SkColor color)
159
{
160
    std::stringstream s;
161
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetR(color) << ":";
162
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetG(color) << ":";
163
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetB(color) << ":";
164
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetA(color);
165
    std::string ret = s.str();
166
    return ret;
167
}
168
 
169
std::string TColor::colorToString(COLOR_T color)
170
{
171
    std::stringstream s;
172
    s << std::setw(2) << std::setfill('0') << std::hex << color.red << ":";
173
    s << std::setw(2) << std::setfill('0') << std::hex << color.green << ":";
174
    s << std::setw(2) << std::setfill('0') << std::hex << color.red << ":";
175
    s << std::setw(2) << std::setfill('0') << std::hex << color.alpha;
176
    std::string ret = s.str();
177
    return ret;
178
}
179
 
180
std::vector<SkColor> TColor::colorRange(SkColor col, int width, int bandwidth, DIRECTION_t dir)
181
{
182
    DECL_TRACER("TColor::colorRange(SkColor col, int width, int bandwidth)");
183
 
184
    int red, green, blue, alpha, colStep;
185
    vector<SkColor> colRange;
186
    SkColor color;
187
 
188
    alpha = SkColorGetA(col);
189
    // Define the start color
190
    if (dir == DIR_LIGHT_DARK || dir == DIR_LIGHT_DARK_LIGHT)
191
    {
192
        red = std::max((int)SkColorGetR(col) - bandwidth, 0);
193
        green = std::max((int)SkColorGetG(col) - bandwidth, 0);
194
        blue = std::max((int)SkColorGetB(col) - bandwidth, 0);
195
 
196
        if (dir == DIR_LIGHT_DARK)
197
            colStep = bandwidth / width;
198
        else
199
            colStep = bandwidth / (width / 2);
200
    }
201
    else
202
    {
203
        red = std::min((int)SkColorGetR(col) + bandwidth, 255);
204
        green = std::min((int)SkColorGetG(col) + bandwidth, 255);
205
        blue = std::min((int)SkColorGetB(col) + bandwidth, 255);
206
 
207
        if (dir == DIR_DARK_LIGHT)
208
            colStep = bandwidth / width;
209
        else
210
            colStep = bandwidth / (width / 2);
211
    }
212
 
213
    if (colStep <= 1)
214
    {
215
        colRange.push_back(col);
216
        return colRange;
217
    }
218
 
219
    switch(dir)
220
    {
221
        case DIR_LIGHT_DARK:
222
            for (int i = 0; i < width; i++)
223
            {
224
                red -= colStep * i;
225
                green -= colStep * i;
226
                blue -= colStep * i;
227
 
228
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
229
                if (green < 0) green = 0; else if (green > 255) green = 255;
230
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
231
 
232
                color = SkColorSetARGB(alpha, red, green, blue);
233
                colRange.push_back(color);
234
            }
235
        break;
236
 
237
        case DIR_DARK_LIGHT:
238
            for (int i = 0; i < width; i++)
239
            {
240
                red += colStep * i;
241
                green += colStep * i;
242
                blue += colStep * i;
243
 
244
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
245
                if (green < 0) green = 0; else if (green > 255) green = 255;
246
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
247
 
248
                color = SkColorSetARGB(alpha, red, green, blue);
249
                colRange.push_back(color);
250
            }
251
        break;
252
 
253
        case DIR_LIGHT_DARK_LIGHT:
254
            for (int i = 0; i < (width / 2); i++)
255
            {
256
                red -= colStep * i;
257
                green -= colStep * i;
258
                blue -= colStep * i;
259
 
260
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
261
                if (green < 0) green = 0; else if (green > 255) green = 255;
262
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
263
 
264
                color = SkColorSetARGB(alpha, red, green, blue);
265
                colRange.push_back(color);
266
            }
267
 
268
            for (int i = 0; i < (width / 2); i++)
269
            {
270
                red += colStep * i;
271
                green += colStep * i;
272
                blue += colStep * i;
273
 
274
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
275
                if (green < 0) green = 0; else if (green > 255) green = 255;
276
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
277
 
278
                color = SkColorSetARGB(alpha, red, green, blue);
279
                colRange.push_back(color);
280
            }
281
        break;
282
 
283
        case DIR_DARK_LIGHT_DARK:
284
            for (int i = 0; i < (width / 2); i++)
285
            {
286
                red += colStep * i;
287
                green += colStep * i;
288
                blue += colStep * i;
289
 
290
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
291
                if (green < 0) green = 0; else if (green > 255) green = 255;
292
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
293
 
294
                color = SkColorSetARGB(alpha, red, green, blue);
295
                colRange.push_back(color);
296
            }
297
 
298
            for (int i = 0; i < (width / 2); i++)
299
            {
300
                red -= colStep * i;
301
                green -= colStep * i;
302
                blue -= colStep * i;
303
 
304
                if (red   < 0) red   = 0; else if (red   > 255) red   = 255;
305
                if (green < 0) green = 0; else if (green > 255) green = 255;
306
                if (blue  < 0) blue  = 0; else if (blue  > 255) blue  = 255;
307
 
308
                color = SkColorSetARGB(alpha, red, green, blue);
309
                colRange.push_back(color);
310
            }
311
        break;
312
    }
313
 
314
    return colRange;
315
}
316
 
317
bool TColor::isValidAMXcolor(const string& color)
318
{
319
    DECL_TRACER("TColor::isValidAMXcolor(const string& color)");
320
 
321
    if (color.empty())
322
        return false;
323
 
324
    size_t pos = color.find('#');
325
 
326
    if (pos == string::npos)
327
    {
328
        if (!mPalette)
329
        {
330
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
331
            return false;
332
        }
333
 
334
        PDATA_T pd = mPalette->findColor(color);
335
 
336
        if (!pd.name.empty())
337
            return true;
338
 
339
        return false;
340
    }
341
 
342
    // Check if we've an index number
343
    if (color.length() <= 2 && isdigit(color[0]))
344
    {
345
        int idx = atoi(color.c_str());
346
 
347
        if (idx < 0 || idx > 88)
348
            return false;
349
 
350
        return true;
351
    }
352
 
353
    if (color.length() >= 7)    // #RRGGBBAA
354
        return true;
355
 
356
    return false;
357
}
358
 
359
int TColor::setAlpha(ulong color, int alpha)
360
{
361
    DECL_TRACER("TColor::setAlpha(ulong color, int alpha)");
362
 
363
    if (alpha > 0x00ff)
364
        alpha = 0x00ff;
365
    else if (alpha < 0)
366
        alpha = 0;
367
 
368
    return ((color & 0xffffff00) | (alpha & 0x00ff));
369
}
370
 
371
SkColor TColor::setAlpha(SkColor color, int alpha)
372
{
373
    DECL_TRACER("TColor::setAlpha(SkColor color, int alpha)");
374
 
375
    if (alpha > 0x00ff)
376
        alpha = 0x00ff;
377
    else if (alpha < 0)
378
        alpha = 0;
379
 
380
    SkColor red = SkColorGetR(color);
381
    SkColor green = SkColorGetG(color);
382
    SkColor blue = SkColorGetB(color);
383
    return SkColorSetARGB(alpha, red, green, blue);
384
}
385
 
386
int TColor::calcAlpha(int alpha1, int alpha2)
387
{
388
    DECL_TRACER("TColor::calcAlpha(int alpha1, int alpha2)");
389
 
390
    return (alpha1 + alpha2) / 2;
391
}
392
 
393
ulong TColor::setAlphaTreshold(ulong color, int alpha)
394
{
395
    DECL_TRACER("TColor::setAlphaTreshold(ulong color, int alpha)");
396
 
397
    uint al = color & 0x000000ff;
398
 
399
    if (al > (uint)alpha)
400
        return (color & 0xffffff00) | (alpha & 0x00ff);
401
 
402
    return color;
403
}
404
 
405
SkColor TColor::setAlphaTreshold(SkColor color, int alpha)
406
{
407
    DECL_TRACER("TColor::setAlphaTreshold(SkColor color, int alpha)");
408
 
409
    int al = SkColorGetA(color);
410
 
411
    if (al > alpha)
412
        return SkColorSetA(color, alpha);
413
 
414
    return color;
415
}