linter
This commit is contained in:
@@ -14,14 +14,89 @@ inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) {
|
||||
buffer += size;
|
||||
}
|
||||
|
||||
// Inicializa el diccionario LZW con los valores iniciales
|
||||
inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int code_length, int& dictionary_ind) {
|
||||
int size = 1 << code_length;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
for (dictionary_ind = 0; dictionary_ind < size; dictionary_ind++) {
|
||||
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
||||
dictionary[dictionary_ind].prev = -1;
|
||||
dictionary[dictionary_ind].len = 1;
|
||||
}
|
||||
dictionary_ind += 2; // Reservamos espacio para clear y stop codes
|
||||
}
|
||||
|
||||
// Lee los próximos bits del stream de entrada para formar un código
|
||||
inline int readNextCode(const uint8_t*& input, int& input_length, unsigned int& mask, int code_length) {
|
||||
int code = 0;
|
||||
for (int i = 0; i < (code_length + 1); i++) {
|
||||
if (input_length <= 0) {
|
||||
throw std::runtime_error("Unexpected end of input in decompress");
|
||||
}
|
||||
int bit = ((*input & mask) != 0) ? 1 : 0;
|
||||
mask <<= 1;
|
||||
if (mask == 0x100) {
|
||||
mask = 0x01;
|
||||
input++;
|
||||
input_length--;
|
||||
}
|
||||
code |= (bit << i);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// Encuentra el primer byte de una cadena del diccionario
|
||||
inline uint8_t findFirstByte(const std::vector<DictionaryEntry>& dictionary, int code) {
|
||||
int ptr = code;
|
||||
while (dictionary[ptr].prev != -1) {
|
||||
ptr = dictionary[ptr].prev;
|
||||
}
|
||||
return dictionary[ptr].byte;
|
||||
}
|
||||
|
||||
// Agrega una nueva entrada al diccionario
|
||||
inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& dictionary_ind,
|
||||
int& code_length, int prev, int code) {
|
||||
uint8_t first_byte;
|
||||
if (code == dictionary_ind) {
|
||||
first_byte = findFirstByte(dictionary, prev);
|
||||
} else {
|
||||
first_byte = findFirstByte(dictionary, code);
|
||||
}
|
||||
|
||||
dictionary[dictionary_ind].byte = first_byte;
|
||||
dictionary[dictionary_ind].prev = prev;
|
||||
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
|
||||
dictionary_ind++;
|
||||
|
||||
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11)) {
|
||||
code_length++;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Escribe la cadena decodificada al buffer de salida
|
||||
inline int writeDecodedString(const std::vector<DictionaryEntry>& dictionary, int code, uint8_t*& out) {
|
||||
int cur_code = code;
|
||||
int match_len = dictionary[cur_code].len;
|
||||
while (cur_code != -1) {
|
||||
out[dictionary[cur_code].len - 1] = dictionary[cur_code].byte;
|
||||
if (dictionary[cur_code].prev == cur_code) {
|
||||
std::cerr << "Internal error; self-reference detected." << std::endl;
|
||||
throw std::runtime_error("Internal error in decompress: self-reference");
|
||||
}
|
||||
cur_code = dictionary[cur_code].prev;
|
||||
}
|
||||
out += match_len;
|
||||
return match_len;
|
||||
}
|
||||
|
||||
void Gif::decompress(int code_length, const uint8_t* input, int input_length, uint8_t* out) {
|
||||
// Verifica que el code_length tenga un rango razonable.
|
||||
if (code_length < 2 || code_length > 12) {
|
||||
throw std::runtime_error("Invalid LZW code length");
|
||||
}
|
||||
|
||||
int i;
|
||||
int bit;
|
||||
int prev = -1;
|
||||
std::vector<DictionaryEntry> dictionary;
|
||||
int dictionary_ind;
|
||||
@@ -29,48 +104,22 @@ void Gif::decompress(int code_length, const uint8_t* input, int input_length, ui
|
||||
int reset_code_length = code_length;
|
||||
int clear_code = 1 << code_length;
|
||||
int stop_code = clear_code + 1;
|
||||
int match_len = 0;
|
||||
|
||||
// Inicializamos el diccionario con el tamaño correspondiente.
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
|
||||
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
||||
dictionary[dictionary_ind].prev = -1;
|
||||
dictionary[dictionary_ind].len = 1;
|
||||
}
|
||||
dictionary_ind += 2; // Reservamos espacio para clear y stop codes
|
||||
initializeDictionary(dictionary, code_length, dictionary_ind);
|
||||
|
||||
// Bucle principal: procesar el stream comprimido.
|
||||
while (input_length > 0) {
|
||||
int code = 0;
|
||||
// Lee (code_length + 1) bits para formar el código.
|
||||
for (i = 0; i < (code_length + 1); i++) {
|
||||
if (input_length <= 0) {
|
||||
throw std::runtime_error("Unexpected end of input in decompress");
|
||||
}
|
||||
bit = ((*input & mask) != 0) ? 1 : 0;
|
||||
mask <<= 1;
|
||||
if (mask == 0x100) {
|
||||
mask = 0x01;
|
||||
input++;
|
||||
input_length--;
|
||||
}
|
||||
code |= (bit << i);
|
||||
}
|
||||
int code = readNextCode(input, input_length, mask, code_length);
|
||||
|
||||
if (code == clear_code) {
|
||||
// Reinicia el diccionario.
|
||||
code_length = reset_code_length;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
|
||||
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
||||
dictionary[dictionary_ind].prev = -1;
|
||||
dictionary[dictionary_ind].len = 1;
|
||||
}
|
||||
dictionary_ind += 2;
|
||||
initializeDictionary(dictionary, code_length, dictionary_ind);
|
||||
prev = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (code == stop_code) {
|
||||
break;
|
||||
}
|
||||
@@ -82,28 +131,7 @@ void Gif::decompress(int code_length, const uint8_t* input, int input_length, ui
|
||||
throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
|
||||
}
|
||||
|
||||
int ptr;
|
||||
if (code == dictionary_ind) {
|
||||
ptr = prev;
|
||||
while (dictionary[ptr].prev != -1) {
|
||||
ptr = dictionary[ptr].prev;
|
||||
}
|
||||
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
||||
} else {
|
||||
ptr = code;
|
||||
while (dictionary[ptr].prev != -1) {
|
||||
ptr = dictionary[ptr].prev;
|
||||
}
|
||||
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
||||
}
|
||||
dictionary[dictionary_ind].prev = prev;
|
||||
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
|
||||
dictionary_ind++;
|
||||
|
||||
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11)) {
|
||||
code_length++;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
}
|
||||
addDictionaryEntry(dictionary, dictionary_ind, code_length, prev, code);
|
||||
}
|
||||
|
||||
prev = code;
|
||||
@@ -115,18 +143,7 @@ void Gif::decompress(int code_length, const uint8_t* input, int input_length, ui
|
||||
throw std::runtime_error("LZW error: invalid code encountered");
|
||||
}
|
||||
|
||||
int cur_code = code; // Variable temporal para recorrer la cadena.
|
||||
match_len = dictionary[cur_code].len;
|
||||
while (cur_code != -1) {
|
||||
// Se asume que dictionary[curCode].len > 0.
|
||||
out[dictionary[cur_code].len - 1] = dictionary[cur_code].byte;
|
||||
if (dictionary[cur_code].prev == cur_code) {
|
||||
std::cerr << "Internal error; self-reference detected." << std::endl;
|
||||
throw std::runtime_error("Internal error in decompress: self-reference");
|
||||
}
|
||||
cur_code = dictionary[cur_code].prev;
|
||||
}
|
||||
out += match_len;
|
||||
writeDecodedString(dictionary, code, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class OpenGLShader : public ShaderBackend {
|
||||
|
||||
void render() override;
|
||||
void setTextureSize(float width, float height) override;
|
||||
void cleanup() override;
|
||||
void cleanup() final;
|
||||
bool isHardwareAccelerated() const override { return is_initialized_; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -127,10 +127,9 @@ SurfaceData Surface::loadSurface(const std::string& file_path) {
|
||||
}
|
||||
|
||||
// Crear un objeto Gif y llamar a la función loadGif
|
||||
GIF::Gif gif;
|
||||
Uint16 w = 0;
|
||||
Uint16 h = 0;
|
||||
std::vector<Uint8> raw_pixels = gif.loadGif(buffer.data(), w, h);
|
||||
std::vector<Uint8> raw_pixels = GIF::Gif::loadGif(buffer.data(), w, h);
|
||||
if (raw_pixels.empty()) {
|
||||
std::cerr << "Error loading GIF from file: " << file_path << std::endl;
|
||||
throw std::runtime_error("Error loading GIF");
|
||||
@@ -336,6 +335,24 @@ void Surface::render(int x, int y, SDL_FRect* src_rect, SDL_FlipMode flip) {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper para calcular coordenadas con flip
|
||||
void Surface::calculateFlippedCoords(int ix, int iy, float sx, float sy, float w, float h, SDL_FlipMode flip, int& src_x, int& src_y) {
|
||||
src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + w - 1 - ix) : (sx + ix);
|
||||
src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + h - 1 - iy) : (sy + iy);
|
||||
}
|
||||
|
||||
// Helper para copiar un pixel si no es transparente
|
||||
void Surface::copyPixelIfNotTransparent(Uint8* dest_data, int dest_x, int dest_y, int dest_width, int src_x, int src_y) const {
|
||||
if (dest_x < 0 || dest_y < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
|
||||
if (color != transparent_color_) {
|
||||
dest_data[dest_x + (dest_y * dest_width)] = sub_palette_[color];
|
||||
}
|
||||
}
|
||||
|
||||
// Copia una región de la superficie de origen a la de destino
|
||||
void Surface::render(SDL_FRect* src_rect, SDL_FRect* dst_rect, SDL_FlipMode flip) {
|
||||
auto surface_data = Screen::get()->getRendererSurface()->getSurfaceData();
|
||||
@@ -370,19 +387,16 @@ void Surface::render(SDL_FRect* src_rect, SDL_FRect* dst_rect, SDL_FlipMode flip
|
||||
// Renderiza píxel por píxel aplicando el flip si es necesario
|
||||
for (int iy = 0; iy < final_height; ++iy) {
|
||||
for (int ix = 0; ix < final_width; ++ix) {
|
||||
// Coordenadas de origen
|
||||
int src_x = (flip == SDL_FLIP_HORIZONTAL) ? (sx + final_width - 1 - ix) : (sx + ix);
|
||||
int src_y = (flip == SDL_FLIP_VERTICAL) ? (sy + final_height - 1 - iy) : (sy + iy);
|
||||
int src_x = 0;
|
||||
int src_y = 0;
|
||||
calculateFlippedCoords(ix, iy, sx, sy, final_width, final_height, flip, src_x, src_y);
|
||||
|
||||
// Coordenadas de destino
|
||||
if (int dest_x = dx + ix; dest_x >= 0 && dest_x < surface_data->width) {
|
||||
if (int dest_y = dy + iy; dest_y >= 0 && dest_y < surface_data->height) {
|
||||
// Copiar el píxel si no es transparente
|
||||
Uint8 color = surface_data_->data.get()[static_cast<size_t>(src_x + (src_y * surface_data_->width))];
|
||||
if (color != transparent_color_) {
|
||||
surface_data->data[dest_x + (dest_y * surface_data->width)] = sub_palette_[color];
|
||||
}
|
||||
}
|
||||
int dest_x = dx + ix;
|
||||
int dest_y = dy + iy;
|
||||
|
||||
// Verificar límites de destino antes de copiar
|
||||
if (dest_x >= 0 && dest_x < surface_data->width && dest_y >= 0 && dest_y < surface_data->height) {
|
||||
copyPixelIfNotTransparent(surface_data->data.get(), dest_x, dest_y, surface_data->width, src_x, src_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class Surface {
|
||||
|
||||
// Copia una región de la SurfaceData de origen a la SurfaceData de destino
|
||||
void render(float dx, float dy, float sx, float sy, float w, float h);
|
||||
void render(int x, int y, SDL_FRect* clip = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
||||
void render(int x, int y, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
||||
void render(SDL_FRect* src_rect = nullptr, SDL_FRect* dst_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
||||
|
||||
// Copia una región de la SurfaceData de origen a la SurfaceData de destino reemplazando un color por otro
|
||||
@@ -130,4 +130,11 @@ class Surface {
|
||||
|
||||
// Inicializa la sub paleta
|
||||
static void initializeSubPalette(SubPalette& palette) { std::iota(palette.begin(), palette.end(), 0); }
|
||||
|
||||
private:
|
||||
// Helper para calcular coordenadas con flip
|
||||
static void calculateFlippedCoords(int ix, int iy, float sx, float sy, float w, float h, SDL_FlipMode flip, int& src_x, int& src_y);
|
||||
|
||||
// Helper para copiar un pixel si no es transparente
|
||||
void copyPixelIfNotTransparent(Uint8* dest_data, int dest_x, int dest_y, int dest_width, int src_x, int src_y) const;
|
||||
};
|
||||
|
||||
@@ -135,6 +135,96 @@ void SurfaceAnimatedSprite::resetAnimation() {
|
||||
animations_[current_animation_].completed = false;
|
||||
}
|
||||
|
||||
// Helper: Parsea los parámetros de configuración globales (frame_width, frame_height)
|
||||
bool parseGlobalParameter(const std::string& line, float& frame_width, float& frame_height) {
|
||||
size_t pos = line.find("=");
|
||||
if (pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = line.substr(0, pos);
|
||||
int value = std::stoi(line.substr(pos + 1));
|
||||
|
||||
if (key == "frame_width") {
|
||||
frame_width = value;
|
||||
return true;
|
||||
}
|
||||
if (key == "frame_height") {
|
||||
frame_height = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper: Parsea los frames de una animación desde una cadena separada por comas
|
||||
void parseAnimationFrames(const std::string& value, AnimationData& animation,
|
||||
float frame_width, float frame_height,
|
||||
int frames_per_row, int max_tiles) {
|
||||
std::stringstream ss(value);
|
||||
std::string tmp;
|
||||
SDL_FRect rect = {0.0F, 0.0F, frame_width, frame_height};
|
||||
|
||||
while (getline(ss, tmp, ',')) {
|
||||
const int NUM_TILE = std::stoi(tmp);
|
||||
if (NUM_TILE <= max_tiles) {
|
||||
rect.x = (NUM_TILE % frames_per_row) * frame_width;
|
||||
rect.y = (NUM_TILE / frames_per_row) * frame_height;
|
||||
animation.frames.emplace_back(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: Parsea un parámetro de animación individual
|
||||
bool parseAnimationParameter(const std::string& key, const std::string& value,
|
||||
AnimationData& animation,
|
||||
float frame_width, float frame_height,
|
||||
int frames_per_row, int max_tiles) {
|
||||
if (key == "name") {
|
||||
animation.name = value;
|
||||
return true;
|
||||
}
|
||||
if (key == "speed") {
|
||||
animation.speed = std::stoi(value);
|
||||
return true;
|
||||
}
|
||||
if (key == "loop") {
|
||||
animation.loop = std::stoi(value);
|
||||
return true;
|
||||
}
|
||||
if (key == "frames") {
|
||||
parseAnimationFrames(value, animation, frame_width, frame_height, frames_per_row, max_tiles);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper: Parsea una animación completa
|
||||
AnimationData parseAnimation(const Animations& animations, size_t& index,
|
||||
float frame_width, float frame_height,
|
||||
int frames_per_row, int max_tiles) {
|
||||
AnimationData animation;
|
||||
std::string line;
|
||||
|
||||
do {
|
||||
index++;
|
||||
line = animations.at(index);
|
||||
size_t pos = line.find("=");
|
||||
|
||||
if (pos != std::string::npos) {
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1);
|
||||
parseAnimationParameter(key, value, animation, frame_width, frame_height,
|
||||
frames_per_row, max_tiles);
|
||||
}
|
||||
} while (line != "[/animation]");
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
// Carga la animación desde un vector de cadenas
|
||||
void SurfaceAnimatedSprite::setAnimations(const Animations& animations) {
|
||||
float frame_width = 1.0F;
|
||||
@@ -148,21 +238,7 @@ void SurfaceAnimatedSprite::setAnimations(const Animations& animations) {
|
||||
|
||||
// Parsea el fichero para buscar variables y valores
|
||||
if (line != "[animation]") {
|
||||
// Encuentra la posición del caracter '='
|
||||
size_t pos = line.find("=");
|
||||
|
||||
// Procesa las dos subcadenas
|
||||
if (pos != std::string::npos) {
|
||||
std::string key = line.substr(0, pos);
|
||||
int value = std::stoi(line.substr(pos + 1));
|
||||
if (key == "frame_width") {
|
||||
frame_width = value;
|
||||
} else if (key == "frame_height") {
|
||||
frame_height = value;
|
||||
} else {
|
||||
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||
}
|
||||
|
||||
if (parseGlobalParameter(line, frame_width, frame_height)) {
|
||||
frames_per_row = surface_->getWidth() / frame_width;
|
||||
const int W = surface_->getWidth() / frame_width;
|
||||
const int H = surface_->getHeight() / frame_height;
|
||||
@@ -172,45 +248,8 @@ void SurfaceAnimatedSprite::setAnimations(const Animations& animations) {
|
||||
|
||||
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
|
||||
if (line == "[animation]") {
|
||||
AnimationData animation;
|
||||
do {
|
||||
index++;
|
||||
line = animations.at(index);
|
||||
size_t pos = line.find("=");
|
||||
|
||||
if (pos != std::string::npos) {
|
||||
std::string key = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 1);
|
||||
|
||||
if (key == "name") {
|
||||
animation.name = value;
|
||||
} else if (key == "speed") {
|
||||
animation.speed = std::stoi(value);
|
||||
} else if (key == "loop") {
|
||||
animation.loop = std::stoi(value);
|
||||
} else if (key == "frames") {
|
||||
// Se introducen los valores separados por comas en un vector
|
||||
std::stringstream ss(value);
|
||||
std::string tmp;
|
||||
SDL_FRect rect = {0.0F, 0.0F, frame_width, frame_height};
|
||||
while (getline(ss, tmp, ',')) {
|
||||
// Comprueba que el tile no sea mayor que el maximo indice permitido
|
||||
const int NUM_TILE = std::stoi(tmp);
|
||||
if (NUM_TILE <= max_tiles) {
|
||||
rect.x = (NUM_TILE % frames_per_row) * frame_width;
|
||||
rect.y = (NUM_TILE / frames_per_row) * frame_height;
|
||||
animation.frames.emplace_back(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
std::cout << "Warning: unknown parameter " << key << std::endl;
|
||||
}
|
||||
}
|
||||
} while (line != "[/animation]");
|
||||
|
||||
// Añade la animación al vector de animaciones
|
||||
AnimationData animation = parseAnimation(animations, index, frame_width, frame_height,
|
||||
frames_per_row, max_tiles);
|
||||
animations_.emplace_back(animation);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user