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
 
45
    size_t pos = color.find('#');
46
 
47
    if (pos == string::npos)
48
    {
49
        if (!mPalette)
50
        {
51
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
52
            TError::setError();
53
            return TColor::COLOR_T();
54
        }
55
 
56
        PDATA_T pd = mPalette->findColor(color);
57
 
58
        if (!pd.name.empty())
59
            return splitColors(pd);
60
 
137 andreas 61
        MSG_DEBUG("Color " << color << " not found in table!");
4 andreas 62
        return TColor::COLOR_T();
63
    }
64
 
108 andreas 65
    // Check if we've an index number
66
    if (color.length() <= 2 && isdigit(color[0]))
67
    {
68
        int idx = atoi(color.c_str());
69
 
70
        if (idx < 0 || idx > 88)
71
            return TColor::COLOR_T();
72
 
73
        PDATA_T pd = mPalette->findColor(idx);
74
 
75
        if (!pd.name.empty())
76
            return splitColors(pd);
77
 
78
        return TColor::COLOR_T();
79
    }
80
 
4 andreas 81
    TColor::COLOR_T ct;
82
    ct.red = (int)strtol(color.substr(pos+1, 2).c_str(), NULL, 16);
83
    ct.green = (int)strtol(color.substr(pos+3, 2).c_str(), NULL, 16);
84
    ct.blue = (int)strtol(color.substr(pos+5, 2).c_str(), NULL, 16);
85
 
86
    if (color.length() > 7)
87
        ct.alpha = (int)strtol(color.substr(pos+7).c_str(), NULL, 16);
88
    else
89
        ct.alpha = 0x00ff;
90
 
91
    return ct;
92
}
93
 
94
TColor::COLOR_T TColor::splitColors(PDATA_T& pd)
95
{
96
    DECL_TRACER("TColor::splitColors(PDATA_T& pd)");
97
 
98
    TColor::COLOR_T ct;
99
 
100
    if (pd.color > 0x00ffffff)
101
    {
102
        ct.red = (pd.color & 0xff000000) >> 24;
103
        ct.green = (pd.color & 0x00ff0000) >> 16;
104
        ct.blue = (pd.color & 0x0000ff00) >> 8;
105
        ct.alpha = (pd.color & 0x000000ff);
106
    }
107
    else
108
    {
109
        ct.red = (pd.color & 0xff000000) >> 24;
110
        ct.green = (pd.color & 0x00ff0000) >> 16;
111
        ct.blue = (pd.color & 0x0000ff00) >> 8;
112
        ct.alpha = 0x00ff;
113
    }
114
 
115
    return ct;
116
}
117
 
118
SkColor TColor::getSkiaColor(const std::string& color)
119
{
120
    DECL_TRACER("TColor::getSkiaColor(const std::string& color)");
121
 
122
    COLOR_T col = getAMXColor(color);
59 andreas 123
#ifdef __ANDROID__
124
    return SkColorSetARGB(col.alpha, col.blue, col.green, col.red); // Workaround for a bug in Skia
125
#else
4 andreas 126
    return SkColorSetARGB(col.alpha, col.red, col.green, col.blue);
59 andreas 127
#endif
4 andreas 128
}
5 andreas 129
 
130
ulong TColor::getColor(const std::string& color)
131
{
132
    DECL_TRACER("TColor::getColor(const std::string& color)");
133
 
134
    TColor::COLOR_T ct = getAMXColor(color);
135
    ulong col = ((ct.red << 24) & 0xff000000) | ((ct.green << 16) & 0x00ff0000) | ((ct.blue << 8) & 0x0000ff00) | (ct.alpha & 0x000000ff);
136
    return col;
137
}
7 andreas 138
 
139
std::string TColor::colorToString(ulong color)
140
{
141
    PDATA_T pd;
142
    pd.color = color;
143
    TColor::COLOR_T col = splitColors(pd);
144
    std::stringstream s;
145
    s << std::setw(2) << std::setfill('0') << std::hex << col.red << ":";
146
    s << std::setw(2) << std::setfill('0') << std::hex << col.green << ":";
147
    s << std::setw(2) << std::setfill('0') << std::hex << col.blue << ":";
148
    s << std::setw(2) << std::setfill('0') << std::hex << col.alpha;
149
    std::string ret = s.str();
150
    return ret;
151
}
152
 
153
std::string TColor::colorToString(SkColor color)
154
{
155
    std::stringstream s;
156
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetR(color) << ":";
157
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetG(color) << ":";
158
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetB(color) << ":";
159
    s << std::setw(2) << std::setfill('0') << std::hex << SkColorGetA(color);
160
    std::string ret = s.str();
161
    return ret;
162
}
8 andreas 163
 
40 andreas 164
std::vector<SkColor> TColor::colorRange(SkColor col, int width, int bandwidth, DIRECTION_t dir)
165
{
166
    DECL_TRACER("TColor::colorRange(SkColor col, int width, int bandwidth)");
167
 
168
    int red, green, blue, alpha, colStep;
169
    vector<SkColor> colRange;
170
    SkColor color;
171
 
172
    alpha = SkColorGetA(col);
173
    // Define the start color
174
    if (dir == DIR_LIGHT_DARK || dir == DIR_LIGHT_DARK_LIGHT)
175
    {
176
        red = std::max((int)SkColorGetR(col) - bandwidth, 0);
177
        green = std::max((int)SkColorGetG(col) - bandwidth, 0);
178
        blue = std::max((int)SkColorGetB(col) - bandwidth, 0);
179
 
180
        if (dir == DIR_LIGHT_DARK)
181
            colStep = bandwidth / width;
182
        else
183
            colStep = bandwidth / (width / 2);
184
    }
185
    else
186
    {
187
        red = std::min((int)SkColorGetR(col) + bandwidth, 255);
188
        green = std::min((int)SkColorGetG(col) + bandwidth, 255);
189
        blue = std::min((int)SkColorGetB(col) + bandwidth, 255);
190
 
191
        if (dir == DIR_DARK_LIGHT)
192
            colStep = bandwidth / width;
193
        else
194
            colStep = bandwidth / (width / 2);
195
    }
196
 
197
    if (colStep <= 1)
198
    {
199
        colRange.push_back(col);
200
        return colRange;
201
    }
202
 
203
    switch(dir)
204
    {
205
        case DIR_LIGHT_DARK:
206
            for (int i = 0; i < width; i++)
207
            {
208
                red -= colStep * i;
209
                green -= colStep * i;
210
                blue -= colStep * i;
211
                color = SkColorSetARGB(alpha, red, green, blue);
212
                colRange.push_back(color);
213
            }
214
        break;
215
 
216
        case DIR_DARK_LIGHT:
217
            for (int i = 0; i < width; i++)
218
            {
219
                red += colStep * i;
220
                green += colStep * i;
221
                blue += colStep * i;
222
                color = SkColorSetARGB(alpha, red, green, blue);
223
                colRange.push_back(color);
224
            }
225
        break;
226
 
227
        case DIR_LIGHT_DARK_LIGHT:
228
            for (int i = 0; i < (width / 2); i++)
229
            {
230
                red -= colStep * i;
231
                green -= colStep * i;
232
                blue -= colStep * i;
233
                color = SkColorSetARGB(alpha, red, green, blue);
234
                colRange.push_back(color);
235
            }
236
 
237
            for (int i = 0; i < (width / 2); i++)
238
            {
239
                red += colStep * i;
240
                green += colStep * i;
241
                blue += colStep * i;
242
                color = SkColorSetARGB(alpha, red, green, blue);
243
                colRange.push_back(color);
244
            }
245
        break;
246
 
247
        case DIR_DARK_LIGHT_DARK:
248
            for (int i = 0; i < (width / 2); i++)
249
            {
250
                red += colStep * i;
251
                green += colStep * i;
252
                blue += colStep * i;
253
                color = SkColorSetARGB(alpha, red, green, blue);
254
                colRange.push_back(color);
255
            }
256
 
257
            for (int i = 0; i < (width / 2); i++)
258
            {
259
                red -= colStep * i;
260
                green -= colStep * i;
261
                blue -= colStep * i;
262
                color = SkColorSetARGB(alpha, red, green, blue);
263
                colRange.push_back(color);
264
            }
265
        break;
266
    }
267
 
268
    return colRange;
269
}
270
 
108 andreas 271
bool TColor::isValidAMXcolor(const string& color)
272
{
273
    DECL_TRACER("TColor::isValidAMXcolor(const string& color)");
274
 
275
    if (color.empty())
276
        return false;
277
 
278
    size_t pos = color.find('#');
279
 
280
    if (pos == string::npos)
281
    {
282
        if (!mPalette)
283
        {
284
            MSG_ERROR("No palette was set! First set a palette to be able to get any color!");
285
            return false;
286
        }
287
 
288
        PDATA_T pd = mPalette->findColor(color);
289
 
290
        if (!pd.name.empty())
291
            return true;
292
 
293
        return false;
294
    }
295
 
296
    // Check if we've an index number
297
    if (color.length() <= 2 && isdigit(color[0]))
298
    {
299
        int idx = atoi(color.c_str());
300
 
301
        if (idx < 0 || idx > 88)
302
            return false;
303
 
304
        return true;
305
    }
306
 
307
    if (color.length() >= 7)    // #RRGGBBAA
308
        return true;
309
 
310
    return false;
311
}
312
 
8 andreas 313
int TColor::setAlpha(ulong color, int alpha)
314
{
315
    DECL_TRACER("TColor::setAlpha(ulong color, int alpha)");
316
 
317
    if (alpha > 0x00ff)
318
        alpha = 0x00ff;
319
    else if (alpha < 0)
320
        alpha = 0;
321
 
322
    return ((color & 0xffffff00) | (alpha & 0x00ff));
323
}
324
 
325
SkColor TColor::setAlpha(SkColor color, int alpha)
326
{
327
    DECL_TRACER("TColor::setAlpha(SkColor color, int alpha)");
328
 
329
    if (alpha > 0x00ff)
330
        alpha = 0x00ff;
331
    else if (alpha < 0)
332
        alpha = 0;
333
 
334
    SkColor red = SkColorGetR(color);
335
    SkColor green = SkColorGetG(color);
336
    SkColor blue = SkColorGetB(color);
337
    return SkColorSetARGB(alpha, red, green, blue);
338
}
339
 
340
int TColor::calcAlpha(int alpha1, int alpha2)
341
{
342
    DECL_TRACER("TColor::calcAlpha(int alpha1, int alpha2)");
343
 
344
    return (alpha1 + alpha2) / 2;
345
}
346
 
347
ulong TColor::setAlphaTreshold(ulong color, int alpha)
348
{
349
    DECL_TRACER("TColor::setAlphaTreshold(ulong color, int alpha)");
350
 
351
    uint al = color & 0x000000ff;
352
 
353
    if (al > (uint)alpha)
354
        return (color & 0xffffff00) | (alpha & 0x00ff);
355
 
356
    return color;
357
}
358
 
359
SkColor TColor::setAlphaTreshold(SkColor color, int alpha)
360
{
361
    DECL_TRACER("TColor::setAlphaTreshold(SkColor color, int alpha)");
362
 
363
    int al = SkColorGetA(color);
364
 
365
    if (al > alpha)
366
        return SkColorSetA(color, alpha);
367
 
368
    return color;
369
}