Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion base/sources/iron.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,10 @@ i32 parse_int_hex(const char *s) {
#endif

f32 parse_float(const char *s) {
return strtof(s, NULL);
// Replace comma with dot for locale-independent parsing
char *s_copy = string_replace_all(s, ",", ".");
f32 result = strtof(s_copy, NULL);
return result;
}

i32 color_from_floats(f32 r, f32 g, f32 b, f32 a) {
Expand Down
29 changes: 22 additions & 7 deletions base/sources/iron_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static int token_size() {

static bool has_dot(char *str, uint32_t len) {
for (uint32_t i = 0; i < len; ++i) {
if (str[i] == '.') {
if (str[i] == '.' || str[i] == ',') {
return true;
}
}
Expand Down Expand Up @@ -162,11 +162,16 @@ static void token_write() {
store_ptr_abs(NULL);
}
else {
has_dot(source + t.start, t.end - t.start) ? store_f32(strtof(source + t.start, NULL)) :
// Replace comma with dot for locale-independent parsing
char *num_str = string_copy(source + t.start);
for (int i = 0; i < (t.end - t.start); i++) {
if (num_str[i] == ',') num_str[i] = '.';
}
has_dot(source + t.start, t.end - t.start) ? store_f32(strtof(num_str, NULL)) :
#ifdef _WIN32
store_i32(_strtoi64(source + t.start, NULL, 10));
store_i32(_strtoi64(num_str, NULL, 10));
#else
store_i32(strtol(source + t.start, NULL, 10));
store_i32(strtol(num_str, NULL, 10));
#endif
}
}
Expand Down Expand Up @@ -452,7 +457,7 @@ static uint8_t jenc_forced_array_type;

static bool jenc_has_dot(int start, int end) {
for (int i = start; i < end; i++) {
if (jenc_src[i] == '.')
if (jenc_src[i] == '.' || jenc_src[i] == ',')
return true;
}
return false;
Expand Down Expand Up @@ -567,7 +572,12 @@ static void jenc_array(int count) {
armpack_write_u8(0xca);
for (int i = 0; i < count; i++) {
jsmntok_t t = jenc_tokens[jenc_ti++];
armpack_write_f32(strtof(jenc_src + t.start, NULL));
// Replace comma with dot for locale-independent parsing
char *num_str = string_copy(jenc_src + t.start);
for (int j = 0; j < (t.end - t.start); j++) {
if (num_str[j] == ',') num_str[j] = '.';
}
armpack_write_f32(strtof(num_str, NULL));
}
}
else if (elem_type == 0xd2) { // typed i32
Expand Down Expand Up @@ -637,7 +647,12 @@ static void jenc_value() {
}
else if (jenc_has_dot(t.start, t.end)) {
armpack_write_u8(0xca);
armpack_write_f32(strtof(jenc_src + t.start, NULL));
// Replace comma with dot for locale-independent parsing
char *num_str = string_copy(jenc_src + t.start);
for (int j = 0; j < (t.end - t.start); j++) {
if (num_str[j] == ',') num_str[j] = '.';
}
armpack_write_f32(strtof(num_str, NULL));
}
else {
armpack_write_u8(0xd2);
Expand Down
8 changes: 6 additions & 2 deletions base/sources/iron_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -2311,11 +2311,15 @@ float ui_slider(ui_handle_t *handle, char *text, float from, float to, bool fill
if (current->submit_text_handle == handle) {
ui_submit_text_edit();
#ifdef WITH_EVAL
minic_ctx_t *_ctx = minic_eval(string("float main() { return %s; }", handle->text));
// Replace comma with dot for locale-independent parsing
char *text_copy = string_replace_all(handle->text, ",", ".");
minic_ctx_t *_ctx = minic_eval(string("float main() { return %s; }", text_copy));
handle->f = minic_ctx_result(_ctx);
minic_ctx_free(_ctx);
#else
handle->f = atof(handle->text);
// Replace comma with dot for locale-independent parsing
char *text_copy = string_replace_all(handle->text, ",", ".");
handle->f = atof(text_copy);
#endif
handle->changed = current->changed = true;
}
Expand Down
4 changes: 3 additions & 1 deletion base/sources/iron_ui_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ float ui_float_input(ui_handle_t *handle, char *label, int align, float precisio
handle->text = tmp;
sprintf(handle->text, "%f", round(handle->f * precision) / precision);
char *text = ui_text_input(handle, label, align, true, false);
handle->f = atof(text);
// Replace comma with dot for locale-independent parsing
char *text_copy = string_replace_all(text, ",", ".");
handle->f = atof(text_copy);
return handle->f;
}

Expand Down
15 changes: 15 additions & 0 deletions base/sources/libs/minic.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,21 @@ static void minic_lex_next(minic_lexer_t *l) {
return;
}

if (c == '.' && isdigit((unsigned char)l->src[l->pos])) {
double n = 0;
double frac = 0.1;
while (isdigit((unsigned char)l->src[l->pos])) {
n += (l->src[l->pos++] - '0') * frac;
frac *= 0.1;
}
if (l->src[l->pos] == 'f' || l->src[l->pos] == 'F') {
l->pos++;
}
l->cur.val = minic_val_float((float)n);
l->cur.type = TOK_NUMBER;
return;
}

for (size_t k = 0; k < sizeof(minic_ops) / sizeof(minic_ops[0]); ++k) {
if (c == minic_ops[k].a && (minic_ops[k].b == 0 || l->src[l->pos + 1] == minic_ops[k].b)) {
l->pos += minic_ops[k].b != 0 ? 2 : 1;
Expand Down
13 changes: 13 additions & 0 deletions base/sources/libs/minic_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@ const char *test12 = " \n\
} \n\
";

// Test for leading-dot float literals (.3, .5f)
const char *test13 = " \n\
float main() { \n\
float a = .3; \n\
float b = .5f; \n\
float c = 0.0; \n\
c = .7; \n\
if (a == 0.3 && b == 0.5 && c == 0.7) { return 0.0; } \n\
return 1.0; \n\
} \n\
";

#define MINIC_TEST(n, src) \
do { \
minic_ctx_t *_c = minic_eval(src); \
Expand Down Expand Up @@ -216,6 +228,7 @@ void minic_tests() {
MINIC_TEST(10, test10);
MINIC_TEST(11, test11);
MINIC_TEST(12, test12);
MINIC_TEST(13, test13);
}

#endif
2 changes: 1 addition & 1 deletion paint/sources/nodes_brush/brush_output_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void brush_output_node_parse_inputs() {
}
}
else {
g_context->brush_nodes_opacity = opac->_f32;
g_context->brush_nodes_opacity = math_max(0.0, math_min(1.0, opac->_f32));
g_context->brush_mask_image = NULL;
}

Expand Down
1 change: 1 addition & 0 deletions paint/sources/ui/tab_layers.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ void tab_layers_draw_layer_context_menu_draw() {
ui_handle_t *layer_opac_handle = ui_nest(ui_handle(__ID__), l->id);
layer_opac_handle->f = l->mask_opacity;
ui_slider(layer_opac_handle, tr("Opacity"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
layer_opac_handle->f = math_max(0.0, math_min(1.0, layer_opac_handle->f));
if (layer_opac_handle->changed) {
if (g_ui->input_started) {
history_layer_opacity();
Expand Down
1 change: 1 addition & 0 deletions paint/sources/ui/tab_swatches.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ void tab_swatches_draw_edit_menu() {
ui_handle_t *hopacity = ui_handle(__ID__);
hopacity->f = g_context->swatch->opacity;
g_context->swatch->opacity = ui_slider(hopacity, "Opacity", 0, 1, true, 100.0, true, UI_ALIGN_RIGHT, true);
g_context->swatch->opacity = math_max(0.0, math_min(1.0, g_context->swatch->opacity));

if (g_config->workflow == WORKFLOW_PBR) {
ui_handle_t *hocclusion = ui_handle(__ID__);
Expand Down
2 changes: 2 additions & 0 deletions paint/sources/ui/ui_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ void ui_header_draw_tool_properties() {
ui_handle_t *hopac = ui_handle(__ID__);
hopac->f = g_context->picked_color->opacity;
g_context->picked_color->opacity = ui_slider(hopac, tr("Opacity"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
g_context->picked_color->opacity = math_max(0.0, math_min(1.0, g_context->picked_color->opacity));

ui_handle_t *h_select_mat = ui_handle(__ID__);
h_select_mat->b = g_context->picker_select_material;
Expand Down Expand Up @@ -369,6 +370,7 @@ void ui_header_draw_tool_properties() {
ui_handle_t *brush_opacity_handle = ui_handle(__ID__);
brush_opacity_handle->f = g_context->brush_opacity;
g_context->brush_opacity = ui_slider(brush_opacity_handle, tr("Opacity"), 0.0, 1.0, true, 100.0, true, UI_ALIGN_RIGHT, true);
g_context->brush_opacity = math_max(0.0, math_min(1.0, g_context->brush_opacity));
if (g_ui->is_hovered) {
any_map_t *vars = any_map_create();
any_map_set(vars, "brush_opacity", any_map_get(g_keymap, "brush_opacity"));
Expand Down
2 changes: 1 addition & 1 deletion paint/sources/uniforms.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ f32 uniforms_ext_f32_link(object_t *object, material_data_t *mat, char *link) {
if (g_config->pressure_opacity && pen_down("tip") && !slot_layer_is_path(g_context->layer)) {
val *= pen_pressure * g_config->pressure_sensitivity;
}
return val;
return math_max(0.0, math_min(1.0, val));
}
else if (string_equals(link, "_brush_hardness")) {
bool decal_mask = context_is_decal_mask_paint();
Expand Down