Simplified rect drawing and started with text rendering (text not working)

This commit is contained in:
Dennis Eichhorn 2024-10-02 17:32:04 +02:00
parent 390158687a
commit 223edfd595
18 changed files with 349 additions and 118 deletions

View File

@ -15,16 +15,16 @@
#include "AnimationEaseType.h"
inline
float lerp(float a, float b, float t)
f32 lerp(f32 a, f32 b, f32 t)
{
return a + t * (b - a);
}
float smoothstep(float t) {
f32 smoothstep(f32 t) {
return t * t * (3 - 2 * t);
}
float anim_ease(float t, AnimationEaseType type) {
f32 anim_ease(f32 t, AnimationEaseType type) {
switch(type) {
case ANIMATION_EASE_IN_SINE: {
return anim_ease_in_sine(t);
@ -122,113 +122,113 @@ float anim_ease(float t, AnimationEaseType type) {
}
inline
float anim_ease_linear(float t) {
f32 anim_ease_linear(f32 t) {
return t;
}
inline
float anim_ease_in_sine(float t) {
return 1 - cosf_approx((t * OMS_PI) / 2);
f32 anim_ease_in_sine(f32 t) {
return 1 - cosf((t * OMS_PI) / 2);
}
inline
float anim_ease_out_sine(float t) {
return sinf_approx((t * OMS_PI) / 2);
f32 anim_ease_out_sine(f32 t) {
return sinf((t * OMS_PI) / 2);
}
inline
float anim_ease_in_out_sine(float t) {
return -(cosf_approx(OMS_PI * t) - 1) / 2;
f32 anim_ease_in_out_sine(f32 t) {
return -(cosf(OMS_PI * t) - 1) / 2;
}
inline
float anim_ease_in_quad(float t) {
f32 anim_ease_in_quad(f32 t) {
return t * t;
}
inline
float anim_ease_out_quad(float t) {
f32 anim_ease_out_quad(f32 t) {
return 1 - (1 - t) * (1 - t);
}
inline
float anim_ease_in_out_quad(float t) {
f32 anim_ease_in_out_quad(f32 t) {
return t < 0.5
? 2 * t * t
: 1 - pow(-2 * t + 2, 2) / 2;
}
inline
float anim_ease_in_cubic(float t) {
f32 anim_ease_in_cubic(f32 t) {
return t * t * t;
}
inline
float anim_ease_out_cubic(float t) {
f32 anim_ease_out_cubic(f32 t) {
return 1 - pow(1 - t, 3);
}
inline
float anim_ease_in_out_cubic(float t) {
f32 anim_ease_in_out_cubic(f32 t) {
return t < 0.5
? 4 * t * t * t
: 1 - pow(-2 * t + 2, 3) / 2;
}
inline
float anim_ease_in_quart(float t) {
f32 anim_ease_in_quart(f32 t) {
return t * t * t * t;
}
inline
float anim_ease_out_quart(float t) {
f32 anim_ease_out_quart(f32 t) {
return 1 - pow(1 - t, 4);
}
inline
float anim_ease_in_perlin(float t) {
f32 anim_ease_in_perlin(f32 t) {
return t * t * t * (t * (t * 6 - 15) + 10);
}
inline
float anim_ease_in_out_quart(float t) {
f32 anim_ease_in_out_quart(f32 t) {
return t < 0.5
? 8 * t * t * t * t
: 1 - pow(-2 * t + 2, 4) / 2;
}
inline
float anim_ease_in_quint(float t) {
f32 anim_ease_in_quint(f32 t) {
return t * t * t * t * t;
}
inline
float anim_ease_out_quint(float t) {
f32 anim_ease_out_quint(f32 t) {
return 1 - pow(1 - t, 5);
}
inline
float anim_ease_in_out_quint(float t) {
f32 anim_ease_in_out_quint(f32 t) {
return t < 0.5
? 16 * t * t * t * t * t
: 1 - pow(-2 * t + 2, 5) / 2;
}
inline
float anim_ease_in_expo(float t) {
f32 anim_ease_in_expo(f32 t) {
return t == 0
? 0 : pow(2, 10 * t - 10);
}
inline
float anim_ease_out_expo(float t) {
f32 anim_ease_out_expo(f32 t) {
return t == 1
? 1
: 1 - pow(2, -10 * t);
}
inline
float anim_ease_in_out_expo(float t) {
f32 anim_ease_in_out_expo(f32 t) {
if (t == 0 || t == 1) {
return t;
}
@ -239,42 +239,42 @@ float anim_ease_in_out_expo(float t) {
}
inline
float anim_ease_in_circ(float t) {
f32 anim_ease_in_circ(f32 t) {
return 1 - sqrt(1 - pow(t, 2));
}
inline
float anim_ease_out_circ(float t) {
f32 anim_ease_out_circ(f32 t) {
return sqrt(1 - pow(t - 1, 2));
}
inline
float anim_ease_in_out_circ(float t) {
f32 anim_ease_in_out_circ(f32 t) {
return t < 0.5
? (1 - sqrt(1 - pow(2 * t, 2))) / 2
: (sqrt(1 - pow(-2 * t + 2, 2)) + 1) / 2;
}
inline
float anim_ease_in_back(float t) {
const float c1 = 1.70158;
const float c3 = c1 + 1;
f32 anim_ease_in_back(f32 t) {
const f32 c1 = 1.70158;
const f32 c3 = c1 + 1;
return c3 * t * t * t - c1 * t * t;
}
inline
float anim_ease_out_back(float t) {
const float c1 = 1.70158;
const float c3 = c1 + 1;
f32 anim_ease_out_back(f32 t) {
const f32 c1 = 1.70158;
const f32 c3 = c1 + 1;
return 1 + c3 * pow(t - 1, 3) + c1 * pow(t - 1, 2);
}
inline
float anim_ease_in_out_back(float t) {
const float c1 = 1.70158;
const float c2 = c1 * 1.525;
f32 anim_ease_in_out_back(f32 t) {
const f32 c1 = 1.70158;
const f32 c2 = c1 * 1.525;
return t < 0.5
? (pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
@ -282,49 +282,49 @@ float anim_ease_in_out_back(float t) {
}
inline
float anim_ease_in_elastic(float t) {
const float c4 = (2 * OMS_PI) / 3;
f32 anim_ease_in_elastic(f32 t) {
const f32 c4 = (2 * OMS_PI) / 3;
if (t == 0 || t == 1) {
return t;
}
return -pow(2, 10 * t - 10) * sinf_approx((t * 10 - 10.75) * c4);
return -pow(2, 10 * t - 10) * sinf((t * 10 - 10.75) * c4);
}
inline
float anim_ease_out_elastic(float t) {
const float c4 = (2 * OMS_PI) / 3;
f32 anim_ease_out_elastic(f32 t) {
const f32 c4 = (2 * OMS_PI) / 3;
if (t == 0.0 || t == 1.0) {
return t;
}
return pow(2, -10 * t) * sinf_approx((t * 10 - 0.75) * c4) + 1;
return pow(2, -10 * t) * sinf((t * 10 - 0.75) * c4) + 1;
}
inline
float anim_ease_in_out_elastic(float t) {
const float c5 = (2 * OMS_PI) / 4.5;
f32 anim_ease_in_out_elastic(f32 t) {
const f32 c5 = (2 * OMS_PI) / 4.5;
if (t == 0.0 || t == 1.0) {
return t;
} else if (t < 0.5) {
return -(pow(2, 20 * t - 10) * sinf_approx((20 * t - 11.125) * c5)) / 2;
return -(pow(2, 20 * t - 10) * sinf((20 * t - 11.125) * c5)) / 2;
}
return (pow(2, -20 * t + 10) * sinf_approx((20 * t - 11.125) * c5)) / 2 + 1;
return (pow(2, -20 * t + 10) * sinf((20 * t - 11.125) * c5)) / 2 + 1;
}
inline
float anim_ease_in_bounce(float t) {
f32 anim_ease_in_bounce(f32 t) {
return 1 - anim_ease_out_bounce(1 - t);
}
inline
float anim_ease_out_bounce(float t) {
const float n1 = 7.5625;
const float d1 = 2.75;
f32 anim_ease_out_bounce(f32 t) {
const f32 n1 = 7.5625;
const f32 d1 = 2.75;
if (t < 1 / d1) {
return n1 * t * t;
@ -338,7 +338,7 @@ float anim_ease_out_bounce(float t) {
}
inline
float anim_ease_in_out_bounce(float t) {
f32 anim_ease_in_out_bounce(f32 t) {
return t < 0.5
? (1 - anim_ease_out_bounce(1 - 2 * t)) / 2
: (1 + anim_ease_out_bounce(2 * t - 1)) / 2;

View File

@ -0,0 +1,56 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_COLOR_VISION_DEFICIENCY_H
#define TOS_COLOR_VISION_DEFICIENCY_H
#include "../stdlib/Types.h"
f32 protanopia_matrix[9] = {
0.567f, 0.433f, 0.000f,
0.558f, 0.442f, 0.000f,
0.000f, 0.242f, 0.758f
};
f32 deuteranopia_matrix[9] = {
0.625f, 0.375f, 0.000f,
0.700f, 0.300f, 0.000f,
0.000f, 0.300f, 0.700f
};
f32 tritanopia_matrix[9] = {
0.950f, 0.050f, 0.000f,
0.000f, 0.433f, 0.567f,
0.000f, 0.475f, 0.525f
};
f32 protanomaly_matrix[9] = {
0.817f, 0.183f, 0.000f,
0.333f, 0.667f, 0.000f,
0.000f, 0.125f, 0.875f
};
f32 deuteranomaly_matrix[9] = {
0.800f, 0.200f, 0.000f,
0.258f, 0.742f, 0.000f,
0.000f, 0.142f, 0.858f
};
f32 tritanomaly_matrix[9] = {
0.967f, 0.033f, 0.000f,
0.000f, 0.733f, 0.267f,
0.000f, 0.183f, 0.817f
};
f32 achromatopsia_matrix[9] = {
0.299f, 0.587f, 0.114f,
0.299f, 0.587f, 0.114f,
0.299f, 0.587f, 0.114f
};
#endif

57
font/Font.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef TOS_FONT_H
#define TOS_FONT_H
#include "../stdlib/Types.h"
#include "../memory/BufferMemory.h"
struct GlyphMetrics {
f32 width; // Width of the glyph
f32 height; // Height of the glyph
f32 offset_x; // Horizontal offset from baseline
f32 offset_y; // Vertical offset from baseline
f32 advance_x; // Horizontal advance after drawing the glyph
};
// @question Do we even need all this information? x2 and y2 follow from width and height, no?
struct GlyphTextureCoords {
f32 x1;
f32 y1;
f32 x2;
f32 y2;
};
struct Glyph {
uint32 codepoint;
GlyphMetrics metrics;
GlyphTextureCoords coords;
};
struct Font {
uint32 glyph_count;
uint32 line_height;
Glyph* glyphs;
// @question Do we want to have a pointer to the glyph Texture
};
inline
void font_init(BufferMemory* buf, Font* font, int count)
{
font->glyphs = (Glyph *) buffer_get_memory(buf, sizeof(Glyph) * count);
font->glyph_count = count;
}
inline
Glyph* font_glyph_find(Font* font, uint32 codepoint)
{
for (int i = 0; i < font->glyph_count; ++i) {
if (font->glyphs[i].codepoint == codepoint) {
return &font->glyphs[i];
}
}
return NULL;
}
#endif

View File

@ -107,6 +107,7 @@ uint32 get_texture_data_type(uint32 texture_data_type)
// 2. define wrap
// 3. define filter
// 4. load_texture_to_gpu
// 5. texture_use
inline
void prepare_texture(Texture* texture)
@ -123,7 +124,7 @@ void load_texture_to_gpu(const Texture* texture, int32 mipmap_level = 0)
{
uint32 texture_data_type = get_texture_data_type(texture->texture_data_type);
glTexImage2D(
texture_data_type, mipmap_level, GL_RGBA,
texture_data_type, mipmap_level, GL_RGBA8,
texture->image.width, texture->image.height,
0, GL_RGBA, GL_UNSIGNED_BYTE,
texture->image.pixels
@ -141,6 +142,7 @@ void texture_use(const Texture* texture, uint32 texture_unit)
glBindTexture(GL_TEXTURE_2D, (GLuint) texture->id);
}
// @todo should be texture_use, the Texture holds information that should make it possible to determine 1D or 2D
inline
void texture_use_1D(const Texture* texture, uint32 texture_unit)
{
@ -164,10 +166,9 @@ GLuint shader_make(GLenum type, const char *source, RingMemory* ring)
GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar));
glGetShaderInfoLog(shader, length, NULL, info);
LOG(info, true, true);
ASSERT_SIMPLE(false);
// @todo log
}
return shader;
@ -219,17 +220,15 @@ GLuint program_make(
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
ASSERT_SIMPLE(false);
GLint length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar));
glGetProgramInfoLog(program, length, NULL, info);
LOG(info, true, true);
// @todo use global logger
fprintf(stderr, "glLinkProgram failed: %s\n", info);
ASSERT_SIMPLE(false);
}
// @question really?
@ -474,6 +473,8 @@ uint32 gpuapi_shaderbuffer_generate(int32 size, const void* data)
return sbo;
}
// @todo this is not necessary?! We have a flag to determine the BindTexture Type
// Only problem are the parameters
uint32 gpuapi_upload_color_palette(const byte* palette, int32 count, int32 sampler_id)
{
uint32 texture_id;

View File

@ -298,15 +298,12 @@ void image_bmp_generate(const FileBody* src_data, Image* image)
}
uint32 pixel_rgb_bytes = pixel_bytes - alpha_offset;
uint32 row_pos1;
uint32 row_pos2;
uint32 width_pixel_bytes = width * pixel_bytes;
for (uint32 y = 0; y < src.dib_header.height; ++y) {
row_pos1 = y * width_pixel_bytes;
uint32 row_pos1 = y * width_pixel_bytes;
uint32 row_pos2;
if (image->order_rows == IMAGE_ROW_ORDER_TOP_TO_BOTTOM) {
row_pos2 = (src.dib_header.height - y - 1) * width_pixel_bytes;
} else {

View File

@ -44,7 +44,7 @@ void image_flip_vertical(RingMemory* ring, Image* image)
memcpy(temp, image->pixels, image->pixel_count * sizeof(uint32));
// Last row
byte* end = temp + image->pixel_count * sizeof(uint32) - image->width * sizeof(uint32);
const byte* end = temp + image->pixel_count * sizeof(uint32) - image->width * sizeof(uint32);
for (int y = 0; y < image->height; ++y) {
memcpy(image->pixels + y * stride, end - y * stride, stride);

View File

@ -103,15 +103,12 @@ void image_tga_generate(const FileBody* src_data, Image* image)
}
uint32 pixel_rgb_bytes = pixel_bytes - alpha_offset;
uint32 row_pos1;
uint32 row_pos2;
uint32 width_pixel_bytes = src.header.width * pixel_bytes;
for (uint32 y = 0; y < src.header.height; ++y) {
row_pos1 = y * image->width * pixel_bytes;
uint32 row_pos1 = y * image->width * pixel_bytes;
uint32 row_pos2;
if ((image->order_rows == IMAGE_ROW_ORDER_TOP_TO_BOTTOM && src.header.vertical_ordering == 1)
|| (image->order_rows == IMAGE_ROW_ORDER_BOTTOM_TO_TOP && src.header.vertical_ordering == 0)
) {

View File

@ -40,7 +40,7 @@ void debug_memory_init(uint64 start, uint64 size)
return;
}
DebugMemory* mem = debug_memory_find(start, size);
const DebugMemory* mem = debug_memory_find(start, size);
if (mem) {
return;
}
@ -64,7 +64,7 @@ void debug_memory_init(uint64 start, uint64 size)
++debug_container->dmc.memory_element_idx;
}
void debug_memory_write(uint64 start, uint64 size)
void debug_memory_write(uint64 start, uint64 size, const char* function)
{
if (!start) {
return;
@ -85,12 +85,13 @@ void debug_memory_write(uint64 start, uint64 size)
// @question consider to use other time_ms() since __rdtsc is variable (boost, power saving)
mem->last_action[mem->action_idx].time = __rdtsc();
mem->last_action[mem->action_idx].function_name = function;
++mem->action_idx;
mem->usage += size;
}
void debug_memory_read(uint64 start, uint64 size)
void debug_memory_read(uint64 start, uint64 size, const char* function)
{
if (!start) {
return;
@ -111,11 +112,12 @@ void debug_memory_read(uint64 start, uint64 size)
// @question consider to use other time_ms() since __rdtsc is variable (boost, power saving)
mem->last_action[mem->action_idx].time = __rdtsc();
mem->last_action[mem->action_idx].function_name = function;
++mem->action_idx;
}
void debug_memory_delete(uint64 start, uint64 size)
void debug_memory_delete(uint64 start, uint64 size, const char* function)
{
DebugMemory* mem = debug_memory_find(start, size);
if (!mem) {
@ -132,6 +134,7 @@ void debug_memory_delete(uint64 start, uint64 size)
// @question consider to use other time_ms() since __rdtsc is variable (boost, power saving)
mem->last_action[mem->action_idx].time = __rdtsc();
mem->last_action[mem->action_idx].function_name = function;
++mem->action_idx;
mem->usage -= size;

View File

@ -29,6 +29,8 @@ struct DebugMemoryRange {
uint64 start;
uint64 size;
uint64 time;
const char* function_name;
};
struct DebugMemory {
@ -48,9 +50,9 @@ struct DebugMemoryContainer {
#if DEBUG
#define DEBUG_MEMORY_INIT(start, size) debug_memory_init((start), (size))
#define DEBUG_MEMORY_READ(start, size) debug_memory_read((start), (size))
#define DEBUG_MEMORY_WRITE(start, size) debug_memory_write((start), (size))
#define DEBUG_MEMORY_DELETE(start, size) debug_memory_delete((start), (size))
#define DEBUG_MEMORY_READ(start, size) debug_memory_read((start), (size), __func__)
#define DEBUG_MEMORY_WRITE(start, size) debug_memory_write((start), (size), __func__)
#define DEBUG_MEMORY_DELETE(start, size) debug_memory_delete((start), (size), __func__)
#define DEBUG_MEMORY_RESET() debug_memory_reset()
#else
#define DEBUG_MEMORY_INIT(start, size) ((void) 0)

View File

@ -20,9 +20,9 @@
}
inline
void aligned_free(void* ptr) {
_aligned_free(ptr);
ptr = NULL;
void aligned_free(void** ptr) {
_aligned_free(*ptr);
*ptr = NULL;
}
inline
@ -43,25 +43,25 @@
}
inline
void platform_free(void* ptr, size_t) {
VirtualFree(ptr, 0, MEM_RELEASE);
ptr = NULL;
void platform_free(void** ptr, size_t) {
VirtualFree(*ptr, 0, MEM_RELEASE);
*ptr = NULL;
}
inline
void platform_aligned_free(void* aligned_ptr, size_t) {
void* ptr = ((void**) aligned_ptr)[-1];
void platform_aligned_free(void** aligned_ptr, size_t) {
void* ptr = ((void**) *aligned_ptr)[-1];
VirtualFree(ptr, 0, MEM_RELEASE);
aligned_ptr = NULL;
*aligned_ptr = NULL;
}
#else
#include <unistd.h>
#include <sys/mman.h>
inline
void aligned_free(void* ptr) {
free(ptr);
ptr = NULL;
void aligned_free(void** ptr) {
free(*ptr);
*ptr = NULL;
}
inline
@ -97,16 +97,16 @@
}
inline
void platform_free(void* ptr, size_t size) {
munmap(ptr, size);
ptr = NULL;
void platform_free(void** ptr, size_t size) {
munmap(*ptr, size);
*ptr = NULL;
}
inline
void platform_aligned_free(void* aligned_ptr, size_t size) {
void* ptr = ((void**) aligned_ptr)[-1];
munmap(ptr, size + ((uintptr_t)aligned_ptr - (uintptr_t)ptr));
aligned_ptr = NULL;
void platform_aligned_free(void** aligned_ptr, size_t size) {
void* ptr = ((void**) *aligned_ptr)[-1];
munmap(ptr, size + ((uintptr_t) *aligned_ptr - (uintptr_t)ptr));
*aligned_ptr = NULL;
}
#endif

View File

@ -45,9 +45,9 @@ void buffer_free(BufferMemory* buf)
{
DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size);
if (buf->alignment < 2) {
platform_free(buf->memory, buf->size);
platform_free((void **) &buf->memory, buf->size);
} else {
platform_aligned_free(buf->memory, buf->size);
platform_aligned_free((void **) &buf->memory, buf->size);
}
}

View File

@ -51,9 +51,9 @@ void chunk_free(ChunkMemory* buf)
{
DEBUG_MEMORY_DELETE((uint64) buf->memory, buf->size);
if (buf->alignment < 2) {
platform_free(buf->memory, buf->size);
platform_free((void **) &buf->memory, buf->size);
} else {
platform_aligned_free(buf->memory, buf->size);
platform_aligned_free((void **) &buf->memory, buf->size);
}
}

View File

@ -73,9 +73,9 @@ inline
void ring_free(RingMemory* buf)
{
if (buf->alignment < 2) {
platform_free(buf->memory, buf->size);
platform_free((void **) &buf->memory, buf->size);
} else {
platform_aligned_free(buf->memory, buf->size);
platform_aligned_free((void **) &buf->memory, buf->size);
}
}

View File

@ -24,14 +24,14 @@
struct MobState {
Location location;
float t;
f32 t;
// Action performed
// first byte = action category
// last 3 bytes = animation to use
uint32 action = (MOB_ACTION_INACTIVE << 24);
int chunk_id;
int32 chunk_id;
bool in_battle;

View File

@ -18,18 +18,18 @@
struct LootTable {
// Chance this table becomes effective at all
// Useful to define multiple loot tables for a mob e.g. normal drop + 1 rare guarantueed
float table_chance;
f32 table_chance;
uint64* items;
int table_size;
int32 table_size;
// If drop chance = -1 -> use default rarity drop chance
float* item_drop_chances;
f32* item_drop_chances;
// How many stacks of that item should be dropped
// Usually only used for consumables
int* item_min_drop_count;
int* item_max_drop_count;
int32* item_min_drop_count;
int32* item_max_drop_count;
bool item_unique;
// How many "different" items should be dropped
@ -58,7 +58,7 @@ void loot_table_drop(const LootTable* table, Drop* drop, uint32 counter = 0)
}
f32 range_value = 0;
int i = 0;
int32 i = 0;
for (i = 0; i < table->table_size; ++i) {
range_value += table->item_drop_chances[i];
@ -76,7 +76,7 @@ void loot_table_drop(const LootTable* table, Drop* drop, uint32 counter = 0)
drop->quantity = 1;
if (table->item_max_drop_count[i] > 1) {
rand = fast_rand_percentage();
drop->quantity = OMS_MAX(table->item_min_drop_count[i], (int) ((float) table->item_max_count * rand));
drop->quantity = OMS_MAX(table->item_min_drop_count[i], (int) ((f32) table->item_max_count * rand));
}
}

View File

@ -14,14 +14,14 @@
struct Vertex3D {
v3_f32 position;
v3_f32 normal;
v2_int32 tex_coord;
v2_f32 tex_coord;
v4_f32 color;
};
struct Vertex3DTextureColorIndex {
v3_f32 position;
v2_int32 tex_coord;
f32 color;
v2_f32 tex_coord;
uint32 color;
};
struct Vertex3DColorIndex {
@ -31,13 +31,13 @@ struct Vertex3DColorIndex {
struct Vertex2D {
v2_f32 position;
v2_int32 tex_coord;
v2_f32 tex_coord;
v4_f32 color;
};
struct Vertex2DTexture {
v2_f32 position;
v2_int32 tex_coord;
v2_f32 tex_coord;
};
struct Vertex2DColor {

View File

@ -15,6 +15,124 @@
#include "../stdlib/Types.h"
inline
int32 utf8_encode(uint32 codepoint, char* out)
{
if (codepoint <= 0x7F) {
// 1-byte sequence: 0xxxxxxx
out[0] = (byte) codepoint;
return 1;
} else if (codepoint <= 0x7FF) {
// 2-byte sequence: 110xxxxx 10xxxxxx
out[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
out[1] = 0x80 | (codepoint & 0x3F);
return 2;
} else if (codepoint <= 0xFFFF) {
// 3-byte sequence: 1110xxxx 10xxxxxx 10xxxxxx
out[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
out[1] = 0x80 | ((codepoint >> 6) & 0x3F);
out[2] = 0x80 | (codepoint & 0x3F);
return 3;
} else if (codepoint <= 0x10FFFF) {
// 4-byte sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
out[0] = 0xF0 | ((codepoint >> 18) & 0x07);
out[1] = 0x80 | ((codepoint >> 12) & 0x3F);
out[2] = 0x80 | ((codepoint >> 6) & 0x3F);
out[3] = 0x80 | (codepoint & 0x3F);
return 4;
}
return -1;
}
inline
int32 utf8_decode(const char* in, uint32* codepoint) {
unsigned char ch = (unsigned char) in[0];
if (ch <= 0x7F) {
// 1-byte sequence (ASCII)
*codepoint = ch;
return 1;
} else if ((ch & 0xE0) == 0xC0) {
// 2-byte sequence
*codepoint = ((ch & 0x1F) << 6) | (in[1] & 0x3F);
return 2;
} else if ((ch & 0xF0) == 0xE0) {
// 3-byte sequence
*codepoint = ((ch & 0x0F) << 12) | ((in[1] & 0x3F) << 6) | (in[2] & 0x3F);
return 3;
} else if ((ch & 0xF8) == 0xF0) {
// 4-byte sequence
*codepoint = ((ch & 0x07) << 18) | ((in[1] & 0x3F) << 12) | ((in[2] & 0x3F) << 6) | (in[3] & 0x3F);
return 4;
}
return -1;
}
inline
int32 utf8_strlen(const char* in) {
int32 length = 0;
int32 bytes;
uint32 codepoint;
while (*in) {
bytes = utf8_decode(in, &codepoint);
if (bytes < 0) {
return -1;
}
in += bytes;
++length;
}
return length;
}
inline
void string_to_utf8(const uint32* in, char* out) {
char buffer[5] = {0};
while (*in) {
int32 len = utf8_encode(*in, buffer);
if (len > 0) {
strncat(out, buffer, len);
}
++in;
}
}
inline
int32 utf8_get_char_at(const char* in, int32 index) {
int32 i = 0;
int32 bytes_consumed;
uint32 codepoint;
while (*in) {
bytes_consumed = utf8_decode(in, &codepoint);
if (bytes_consumed < 0) {
return -1;
}
if (i == index) {
return codepoint;
}
++i;
in += bytes_consumed;
}
return -1;
}
inline
void wchar_to_char(const wchar_t* src, char* dest, int32 length = 0)
{

View File

@ -64,7 +64,7 @@ void random_unique(int32* array, int32 size) {
/**
* Gets random index based value probability
*/
int random_weighted_index(int32* arr, int32 array_count)
int random_weighted_index(const int32* arr, int32 array_count)
{
uint32 prob_sum = 0;
for (int32 i = 0; i < array_count; ++i) {