ManaPlus
dye.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 
24 #include "resources/dye/dye.h"
25 
26 #include "logger.h"
27 
29 
30 #include "utils/delete2.h"
31 
32 #include <sstream>
33 
34 PRAGMA48(GCC diagnostic push)
35 PRAGMA48(GCC diagnostic ignored "-Wshadow")
36 #ifndef SDL_BIG_ENDIAN
37 #include <SDL_endian.h>
38 #endif // SDL_BYTEORDER
39 PRAGMA48(GCC diagnostic pop)
40 
41 #include "debug.h"
42 
43 Dye::Dye(const std::string &restrict description)
44 {
45  for (int i = 0; i < dyePalateSize; ++i)
46  mDyePalettes[i] = nullptr;
47 
48  if (description.empty())
49  return;
50 
51  size_t next_pos = 0;
52  const size_t length = description.length();
53  do
54  {
55  const size_t pos = next_pos;
56  next_pos = description.find(';', pos);
57 
58  if (next_pos == std::string::npos)
59  next_pos = length;
60 
61  if (next_pos <= pos + 3 || description[pos + 1] != ':')
62  {
63  logger->log("Error, invalid dye: %s", description.c_str());
64  return;
65  }
66 
67  int i = 0;
68 
69  switch (description[pos])
70  {
71  case 'R': i = 0; break;
72  case 'G': i = 1; break;
73  case 'Y': i = 2; break;
74  case 'B': i = 3; break;
75  case 'M': i = 4; break;
76  case 'C': i = 5; break;
77  case 'W': i = 6; break;
78  case 'S': i = 7; break;
79  case 'A': i = 8; break;
80  default:
81  logger->log("Error, invalid dye: %s", description.c_str());
82  return;
83  }
84  mDyePalettes[i] = new DyePalette(description.substr(
85  pos + 2, next_pos - pos - 2), i != 8 ? 6 : 8);
86  ++next_pos;
87  }
88  while (next_pos < length);
89 }
90 
92 {
93  for (int i = 0; i < dyePalateSize; ++i)
95 }
96 
97 void Dye::instantiate(std::string &restrict target,
98  const std::string &restrict palettes)
99 {
100  size_t next_pos = target.find('|');
101 
102  if (next_pos == std::string::npos || palettes.empty())
103  return;
104 
105  ++next_pos;
106 
107  std::ostringstream s;
108  s << target.substr(0, next_pos);
109  size_t last_pos = target.length();
110  size_t pal_pos = 0;
111  do
112  {
113  const size_t pos = next_pos;
114  next_pos = target.find(';', pos);
115 
116  if (next_pos == std::string::npos)
117  next_pos = last_pos;
118 
119  if (next_pos == pos + 1 && pal_pos != std::string::npos)
120  {
121  const size_t pal_next_pos = palettes.find(';', pal_pos);
122  s << target[pos] << ':';
123  if (pal_next_pos == std::string::npos)
124  {
125  s << palettes.substr(pal_pos);
126  s << target.substr(next_pos);
127  break;
128  }
129  s << palettes.substr(pal_pos, pal_next_pos - pal_pos);
130  pal_pos = pal_next_pos + 1;
131  }
132  else if (next_pos > pos + 2)
133  {
134  s << target.substr(pos, next_pos - pos);
135  }
136  else
137  {
138  logger->log("Error, invalid dye placeholder: %s", target.c_str());
139  return;
140  }
141  s << target[next_pos];
142  ++next_pos;
143  }
144  while (next_pos < last_pos);
145 
146  target = s.str();
147 }
148 
150 {
151  if (mDyePalettes[sPaleteIndex] != nullptr)
152  return 1;
153  if (mDyePalettes[aPaleteIndex] != nullptr)
154  return 2;
155  return 0;
156 }
157 
158 void Dye::normalDye(uint32_t *restrict pixels,
159  const int bufSize) const restrict2
160 {
161  if (pixels == nullptr)
162  return;
163 
164  for (const uint32_t *const p_end = pixels + CAST_SIZE(bufSize);
165  pixels != p_end;
166  ++ pixels)
167  {
168  const uint32_t p = *pixels;
169 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
170  const int alpha = p & 0xff000000;
171 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
172 
173  const int alpha = p & 0xff;
174 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
175 
176  if (alpha == 0)
177  continue;
178  unsigned int color[3];
179 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
180  color[0] = (p) & 255U;
181  color[1] = (p >> 8U) & 255U;
182  color[2] = (p >> 16U) & 255U;
183 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
184 
185  color[0] = (p >> 24U) & 255U;
186  color[1] = (p >> 16U) & 255U;
187  color[2] = (p >> 8U) & 255U;
188 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
189 
190  const unsigned int cmax = std::max(
191  color[0], std::max(color[1], color[2]));
192  if (cmax == 0)
193  continue;
194 
195  const unsigned int cmin = std::min(
196  color[0], std::min(color[1], color[2]));
197  const unsigned int intensity = color[0] + color[1] + color[2];
198 
199  if (cmin != cmax && (cmin != 0 || (intensity != cmax
200  && intensity != 2 * cmax)))
201  {
202  // not pure
203  continue;
204  }
205 
206  const unsigned int i = static_cast<int>(color[0] != 0) |
207  (static_cast<int>(color[1] != 0) << 1) |
208  (static_cast<int>(color[2] != 0) << 2);
209 
210  if (mDyePalettes[i - 1] != nullptr)
211  mDyePalettes[i - 1]->getColor(cmax, color);
212 
213 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
214  *pixels = (color[0]) | (color[1] << 8)
215  | (color[2] << 16) | alpha;
216 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
217 
218  *pixels = (color[0] << 24) | (color[1] << 16)
219  | (color[2] << 8) | alpha;
220 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
221  }
222 }
223 
224 void Dye::normalOGLDye(uint32_t *restrict pixels,
225  const int bufSize) const restrict2
226 {
227  if (pixels == nullptr)
228  return;
229 
230  for (const uint32_t *const p_end = pixels + CAST_SIZE(bufSize);
231  pixels != p_end;
232  ++ pixels)
233  {
234  const uint32_t p = *pixels;
235 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
236  const uint32_t alpha = p & 255U;
237 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
238 
239  const uint32_t alpha = p & 0xff000000U;
240 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
241 
242  if (alpha == 0)
243  continue;
244  unsigned int color[3];
245 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
246  color[0] = (p >> 24U) & 255U;
247  color[1] = (p >> 16U) & 255U;
248  color[2] = (p >> 8U) & 255U;
249 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
250 
251  color[0] = (p) & 255U;
252  color[1] = (p >> 8U) & 255U;
253  color[2] = (p >> 16U) & 255U;
254 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
255 
256  const unsigned int cmax = std::max(
257  color[0], std::max(color[1], color[2]));
258  if (cmax == 0)
259  continue;
260 
261  const unsigned int cmin = std::min(
262  color[0], std::min(color[1], color[2]));
263  const unsigned int intensity = color[0] + color[1] + color[2];
264 
265  if (cmin != cmax && (cmin != 0 || (intensity != cmax
266  && intensity != 2 * cmax)))
267  {
268  // not pure
269  continue;
270  }
271 
272  const unsigned int i = static_cast<int>(color[0] != 0) |
273  (static_cast<int>(color[1] != 0) << 1) |
274  (static_cast<int>(color[2] != 0) << 2);
275 
276  if (mDyePalettes[i - 1] != nullptr)
277  mDyePalettes[i - 1]->getColor(cmax, color);
278 
279 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
280  *pixels = (color[0] << 24) | (color[1] << 16)
281  | (color[2] << 8) | alpha;
282 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
283 
284  *pixels = (color[0]) | (color[1] << 8)
285  | (color[2] << 16) | alpha;
286 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
287  }
288 }
#define CAST_SIZE
Definition: cast.h:34
Dye(const std::string &dye)
Definition: dye.cpp:43
static void instantiate(std::string &target, const std::string &palettes)
Definition: dye.cpp:97
void normalDye(uint32_t *pixels, const int bufSize) const
Definition: dye.cpp:158
void normalOGLDye(uint32_t *pixels, const int bufSize) const
Definition: dye.cpp:224
DyePalette * mDyePalettes[dyePalateSize]
Definition: dye.h:93
int getType() const
Definition: dye.cpp:149
~Dye()
Definition: dye.cpp:91
void log(const char *const log_text,...)
Definition: logger.cpp:269
#define delete2(var)
Definition: delete2.h:25
const int aPaleteIndex
Definition: dye.h:35
const int sPaleteIndex
Definition: dye.h:34
const int dyePalateSize
Definition: dye.h:33
#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