GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/palette.cpp Lines: 9 78 11.5 %
Date: 2021-03-17 Branches: 0 46 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008  Douglas Boffey <[email protected]>
4
 *  Copyright (C) 2009  The Mana World Development Team
5
 *  Copyright (C) 2009-2010  The Mana Developers
6
 *  Copyright (C) 2011-2019  The ManaPlus Developers
7
 *  Copyright (C) 2019-2021  Andrei Karas
8
 *
9
 *  This file is part of The ManaPlus Client.
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  any later version.
15
 *
16
 *  This program is distributed in the hope that it will be useful,
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *  GNU General Public License for more details.
20
 *
21
 *  You should have received a copy of the GNU General Public License
22
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
#include "gui/palette.h"
26
27
#include "utils/foreach.h"
28
#include "utils/timer.h"
29
30
#ifndef USE_SDL2
31
#include <cmath>
32
#endif  // USE_SDL2
33
34
#include "debug.h"
35
36
const Color Palette::BLACK = Color(0, 0, 0, 255);
37
1
Palette::Palettes Palette::mInstances;
38
39
const Color Palette::RAINBOW_COLORS[7] =
40
{
41
    Color(255, 0, 0, 255),
42
    Color(255, 153, 0, 255),
43
    Color(255, 255, 0, 255),
44
    Color(0, 153, 0, 255),
45
    Color(0, 204, 204, 255),
46
    Color(51, 0, 153, 255),
47
    Color(153, 0, 153, 255)
48
};
49
50
const int Palette::RAINBOW_COLOR_COUNT = 7;
51
52
363
Palette::Palette(const int size) :
53
    mRainbowTime(tick_time),
54
    mColors(Colors(size)),
55
    mCharColors(),
56
1815
    mGradVector()
57
{
58
726
    mInstances.insert(this);
59
363
}
60
61
1400
Palette::~Palette()
62
{
63
700
    mInstances.erase(this);
64
350
}
65
66
const Color& Palette::getCharColor(const signed char c, bool &valid) const
67
{
68
    const CharColors::const_iterator it = mCharColors.find(c);
69
    if (it != mCharColors.end())
70
    {
71
        valid = true;
72
        return mColors[(*it).second].color;
73
    }
74
75
    valid = false;
76
    return BLACK;
77
}
78
79
void Palette::advanceGradients()
80
{
81
    FOR_EACH (Palettes::const_iterator, it, mInstances)
82
        (*it)->advanceGradient();
83
}
84
85
void Palette::advanceGradient()
86
{
87
    const int time = get_elapsed_time(mRainbowTime);
88
    if (time > 5)
89
    {
90
        // For slower systems, advance can be greater than one (advance > 1
91
        // skips advance-1 steps). Should make gradient look the same
92
        // independent of the framerate.
93
        const int advance = time / 5;
94
95
        for (size_t i = 0, sz = mGradVector.size(); i < sz; i++)
96
        {
97
            ColorElem *const elem A_NONNULLPOINTER = mGradVector[i];
98
            if (elem == nullptr)
99
                continue;
100
101
            int delay = elem->delay;
102
            const GradientTypeT &grad = elem->grad;
103
104
            if (grad == GradientType::PULSE)
105
                delay = delay / 20;
106
107
            const int numOfColors = (elem->grad == GradientType::SPECTRUM ? 6 :
108
                grad == GradientType::PULSE ? 127 :
109
                RAINBOW_COLOR_COUNT);
110
111
            elem->gradientIndex = (elem->gradientIndex + advance)
112
                % (delay * numOfColors);
113
114
            const int gradIndex = elem->gradientIndex;
115
            const int pos = delay != 0 ? (gradIndex % delay) : gradIndex;
116
            int colIndex;
117
            if (delay != 0)
118
                colIndex = gradIndex / delay;
119
            else
120
                colIndex = gradIndex;
121
122
            Color &color = elem->color;
123
            int colVal;
124
125
            if (grad == GradientType::PULSE)
126
            {
127
                colVal = CAST_S32(255.0 *
128
                        sin(M_PI * colIndex / numOfColors));
129
130
                const Color &col = elem->testColor;
131
132
                color.r = ((colVal * col.r) / 255) % (col.r + 1);
133
                color.g = ((colVal * col.g) / 255) % (col.g + 1);
134
                color.b = ((colVal * col.b) / 255) % (col.b + 1);
135
            }
136
            else if (grad == GradientType::SPECTRUM)
137
            {
138
                if ((colIndex % 2) != 0)
139
                {   // falling curve
140
                    if (delay != 0)
141
                    {
142
                        colVal = CAST_S32(255.0 *
143
                             (cos(M_PI * pos / delay) + 1) / 2);
144
                    }
145
                    else
146
                    {
147
                        colVal = CAST_S32(255.0 *
148
                             (cos(M_PI * pos) + 1) / 2);
149
                    }
150
                }
151
                else
152
                {   // ascending curve
153
                    if (delay != 0)
154
                    {
155
                        colVal = CAST_S32(255.0 * (cos(M_PI *
156
                            (delay - pos) / delay) + 1) / 2);
157
                    }
158
                    else
159
                    {
160
                        colVal = CAST_S32(255.0 * (cos(M_PI *
161
                            (delay - pos)) + 1) / 2);
162
                    }
163
                }
164
165
                color.r = (colIndex == 0 || colIndex == 5) ? 255 :
166
                    (colIndex == 1 || colIndex == 4) ? colVal : 0;
167
                color.g = (colIndex == 1 || colIndex == 2) ? 255 :
168
                    (colIndex == 0 || colIndex == 3) ? colVal : 0;
169
                color.b = (colIndex == 3 || colIndex == 4) ? 255 :
170
                    (colIndex == 2 || colIndex == 5) ? colVal : 0;
171
            }
172
            else if (elem->grad == GradientType::RAINBOW)
173
            {
174
                const Color &startCol = RAINBOW_COLORS[colIndex];
175
                const Color &destCol
176
                    = RAINBOW_COLORS[(colIndex + 1) % numOfColors];
177
                double startColVal;
178
                double destColVal;
179
180
                if (delay != 0)
181
                    startColVal = (cos(M_PI * pos / delay) + 1) / 2;
182
                else
183
                    startColVal = 0;
184
185
                destColVal = 1 - startColVal;
186
187
                color.r = CAST_S32(startColVal
188
                    * startCol.r + destColVal * destCol.r);
189
190
                color.g = CAST_S32(startColVal
191
                    * startCol.g + destColVal * destCol.g);
192
193
                color.b = CAST_S32(startColVal
194
                    * startCol.b + destColVal * destCol.b);
195
            }
196
        }
197
198
        mRainbowTime = tick_time;
199
    }
200
2
}