ManaPlus
dyepalette.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2007-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
25 
26 #include "logger.h"
27 
28 #ifndef DYECMD
29 #include "resources/db/palettedb.h"
30 #endif // DYECMD
31 
32 #include "utils/stringutils.h"
33 
34 #ifndef USE_SDL2
35 #include <cmath>
36 #endif // USE_SDL2
37 
38 PRAGMA48(GCC diagnostic push)
39 PRAGMA48(GCC diagnostic ignored "-Wshadow")
40 #ifndef SDL_BIG_ENDIAN
41 #include <SDL_endian.h>
42 #endif // SDL_BYTEORDER
43 PRAGMA48(GCC diagnostic pop)
44 
45 #ifdef SIMD_SUPPORTED
46 #include "utils/cpu.h"
47 #endif // SIMD_SUPPORTED
48 #include "utils/foreach.h"
49 
50 #include "debug.h"
51 
58 
59 #ifdef USE_OPENGL
66 #endif // USE_OPENGL
67 
68 DyePalette::DyePalette(const std::string &restrict description,
69  const uint8_t blockSize) :
70  mColors()
71 {
72  const size_t size = CAST_SIZE(description.length());
73  if (size == 0)
74  return;
75 
76  StringVect parts;
77  splitToStringVector(parts, description.substr(1), ',');
78  if (description[0] == '#')
79  {
80  FOR_EACH (StringVectCIter, it, parts)
81  {
82  DyeColor color(0, 0, 0, 0);
83  hexToColor(*it, blockSize, color);
84  mColors.push_back(color);
85  }
86  return;
87  }
88 #ifndef DYECMD
89  else if (description[0] == '@')
90  {
91  uint8_t alpha = 255;
92  FOR_EACH (StringVectCIter, it, parts)
93  {
94  const std::string str = *it;
95  if (str.empty())
96  continue;
97  if (str[0] == '+')
98  {
99  if (str.size() != 3)
100  continue;
101  alpha = CAST_U8((hexDecode(str[1]) << 4) + hexDecode(str[2]));
102  continue;
103  }
104  const DyeColor *const color = PaletteDB::getColor(str);
105  if (color != nullptr)
106  {
107  DyeColor color2 = *color;
108  color2.value[3] = alpha;
109  mColors.push_back(color2);
110  }
111  else
112  {
113  DyeColor color2(0, 0, 0, 0);
114  hexToColor(str, blockSize, color2);
115  mColors.push_back(color2);
116  }
117  }
118  return;
119  }
120 #endif // DYECMD
121 
122  logger->log("Error, invalid embedded palette: %s", description.c_str());
123 }
124 
125 void DyePalette::hexToColor(const std::string &restrict hexStr,
126  const uint8_t blockSize,
127  DyeColor &color) noexcept2
128 {
129  for (size_t i = 0, colorIdx = 0;
130  i < blockSize && colorIdx < 4;
131  i += 2, colorIdx ++)
132  {
133  color.value[colorIdx] = CAST_U8((
134  hexDecode(hexStr[i]) << 4)
135  + hexDecode(hexStr[i + 1]));
136  }
137  color.update();
138 }
139 
140 unsigned int DyePalette::hexDecode(const signed char c) noexcept2
141 {
142  if ('0' <= c && c <= '9')
143  return c - '0';
144  else if ('A' <= c && c <= 'F')
145  return c - 'A' + 10;
146  else if ('a' <= c && c <= 'f')
147  return c - 'a' + 10;
148  else
149  return 0;
150 }
151 
152 void DyePalette::getColor(const unsigned int intensity,
153  unsigned int (&restrict color)[3]) const restrict2
154 {
155  if (intensity == 0)
156  {
157  color[0] = 0;
158  color[1] = 0;
159  color[2] = 0;
160  return;
161  }
162 
163  const int last = CAST_S32(mColors.size());
164  if (last == 0)
165  return;
166 
167  const int intLast = intensity * last;
168  const int i = intLast / 255;
169  const int t = intLast % 255;
170 
171  int j = t != 0 ? i : i - 1;
172 
173  if (j >= last)
174  j = 0;
175 
176  // Get the exact color if any, the next color otherwise.
177  const DyeColor &colorJ = mColors[j];
178  const int r2 = colorJ.value[0];
179  const int g2 = colorJ.value[1];
180  const int b2 = colorJ.value[2];
181 
182  if (t == 0)
183  {
184  // Exact color.
185  color[0] = r2;
186  color[1] = g2;
187  color[2] = b2;
188  return;
189  }
190 
191  // Get the previous color. First color is implicitly black.
192  if (i > 0 && i < last + 1)
193  {
194  const DyeColor &colorI = mColors[i - 1];
195  const int t2 = 255 - t;
196  // Perform a linear interpolation.
197  color[0] = (t2 * colorI.value[0] + t * r2) / 255;
198  color[1] = (t2 * colorI.value[1] + t * g2) / 255;
199  color[2] = (t2 * colorI.value[2] + t * b2) / 255;
200  }
201  else
202  {
203  // Perform a linear interpolation.
204  color[0] = (t * r2) / 255;
205  color[1] = (t * g2) / 255;
206  color[2] = (t * b2) / 255;
207  }
208 }
209 
210 void DyePalette::getColor(double intensity,
211  int (&restrict color)[3]) const restrict2
212 {
213  // Nothing to do here
214  if (mColors.empty())
215  return;
216 
217  // Force range
218  if (intensity > 1.0)
219  intensity = 1.0;
220  else if (intensity < 0.0)
221  intensity = 0.0;
222 
223  // Scale up
224  intensity *= static_cast<double>(mColors.size() - 1);
225 
226  // Color indices
227  const int i = CAST_S32(floor(intensity));
228  const int j = CAST_S32(ceil(intensity));
229  const DyeColor &colorI = mColors[i];
230 
231  if (i == j)
232  {
233  // Exact color.
234  color[0] = colorI.value[0];
235  color[1] = colorI.value[1];
236  color[2] = colorI.value[2];
237  return;
238  }
239 
240  intensity -= i;
241  const double rest = 1 - intensity;
242  const DyeColor &colorJ = mColors[j];
243 
244  // Perform the interpolation.
245  color[0] = CAST_S32(rest * colorI.value[0] +
246  intensity * colorJ.value[0]);
247  color[1] = CAST_S32(rest * colorI.value[1] +
248  intensity * colorJ.value[1]);
249  color[2] = CAST_S32(rest * colorI.value[2] +
250  intensity * colorJ.value[2]);
251 }
252 
254 {
255 #ifdef SIMD_SUPPORTED
256  const uint32_t flags = Cpu::getFlags();
257  if ((flags & Cpu::FEATURE_AVX2) != 0U)
258  {
259  funcReplaceSColor = &DyePalette::replaceSColorAvx2;
260  funcReplaceSColorAvx2 = &DyePalette::replaceSColorAvx2;
261  funcReplaceSColorSse2 = &DyePalette::replaceSColorSse2;
262  funcReplaceAColor = &DyePalette::replaceAColorAvx2;
263  funcReplaceAColorAvx2 = &DyePalette::replaceAColorAvx2;
264  funcReplaceAColorSse2 = &DyePalette::replaceAColorSse2;
265 
266 #ifdef USE_OPENGL
267  funcReplaceSOGLColor = &DyePalette::replaceSOGLColorAvx2;
268  funcReplaceSOGLColorAvx2 = &DyePalette::replaceSOGLColorAvx2;
269  funcReplaceSOGLColorSse2 = &DyePalette::replaceSOGLColorSse2;
270  funcReplaceAOGLColor = &DyePalette::replaceAOGLColorAvx2;
271  funcReplaceAOGLColorAvx2 = &DyePalette::replaceAOGLColorAvx2;
272  funcReplaceAOGLColorSse2 = &DyePalette::replaceAOGLColorSse2;
273 #endif // USE_OPENGL
274  }
275  else if ((flags & Cpu::FEATURE_SSE2) != 0U)
276  {
277  funcReplaceSColor = &DyePalette::replaceSColorSse2;
278  funcReplaceSColorAvx2 = &DyePalette::replaceSColorSse2;
279  funcReplaceSColorSse2 = &DyePalette::replaceSColorSse2;
280  funcReplaceAColor = &DyePalette::replaceAColorSse2;
281  funcReplaceAColorAvx2 = &DyePalette::replaceAColorSse2;
282  funcReplaceAColorSse2 = &DyePalette::replaceAColorSse2;
283 
284 #ifdef USE_OPENGL
285  funcReplaceSOGLColor = &DyePalette::replaceSOGLColorSse2;
286  funcReplaceSOGLColorAvx2 = &DyePalette::replaceSOGLColorSse2;
287  funcReplaceSOGLColorSse2 = &DyePalette::replaceSOGLColorSse2;
288  funcReplaceAOGLColor = &DyePalette::replaceAOGLColorSse2;
289  funcReplaceAOGLColorAvx2 = &DyePalette::replaceAOGLColorSse2;
290  funcReplaceAOGLColorSse2 = &DyePalette::replaceAOGLColorSse2;
291 #endif // USE_OPENGL
292  }
293  else
294 #endif // SIMD_SUPPORTED
295  {
302 
303 #ifdef USE_OPENGL
310 #endif // USE_OPENGL
311  }
312 }
#define CAST_S32
Definition: cast.h:30
#define CAST_SIZE
Definition: cast.h:34
#define CAST_U8
Definition: cast.h:27
static void initFunctions()
Definition: dyepalette.cpp:253
static DyeFunctionPtr funcReplaceAOGLColorSse2
Definition: dyepalette.h:171
void getColor(const unsigned int intensity, unsigned int(&color)[3]) const
Definition: dyepalette.cpp:152
static DyeFunctionPtr funcReplaceSColorAvx2
Definition: dyepalette.h:177
void replaceAColorDefault(uint32_t *pixels, const int bufSize) const
static DyeFunctionPtr funcReplaceAColorSse2
Definition: dyepalette.h:179
static DyeFunctionPtr funcReplaceSColor
Definition: dyepalette.h:175
void replaceAOGLColorDefault(uint32_t *pixels, const int bufSize) const
static DyeFunctionPtr funcReplaceAColor
Definition: dyepalette.h:178
static DyeFunctionPtr funcReplaceSOGLColor
Definition: dyepalette.h:167
void replaceSOGLColorDefault(uint32_t *pixels, const int bufSize) const
static void hexToColor(const std::string &hexStr, const uint8_t blockSize, DyeColor &color)
Definition: dyepalette.cpp:125
void replaceSColorDefault(uint32_t *pixels, const int bufSize) const
static DyeFunctionPtr funcReplaceSOGLColorSse2
Definition: dyepalette.h:168
static DyeFunctionPtr funcReplaceSColorSse2
Definition: dyepalette.h:176
static DyeFunctionPtr funcReplaceAOGLColorAvx2
Definition: dyepalette.h:172
static unsigned int hexDecode(const signed char c) A_CONST
Definition: dyepalette.cpp:140
DyePalette(const std::string &pallete, const uint8_t blockSize)
Definition: dyepalette.cpp:68
static DyeFunctionPtr funcReplaceAOGLColor
Definition: dyepalette.h:170
static DyeFunctionPtr funcReplaceSOGLColorAvx2
Definition: dyepalette.h:169
static DyeFunctionPtr funcReplaceAColorAvx2
Definition: dyepalette.h:180
std::vector< DyeColor > mColors
Definition: dyepalette.h:185
void log(const char *const log_text,...)
Definition: logger.cpp:269
void(DyePalette::* DyeFunctionPtr)(uint32_t *pixels, const int bufSize) const
Definition: dyepaletteptr.h:29
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define restrict
Definition: localconsts.h:165
#define restrict2
Definition: localconsts.h:166
#define noexcept2
Definition: localconsts.h:50
#define PRAGMA48(str)
Definition: localconsts.h:199
Logger * logger
Definition: logger.cpp:89
uint32_t getFlags()
Definition: cpu.cpp:176
@ FEATURE_AVX2
Definition: cpu.h:39
@ FEATURE_SSE2
Definition: cpu.h:34
int size()
Definition: emotedb.cpp:306
const DyeColor * getColor(const std::string &name)
Definition: palettedb.cpp:109
std::map< std::string, DyeColor > mColors
Definition: palettedb.cpp:37
void splitToStringVector(StringVect &tokens, const std::string &text, const char separator)
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:31
std::vector< std::string > StringVect
Definition: stringvector.h:29
uint8_t value[4]
Definition: dyecolor.h:77