Update external libraries

This commit is contained in:
Ray 2020-02-06 16:29:57 +01:00
parent ea40bda88c
commit 6c7685da3f
7 changed files with 886 additions and 503 deletions

406
src/external/cgltf.h vendored
View file

@ -1,7 +1,7 @@
/**
* cgltf - a single-file glTF 2.0 parser written in C99.
*
* Version: 1.4
* Version: 1.5
*
* Website: https://github.com/jkuhlmann/cgltf
*
@ -24,8 +24,8 @@
*
* `cgltf_options` is the struct passed to `cgltf_parse()` to control
* parts of the parsing process. You can use it to force the file type
* and provide memory allocation callbacks. Should be zero-initialized
* to trigger default behavior.
* and provide memory allocation as well as file operation callbacks.
* Should be zero-initialized to trigger default behavior.
*
* `cgltf_data` is the struct allocated and filled by `cgltf_parse()`.
* It generally mirrors the glTF format as described by the spec (see
@ -72,6 +72,11 @@
* size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns
* false if the passed-in element_size is too small, or if the accessor is sparse.
*
* `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading
* vector types and does not support matrix types. The passed-in element size is the number of uints
* in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in
* element_size is too small, or if the accessor is sparse.
*
* `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
* and only works with single-component data types.
*
@ -96,6 +101,7 @@ extern "C" {
typedef size_t cgltf_size;
typedef float cgltf_float;
typedef int cgltf_int;
typedef unsigned int cgltf_uint;
typedef int cgltf_bool;
typedef enum cgltf_file_type
@ -105,15 +111,6 @@ typedef enum cgltf_file_type
cgltf_file_type_glb,
} cgltf_file_type;
typedef struct cgltf_options
{
cgltf_file_type type; /* invalid == auto detect */
cgltf_size json_token_count; /* 0 == auto */
void* (*memory_alloc)(void* user, cgltf_size size);
void (*memory_free) (void* user, void* ptr);
void* memory_user_data;
} cgltf_options;
typedef enum cgltf_result
{
cgltf_result_success,
@ -128,6 +125,28 @@ typedef enum cgltf_result
cgltf_result_legacy_gltf,
} cgltf_result;
typedef struct cgltf_memory_options
{
void* (*alloc)(void* user, cgltf_size size);
void (*free) (void* user, void* ptr);
void* user_data;
} cgltf_memory_options;
typedef struct cgltf_file_options
{
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
void* user_data;
} cgltf_file_options;
typedef struct cgltf_options
{
cgltf_file_type type; /* invalid == auto detect */
cgltf_size json_token_count; /* 0 == auto */
cgltf_memory_options memory;
cgltf_file_options file;
} cgltf_options;
typedef enum cgltf_buffer_view_type
{
cgltf_buffer_view_type_invalid,
@ -560,8 +579,8 @@ typedef struct cgltf_data
const void* bin;
cgltf_size bin_size;
void (*memory_free) (void* user, void* ptr);
void* memory_user_data;
cgltf_memory_options memory;
cgltf_file_options file;
} cgltf_data;
cgltf_result cgltf_parse(
@ -591,6 +610,7 @@ void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
cgltf_size cgltf_num_components(cgltf_type type);
@ -713,7 +733,7 @@ static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_siz
{
return NULL;
}
void* result = options->memory_alloc(options->memory_user_data, element_size * count);
void* result = options->memory.alloc(options->memory.user_data, element_size * count);
if (!result)
{
return NULL;
@ -722,6 +742,71 @@ static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_siz
return result;
}
static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data)
{
(void)file_options;
void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc ? memory_options->alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = memory_options->free ? memory_options->free : &cgltf_default_free;
FILE* file = fopen(path, "rb");
if (!file)
{
return cgltf_result_file_not_found;
}
cgltf_size file_size = size ? *size : 0;
if (file_size == 0)
{
fseek(file, 0, SEEK_END);
long length = ftell(file);
if (length < 0)
{
fclose(file);
return cgltf_result_io_error;
}
fseek(file, 0, SEEK_SET);
file_size = (cgltf_size)length;
}
char* file_data = (char*)memory_alloc(memory_options->user_data, file_size);
if (!file_data)
{
fclose(file);
return cgltf_result_out_of_memory;
}
cgltf_size read_size = fread(file_data, 1, file_size, file);
fclose(file);
if (read_size != file_size)
{
memory_free(memory_options->user_data, file_data);
return cgltf_result_io_error;
}
if (size)
{
*size = file_size;
}
if (data)
{
*data = file_data;
}
return cgltf_result_success;
}
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
{
(void)file_options;
void (*memfree)(void*, void*) = memory_options->free ? memory_options->free : &cgltf_default_free;
memfree(memory_options->user_data, data);
}
static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data)
@ -737,13 +822,13 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s
}
cgltf_options fixed_options = *options;
if (fixed_options.memory_alloc == NULL)
if (fixed_options.memory.alloc == NULL)
{
fixed_options.memory_alloc = &cgltf_default_alloc;
fixed_options.memory.alloc = &cgltf_default_alloc;
}
if (fixed_options.memory_free == NULL)
if (fixed_options.memory.free == NULL)
{
fixed_options.memory_free = &cgltf_default_free;
fixed_options.memory.free = &cgltf_default_free;
}
uint32_t tmp;
@ -863,49 +948,23 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
return cgltf_result_invalid_options;
}
void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free;
void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
FILE* file = fopen(path, "rb");
if (!file)
void* file_data = NULL;
cgltf_size file_size = 0;
cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
if (result != cgltf_result_success)
{
return cgltf_result_file_not_found;
return result;
}
fseek(file, 0, SEEK_END);
long length = ftell(file);
if (length < 0)
{
fclose(file);
return cgltf_result_io_error;
}
fseek(file, 0, SEEK_SET);
char* file_data = (char*)memory_alloc(options->memory_user_data, length);
if (!file_data)
{
fclose(file);
return cgltf_result_out_of_memory;
}
cgltf_size file_size = (cgltf_size)length;
cgltf_size read_size = fread(file_data, 1, file_size, file);
fclose(file);
if (read_size != file_size)
{
memory_free(options->memory_user_data, file_data);
return cgltf_result_io_error;
}
cgltf_result result = cgltf_parse(options, file_data, file_size, out_data);
result = cgltf_parse(options, file_data, file_size, out_data);
if (result != cgltf_result_success)
{
memory_free(options->memory_user_data, file_data);
memory_free(options->memory.user_data, file_data);
return result;
}
@ -935,10 +994,11 @@ static void cgltf_combine_paths(char* path, const char* base, const char* uri)
static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data)
{
void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free;
void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
char* path = (char*)memory_alloc(options->memory_user_data, strlen(uri) + strlen(gltf_path) + 1);
char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
if (!path)
{
return cgltf_result_out_of_memory;
@ -946,30 +1006,11 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s
cgltf_combine_paths(path, gltf_path, uri);
FILE* file = fopen(path, "rb");
memory_free(options->memory_user_data, path);
if (!file)
void* file_data = NULL;
cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
if (result != cgltf_result_success)
{
return cgltf_result_file_not_found;
}
char* file_data = (char*)memory_alloc(options->memory_user_data, size);
if (!file_data)
{
fclose(file);
return cgltf_result_out_of_memory;
}
cgltf_size read_size = fread(file_data, 1, size, file);
fclose(file);
if (read_size != size)
{
memory_free(options->memory_user_data, file_data);
return cgltf_result_io_error;
return result;
}
*out_data = file_data;
@ -979,10 +1020,10 @@ static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_s
cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
{
void* (*memory_alloc)(void*, cgltf_size) = options->memory_alloc ? options->memory_alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory_free ? options->memory_free : &cgltf_default_free;
void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc ? options->memory.alloc : &cgltf_default_alloc;
void (*memory_free)(void*, void*) = options->memory.free ? options->memory.free : &cgltf_default_free;
unsigned char* data = (unsigned char*)memory_alloc(options->memory_user_data, size);
unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size);
if (!data)
{
return cgltf_result_out_of_memory;
@ -1007,7 +1048,7 @@ cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size s
if (index < 0)
{
memory_free(options->memory_user_data, data);
memory_free(options->memory.user_data, data);
return cgltf_result_io_error;
}
@ -1372,155 +1413,157 @@ void cgltf_free(cgltf_data* data)
return;
}
data->memory_free(data->memory_user_data, data->asset.copyright);
data->memory_free(data->memory_user_data, data->asset.generator);
data->memory_free(data->memory_user_data, data->asset.version);
data->memory_free(data->memory_user_data, data->asset.min_version);
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
data->memory_free(data->memory_user_data, data->accessors);
data->memory_free(data->memory_user_data, data->buffer_views);
data->memory.free(data->memory.user_data, data->asset.copyright);
data->memory.free(data->memory.user_data, data->asset.generator);
data->memory.free(data->memory.user_data, data->asset.version);
data->memory.free(data->memory.user_data, data->asset.min_version);
data->memory.free(data->memory.user_data, data->accessors);
data->memory.free(data->memory.user_data, data->buffer_views);
for (cgltf_size i = 0; i < data->buffers_count; ++i)
{
if (data->buffers[i].data != data->bin)
{
data->memory_free(data->memory_user_data, data->buffers[i].data);
file_release(&data->memory, &data->file, data->buffers[i].data);
}
data->memory_free(data->memory_user_data, data->buffers[i].uri);
data->memory.free(data->memory.user_data, data->buffers[i].uri);
}
data->memory_free(data->memory_user_data, data->buffers);
data->memory.free(data->memory.user_data, data->buffers);
for (cgltf_size i = 0; i < data->meshes_count; ++i)
{
data->memory_free(data->memory_user_data, data->meshes[i].name);
data->memory.free(data->memory.user_data, data->meshes[i].name);
for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
{
for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
{
data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes[k].name);
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
}
data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].attributes);
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].attributes);
for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
{
for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
{
data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
}
data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets[k].attributes);
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
}
data->memory_free(data->memory_user_data, data->meshes[i].primitives[j].targets);
data->memory.free(data->memory.user_data, data->meshes[i].primitives[j].targets);
}
data->memory_free(data->memory_user_data, data->meshes[i].primitives);
data->memory_free(data->memory_user_data, data->meshes[i].weights);
data->memory.free(data->memory.user_data, data->meshes[i].primitives);
data->memory.free(data->memory.user_data, data->meshes[i].weights);
for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
{
data->memory_free(data->memory_user_data, data->meshes[i].target_names[j]);
data->memory.free(data->memory.user_data, data->meshes[i].target_names[j]);
}
data->memory_free(data->memory_user_data, data->meshes[i].target_names);
data->memory.free(data->memory.user_data, data->meshes[i].target_names);
}
data->memory_free(data->memory_user_data, data->meshes);
data->memory.free(data->memory.user_data, data->meshes);
for (cgltf_size i = 0; i < data->materials_count; ++i)
{
data->memory_free(data->memory_user_data, data->materials[i].name);
data->memory.free(data->memory.user_data, data->materials[i].name);
}
data->memory_free(data->memory_user_data, data->materials);
data->memory.free(data->memory.user_data, data->materials);
for (cgltf_size i = 0; i < data->images_count; ++i)
{
data->memory_free(data->memory_user_data, data->images[i].name);
data->memory_free(data->memory_user_data, data->images[i].uri);
data->memory_free(data->memory_user_data, data->images[i].mime_type);
data->memory.free(data->memory.user_data, data->images[i].name);
data->memory.free(data->memory.user_data, data->images[i].uri);
data->memory.free(data->memory.user_data, data->images[i].mime_type);
}
data->memory_free(data->memory_user_data, data->images);
data->memory.free(data->memory.user_data, data->images);
for (cgltf_size i = 0; i < data->textures_count; ++i)
{
data->memory_free(data->memory_user_data, data->textures[i].name);
data->memory.free(data->memory.user_data, data->textures[i].name);
}
data->memory_free(data->memory_user_data, data->textures);
data->memory.free(data->memory.user_data, data->textures);
data->memory_free(data->memory_user_data, data->samplers);
data->memory.free(data->memory.user_data, data->samplers);
for (cgltf_size i = 0; i < data->skins_count; ++i)
{
data->memory_free(data->memory_user_data, data->skins[i].name);
data->memory_free(data->memory_user_data, data->skins[i].joints);
data->memory.free(data->memory.user_data, data->skins[i].name);
data->memory.free(data->memory.user_data, data->skins[i].joints);
}
data->memory_free(data->memory_user_data, data->skins);
data->memory.free(data->memory.user_data, data->skins);
for (cgltf_size i = 0; i < data->cameras_count; ++i)
{
data->memory_free(data->memory_user_data, data->cameras[i].name);
data->memory.free(data->memory.user_data, data->cameras[i].name);
}
data->memory_free(data->memory_user_data, data->cameras);
data->memory.free(data->memory.user_data, data->cameras);
for (cgltf_size i = 0; i < data->lights_count; ++i)
{
data->memory_free(data->memory_user_data, data->lights[i].name);
data->memory.free(data->memory.user_data, data->lights[i].name);
}
data->memory_free(data->memory_user_data, data->lights);
data->memory.free(data->memory.user_data, data->lights);
for (cgltf_size i = 0; i < data->nodes_count; ++i)
{
data->memory_free(data->memory_user_data, data->nodes[i].name);
data->memory_free(data->memory_user_data, data->nodes[i].children);
data->memory_free(data->memory_user_data, data->nodes[i].weights);
data->memory.free(data->memory.user_data, data->nodes[i].name);
data->memory.free(data->memory.user_data, data->nodes[i].children);
data->memory.free(data->memory.user_data, data->nodes[i].weights);
}
data->memory_free(data->memory_user_data, data->nodes);
data->memory.free(data->memory.user_data, data->nodes);
for (cgltf_size i = 0; i < data->scenes_count; ++i)
{
data->memory_free(data->memory_user_data, data->scenes[i].name);
data->memory_free(data->memory_user_data, data->scenes[i].nodes);
data->memory.free(data->memory.user_data, data->scenes[i].name);
data->memory.free(data->memory.user_data, data->scenes[i].nodes);
}
data->memory_free(data->memory_user_data, data->scenes);
data->memory.free(data->memory.user_data, data->scenes);
for (cgltf_size i = 0; i < data->animations_count; ++i)
{
data->memory_free(data->memory_user_data, data->animations[i].name);
data->memory_free(data->memory_user_data, data->animations[i].samplers);
data->memory_free(data->memory_user_data, data->animations[i].channels);
data->memory.free(data->memory.user_data, data->animations[i].name);
data->memory.free(data->memory.user_data, data->animations[i].samplers);
data->memory.free(data->memory.user_data, data->animations[i].channels);
}
data->memory_free(data->memory_user_data, data->animations);
data->memory.free(data->memory.user_data, data->animations);
for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
{
data->memory_free(data->memory_user_data, data->extensions_used[i]);
data->memory.free(data->memory.user_data, data->extensions_used[i]);
}
data->memory_free(data->memory_user_data, data->extensions_used);
data->memory.free(data->memory.user_data, data->extensions_used);
for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
{
data->memory_free(data->memory_user_data, data->extensions_required[i]);
data->memory.free(data->memory.user_data, data->extensions_required[i]);
}
data->memory_free(data->memory_user_data, data->extensions_required);
data->memory.free(data->memory.user_data, data->extensions_required);
data->memory_free(data->memory_user_data, data->file_data);
file_release(&data->memory, &data->file, data->file_data);
data->memory_free(data->memory_user_data, data);
data->memory.free(data->memory.user_data, data);
}
void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
@ -1787,6 +1830,77 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl
return element_count * floats_per_element;
}
static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type)
{
switch (component_type)
{
case cgltf_component_type_r_8:
return *((const int8_t*) in);
case cgltf_component_type_r_8u:
return *((const uint8_t*) in);
case cgltf_component_type_r_16:
return *((const int16_t*) in);
case cgltf_component_type_r_16u:
return *((const uint16_t*) in);
case cgltf_component_type_r_32u:
return *((const uint32_t*) in);
default:
return 0;
}
return 0;
}
static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size)
{
cgltf_size num_components = cgltf_num_components(type);
if (element_size < num_components)
{
return 0;
}
// Reading integer matrices is not a valid use case
if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
{
return 0;
}
cgltf_size component_size = cgltf_component_size(component_type);
for (cgltf_size i = 0; i < num_components; ++i)
{
out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
}
return 1;
}
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
{
if (accessor->is_sparse)
{
return 0;
}
if (accessor->buffer_view == NULL)
{
memset(out, 0, element_size * sizeof( cgltf_uint ));
return 1;
}
if (accessor->buffer_view->buffer->data == NULL)
{
return 0;
}
cgltf_size offset = accessor->offset + accessor->buffer_view->offset;
const uint8_t* element = (const uint8_t*) accessor->buffer_view->buffer->data;
element += offset + accessor->stride * index;
return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
}
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index)
{
if (accessor->is_sparse)
@ -1916,7 +2030,7 @@ static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* toke
return CGLTF_ERROR_JSON;
}
int size = tokens[i].end - tokens[i].start;
char* result = (char*)options->memory_alloc(options->memory_user_data, size + 1);
char* result = (char*)options->memory.alloc(options->memory.user_data, size + 1);
if (!result)
{
return CGLTF_ERROR_NOMEM;
@ -4387,7 +4501,7 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk,
options->json_token_count = token_count;
}
jsmntok_t* tokens = (jsmntok_t*)options->memory_alloc(options->memory_user_data, sizeof(jsmntok_t) * (options->json_token_count + 1));
jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1));
if (!tokens)
{
@ -4400,7 +4514,7 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk,
if (token_count <= 0)
{
options->memory_free(options->memory_user_data, tokens);
options->memory.free(options->memory.user_data, tokens);
return cgltf_result_invalid_json;
}
@ -4408,21 +4522,21 @@ cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk,
// for invalid JSON inputs this makes sure we don't perform out of bound reads of token data
tokens[token_count].type = JSMN_UNDEFINED;
cgltf_data* data = (cgltf_data*)options->memory_alloc(options->memory_user_data, sizeof(cgltf_data));
cgltf_data* data = (cgltf_data*)options->memory.alloc(options->memory.user_data, sizeof(cgltf_data));
if (!data)
{
options->memory_free(options->memory_user_data, tokens);
options->memory.free(options->memory.user_data, tokens);
return cgltf_result_out_of_memory;
}
memset(data, 0, sizeof(cgltf_data));
data->memory_free = options->memory_free;
data->memory_user_data = options->memory_user_data;
data->memory = options->memory;
data->file = options->file;
int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
options->memory_free(options->memory_user_data, tokens);
options->memory.free(options->memory.user_data, tokens);
if (i < 0)
{

View file

@ -1,4 +1,4 @@
/* stb_image - v2.23 - public domain image loader - http://nothings.org/stb
/* stb_image - v2.25 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk
Do this:
@ -48,6 +48,8 @@ LICENSE
RECENT REVISION HISTORY:
2.25 (2020-02-02) fix warnings
2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
2.23 (2019-08-11) fix clang static analysis warning
2.22 (2019-03-04) gif fixes, fix warnings
2.21 (2019-02-25) fix typo in comment
@ -105,7 +107,8 @@ RECENT REVISION HISTORY:
Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus
Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo
Christian Floisand Kevin Schmidt JR Smith github:darealshinji
Blazej Dariusz Roszkowski github:Michaelangel007
Brad Weinberger Matvey Cherevko github:Michaelangel007
Blazej Dariusz Roszkowski Alexander Veselov
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
@ -434,7 +437,7 @@ STBIDEF int stbi_is_hdr_from_file(FILE *f);
// get a VERY brief reason for failure
// NOT THREADSAFE
// on most compilers (and ALL modern mainstream compilers) this is threadsafe
STBIDEF const char *stbi_failure_reason (void);
// free the loaded image -- this is just free()
@ -467,6 +470,11 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// flip the image vertically, so the first pixel in the output array is the bottom left
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
// as above, but only applies to images loaded on the thread that calls the function
// this function is only available if your compiler supports thread-local variables;
// calling it will fail to link if your compiler doesn't
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
// ZLIB client - used by PNG, available for other purposes
STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
@ -563,6 +571,17 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#define stbi_inline __forceinline
#endif
#ifndef STBI_NO_THREAD_LOCALS
#if defined(__cplusplus) && __cplusplus >= 201103L
#define STBI_THREAD_LOCAL thread_local
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define STBI_THREAD_LOCAL _Thread_local
#elif defined(__GNUC__)
#define STBI_THREAD_LOCAL __thread
#elif defined(_MSC_VER)
#define STBI_THREAD_LOCAL __declspec(thread)
#endif
#endif
#ifdef _MSC_VER
typedef unsigned short stbi__uint16;
@ -873,19 +892,24 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int
static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
#endif
// this is not threadsafe
static const char *stbi__g_failure_reason;
static
#ifdef STBI_THREAD_LOCAL
STBI_THREAD_LOCAL
#endif
const char *stbi__g_failure_reason;
STBIDEF const char *stbi_failure_reason(void)
{
return stbi__g_failure_reason;
}
#ifndef STBI_NO_FAILURE_STRINGS
static int stbi__err(const char *str)
{
stbi__g_failure_reason = str;
return 0;
}
#endif
static void *stbi__malloc(size_t size)
{
@ -924,11 +948,13 @@ static int stbi__mul2sizes_valid(int a, int b)
return a <= INT_MAX/b;
}
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow
static int stbi__mad2sizes_valid(int a, int b, int add)
{
return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add);
}
#endif
// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow
static int stbi__mad3sizes_valid(int a, int b, int c, int add)
@ -946,12 +972,14 @@ static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add)
}
#endif
#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR)
// mallocs with size overflow checking
static void *stbi__malloc_mad2(int a, int b, int add)
{
if (!stbi__mad2sizes_valid(a, b, add)) return NULL;
return stbi__malloc(a*b + add);
}
#endif
static void *stbi__malloc_mad3(int a, int b, int c, int add)
{
@ -995,13 +1023,29 @@ static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp);
#endif
static int stbi__vertically_flip_on_load = 0;
static int stbi__vertically_flip_on_load_global = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load = flag_true_if_should_flip;
stbi__vertically_flip_on_load_global = flag_true_if_should_flip;
}
#ifndef STBI_THREAD_LOCAL
#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global
#else
static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set;
STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load_local = flag_true_if_should_flip;
stbi__vertically_flip_on_load_set = 1;
}
#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \
? stbi__vertically_flip_on_load_local \
: stbi__vertically_flip_on_load_global)
#endif // STBI_THREAD_LOCAL
static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
{
memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
@ -1023,6 +1067,8 @@ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int re
#endif
#ifndef STBI_NO_PSD
if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
#else
STBI_NOTUSED(bpc);
#endif
#ifndef STBI_NO_PIC
if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
@ -1477,6 +1523,9 @@ stbi_inline static stbi_uc stbi__get8(stbi__context *s)
return 0;
}
#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
stbi_inline static int stbi__at_eof(stbi__context *s)
{
if (s->io.read) {
@ -1488,7 +1537,11 @@ stbi_inline static int stbi__at_eof(stbi__context *s)
return s->img_buffer >= s->img_buffer_end;
}
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC)
// nothing
#else
static void stbi__skip(stbi__context *s, int n)
{
if (n < 0) {
@ -1505,7 +1558,11 @@ static void stbi__skip(stbi__context *s, int n)
}
s->img_buffer += n;
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM)
// nothing
#else
static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
{
if (s->io.read) {
@ -1529,18 +1586,27 @@ static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n)
} else
return 0;
}
#endif
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static int stbi__get16be(stbi__context *s)
{
int z = stbi__get8(s);
return (z << 8) + stbi__get8(s);
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC)
// nothing
#else
static stbi__uint32 stbi__get32be(stbi__context *s)
{
stbi__uint32 z = stbi__get16be(s);
return (z << 16) + stbi__get16be(s);
}
#endif
#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF)
// nothing
@ -1562,7 +1628,9 @@ static stbi__uint32 stbi__get32le(stbi__context *s)
#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings
#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
//////////////////////////////////////////////////////////////////////////////
//
// generic converter from built-in img_n to req_comp
@ -1578,7 +1646,11 @@ static stbi_uc stbi__compute_y(int r, int g, int b)
{
return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8);
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM)
// nothing
#else
static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{
int i,j;
@ -1622,12 +1694,20 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
STBI_FREE(data);
return good;
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
{
return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
// nothing
#else
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
{
int i,j;
@ -1671,6 +1751,7 @@ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int r
STBI_FREE(data);
return good;
}
#endif
#ifndef STBI_NO_LINEAR
static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
@ -4942,6 +5023,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
++s->img_n;
}
STBI_FREE(z->expanded); z->expanded = NULL;
// end of PNG chunk, read and skip CRC
stbi__get32be(s);
return 1;
}
@ -5111,7 +5194,7 @@ static int stbi__shiftsigned(unsigned int v, int shift, int bits)
v <<= -shift;
else
v >>= shift;
STBI_ASSERT(v >= 0 && v < 256);
STBI_ASSERT(v < 256);
v >>= (8-bits);
STBI_ASSERT(bits >= 0 && bits <= 8);
return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits];
@ -5121,6 +5204,7 @@ typedef struct
{
int bpp, offset, hsz;
unsigned int mr,mg,mb,ma, all_a;
int extra_read;
} stbi__bmp_data;
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
@ -5133,6 +5217,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->offset = stbi__get32le(s);
info->hsz = hsz = stbi__get32le(s);
info->mr = info->mg = info->mb = info->ma = 0;
info->extra_read = 14;
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
if (hsz == 12) {
@ -5176,6 +5261,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
info->mr = stbi__get32le(s);
info->mg = stbi__get32le(s);
info->mb = stbi__get32le(s);
info->extra_read += 12;
// not documented, but generated by photoshop and handled by mspaint
if (info->mr == info->mg && info->mg == info->mb) {
// ?!?!?
@ -5232,10 +5318,13 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz == 12) {
if (info.bpp < 24)
psize = (info.offset - 14 - 24) / 3;
psize = (info.offset - info.extra_read - 24) / 3;
} else {
if (info.bpp < 16)
psize = (info.offset - 14 - info.hsz) >> 2;
psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
STBI_ASSERT(info.offset == (s->img_buffer - s->buffer_start));
}
if (info.bpp == 24 && ma == 0xff000000)
@ -5263,7 +5352,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
if (info.hsz != 12) stbi__get8(s);
pal[i][3] = 255;
}
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
if (info.bpp == 1) width = (s->img_x + 7) >> 3;
else if (info.bpp == 4) width = (s->img_x + 1) >> 1;
else if (info.bpp == 8) width = s->img_x;
@ -5312,7 +5401,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
int z = 0;
int easy=0;
stbi__skip(s, info.offset - 14 - info.hsz);
stbi__skip(s, info.offset - info.extra_read - info.hsz);
if (info.bpp == 24) width = 3 * s->img_x;
else if (info.bpp == 16) width = 2*s->img_x;
else /* bpp = 32 and pad = 0 */ width=0;
@ -6610,7 +6699,15 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
stride = g.w * g.h * 4;
if (out) {
out = (stbi_uc*) STBI_REALLOC( out, layers * stride );
void *tmp = (stbi_uc*) STBI_REALLOC( out, layers * stride );
if (NULL == tmp) {
STBI_FREE(g.out);
STBI_FREE(g.history);
STBI_FREE(g.background);
return stbi__errpuc("outofmem", "Out of memory");
}
else
out = (stbi_uc*) tmp;
if (delays) {
*delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers );
}

View file

@ -159,6 +159,7 @@
Nathan Reed: warning fixes
REVISIONS
0.97 (2020-02-02) fixed warning
0.96 (2019-03-04) fixed warnings
0.95 (2017-07-23) fixed warnings
0.94 (2017-03-18) fixed warnings
@ -1238,7 +1239,7 @@ static float* stbir__get_decode_buffer(stbir__info* stbir_info)
return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
}
#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace))
static void stbir__decode_scanline(stbir__info* stbir_info, int n)
{

View file

@ -1,4 +1,4 @@
/* stb_image_write - v1.13 - public domain - http://nothings.org/stb
/* stb_image_write - v1.14 - public domain - http://nothings.org/stb
writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
no warranty implied; use at your own risk
@ -247,17 +247,17 @@ STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
#ifdef STB_IMAGE_WRITE_STATIC
static int stbi__flip_vertically_on_write=0;
static int stbi_write_png_compression_level = 8;
static int stbi_write_tga_with_rle = 1;
static int stbi_write_force_png_filter = -1;
#else
int stbi_write_png_compression_level = 8;
int stbi__flip_vertically_on_write=0;
int stbi_write_tga_with_rle = 1;
int stbi_write_force_png_filter = -1;
#endif
static int stbi__flip_vertically_on_write = 0;
STBIWDEF void stbi_flip_vertically_on_write(int flag)
{
stbi__flip_vertically_on_write = flag;
@ -774,7 +774,7 @@ STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const
#ifndef STBIW_ZLIB_COMPRESS
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2)
#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
#define stbiw__sbn(a) stbiw__sbraw(a)[1]
@ -1271,26 +1271,31 @@ static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
bits[0] = val & ((1<<bits[1])-1);
}
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
int dataOff, i, diff, end0pos;
int dataOff, i, j, n, diff, end0pos, x, y;
int DU[64];
// DCT rows
for(dataOff=0; dataOff<64; dataOff+=8) {
for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
}
// DCT columns
for(dataOff=0; dataOff<8; ++dataOff) {
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
&CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
}
// Quantize/descale/zigzag the coefficients
for(i=0; i<64; ++i) {
float v = CDU[i]*fdtbl[i];
// DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
for(y = 0, j=0; y < 8; ++y) {
for(x = 0; x < 8; ++x,++j) {
float v;
i = y*du_stride+x;
v = CDU[i]*fdtbl[j];
// DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
// ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
}
}
// Encode DC
@ -1408,7 +1413,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
int row, col, i, k;
int row, col, i, k, subsample;
float fdtbl_Y[64], fdtbl_UV[64];
unsigned char YTable[64], UVTable[64];
@ -1417,6 +1422,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
}
quality = quality ? quality : 90;
subsample = quality <= 90 ? 1 : 0;
quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
@ -1439,7 +1445,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
s->func(s->context, (void*)head0, sizeof(head0));
s->func(s->context, (void*)YTable, sizeof(YTable));
stbiw__putc(s, 1);
@ -1462,36 +1468,74 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in
// Encode 8x8 macroblocks
{
static const unsigned short fillBits[] = {0x7F, 7};
const unsigned char *imageData = (const unsigned char *)data;
int DCY=0, DCU=0, DCV=0;
int bitBuf=0, bitCnt=0;
// comp == 2 is grey+alpha (alpha is ignored)
int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
const unsigned char *dataR = (const unsigned char *)data;
const unsigned char *dataG = dataR + ofsG;
const unsigned char *dataB = dataR + ofsB;
int x, y, pos;
if(subsample) {
for(y = 0; y < height; y += 16) {
for(x = 0; x < width; x += 16) {
float Y[256], U[256], V[256];
for(row = y, pos = 0; row < y+16; ++row) {
// row >= height => use last input row
int clamped_row = (row < height) ? row : height - 1;
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
for(col = x; col < x+16; ++col, ++pos) {
// if col >= width => use pixel from last input column
int p = base_p + ((col < width) ? col : (width-1))*comp;
float r = dataR[p], g = dataG[p], b = dataB[p];
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
}
}
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
// subsample U,V
{
float subU[64], subV[64];
int yy, xx;
for(yy = 0, pos = 0; yy < 8; ++yy) {
for(xx = 0; xx < 8; ++xx, ++pos) {
int j = yy*32+xx*2;
subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
}
}
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
}
}
}
} else {
for(y = 0; y < height; y += 8) {
for(x = 0; x < width; x += 8) {
float YDU[64], UDU[64], VDU[64];
float Y[64], U[64], V[64];
for(row = y, pos = 0; row < y+8; ++row) {
// row >= height => use last input row
int clamped_row = (row < height) ? row : height - 1;
int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
for(col = x; col < x+8; ++col, ++pos) {
float r, g, b;
// if col >= width => use pixel from last input column
int p = base_p + ((col < width) ? col : (width-1))*comp;
r = imageData[p+0];
g = imageData[p+ofsG];
b = imageData[p+ofsB];
YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
float r = dataR[p], g = dataG[p], b = dataB[p];
Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
}
}
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
}
}
}
@ -1530,6 +1574,9 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history
1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
1.13
1.12
1.11 (2019-08-11)
1.10 (2019-02-07)

View file

@ -1,4 +1,4 @@
// stb_perlin.h - v0.4 - perlin noise
// stb_perlin.h - v0.5 - perlin noise
// public domain single-file C implementation by Sean Barrett
//
// LICENSE
@ -78,6 +78,7 @@
extern "C" {
#endif
extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed);
extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves);
extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);
extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);

View file

@ -1,5 +1,14 @@
// stb_truetype.h - v1.22 - public domain
// authored from 2009-2019 by Sean Barrett / RAD Game Tools
// stb_truetype.h - v1.24 - public domain
// authored from 2009-2020 by Sean Barrett / RAD Game Tools
//
// =======================================================================
//
// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
//
// This library does no range checking of the offsets found in the file,
// meaning an attacker can use it to read arbitrary memory.
//
// =======================================================================
//
// This library processes TrueType files:
// parse files
@ -32,11 +41,11 @@
// Daniel Ribeiro Maciel
//
// Bug/warning reports/fixes:
// "Zer" on mollyrocket Fabian "ryg" Giesen
// Cass Everitt Martins Mozeiko
// stoiko (Haemimont Games) Cap Petschulat
// Brian Hook Omar Cornut
// Walter van Niftrik github:aloucks
// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
// Cass Everitt Martins Mozeiko github:aloucks
// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
// Brian Hook Omar Cornut github:vassvik
// Walter van Niftrik Ryan Griege
// David Gow Peter LaValle
// David Given Sergey Popov
// Ivan-Assen Ivanov Giumo X. Clanjor
@ -44,12 +53,13 @@
// Johan Duparc Thomas Fields
// Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton
// Kenney Phillis Jr. github:oyvindjam
// Brian Costabile github:vassvik
// Ken Voskuil (kaesve) Ryan Griege
// Kenney Phillis Jr. Brian Costabile
// Ken Voskuil (kaesve)
//
// VERSION HISTORY
//
// 1.24 (2020-02-05) fix warning
// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
// 1.21 (2019-02-25) fix warning
// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
@ -704,7 +714,7 @@ struct stbtt_fontinfo
int numGlyphs; // number of glyphs, needed for range checking
int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph
@ -787,6 +797,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1,
STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
// as above, but takes one or more glyph indices for greater efficiency
typedef struct stbtt_kerningentry
{
int glyph1; // use stbtt_FindGlyphIndex
int glyph2;
int advance;
} stbtt_kerningentry;
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
// Retrieves a complete list of all of the kerning pairs provided by the font
// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
//////////////////////////////////////////////////////////////////////////////
//
@ -831,6 +853,11 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s
STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
// frees the data allocated above
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
// fills svg with the character's SVG data.
// returns data size or 0 if SVG not found.
//////////////////////////////////////////////////////////////////////////////
//
// BITMAP RENDERING
@ -1332,6 +1359,22 @@ static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
return stbtt__cff_get_index(&cff);
}
// since most people won't use this, find this table the first time it's needed
static int stbtt__get_svg(stbtt_fontinfo *info)
{
stbtt_uint32 t;
if (info->svg < 0) {
t = stbtt__find_table(info->data, info->fontstart, "SVG ");
if (t) {
stbtt_uint32 offset = ttULONG(info->data + t + 2);
info->svg = t + offset;
} else {
info->svg = 0;
}
}
return info->svg;
}
static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
{
stbtt_uint32 cmap, t;
@ -1411,6 +1454,8 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in
else
info->numGlyphs = 0xffff;
info->svg = -1;
// find a cmap encoding table we understand *now* to avoid searching
// later. (todo: could make this installable)
// the same regardless of glyph.
@ -1759,7 +1804,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
}
}
num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
} else if (numberOfContours == -1) {
} else if (numberOfContours < 0) {
// Compound shapes.
int more = 1;
stbtt_uint8 *comp = data + g + 10;
@ -1836,9 +1881,6 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s
// More components ?
more = flags & (1<<5);
}
} else if (numberOfContours < 0) {
// @TODO other compound variations?
STBTT_assert(0);
} else {
// numberOfCounters == 0, do nothing
}
@ -2267,6 +2309,48 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde
}
}
STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
{
stbtt_uint8 *data = info->data + info->kern;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
return ttUSHORT(data+10);
}
STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
{
stbtt_uint8 *data = info->data + info->kern;
int k, length;
// we only look at the first table. it must be 'horizontal' and format 0.
if (!info->kern)
return 0;
if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
return 0;
if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
return 0;
length = ttUSHORT(data+10);
if (table_length < length)
length = table_length;
for (k = 0; k < length; k++)
{
table[k].glyph1 = ttUSHORT(data+18+(k*6));
table[k].glyph2 = ttUSHORT(data+20+(k*6));
table[k].advance = ttSHORT(data+22+(k*6));
}
return length;
}
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{
stbtt_uint8 *data = info->data + info->kern;
@ -2603,6 +2687,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
STBTT_free(v, info->userdata);
}
STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
{
int i;
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
int numEntries = ttUSHORT(svg_doc_list);
stbtt_uint8 *svg_docs = svg_doc_list + 2;
for(i=0; i<numEntries; i++) {
stbtt_uint8 *svg_doc = svg_docs + (12 * i);
if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
return svg_doc;
}
return 0;
}
STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
{
stbtt_uint8 *data = info->data;
stbtt_uint8 *svg_doc;
if (info->svg == 0)
return 0;
svg_doc = stbtt_FindSVGDoc(info, gl);
if (svg_doc != NULL) {
*svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
return ttULONG(svg_doc + 8);
} else {
return 0;
}
}
STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
{
return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
}
//////////////////////////////////////////////////////////////////////////////
//
// antialiasing software rasterizer