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