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