Changeset View
Standalone View
source/blender/blenlib/intern/array_utils.c
| Show All 24 Lines | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_array_utils.h" | #include "BLI_array_utils.h" | ||||
| #include "BLI_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_math_base.h" | |||||
| #include "BLI_sys_types.h" | #include "BLI_sys_types.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_strict_flags.h" | #include "BLI_strict_flags.h" | ||||
| /** | /** | ||||
| *In-place array reverse. | *In-place array reverse. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | bool _bli_array_is_zeroed(const void *arr_v, unsigned int arr_len, size_t arr_stride) | ||||
| size_t i = arr_stride * arr_len; | size_t i = arr_stride * arr_len; | ||||
| while (i--) { | while (i--) { | ||||
| if (*(arr_step++)) { | if (*(arr_step++)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** | |||||
| * Smart function to sample a rect spiraling outside, nice for selection ID. | |||||
| * | |||||
| * \param arr_shape: size [h, w]. | |||||
| * \param center: coordinates [y, x] indicating where to start reading. | |||||
brecht: Why flip the x/y order? I'm having a hard time reading the code since I have to mentally flip… | |||||
Done Inline ActionsIn fact, using the x, y order can be useful when, for example, the mouse coordinates are passed. value = buff[h][w] Having the h before the w. But this is not mandatory. In fact, I had set the order x, y before. mano-wii: In fact, using the x, y order can be useful when, for example, the mouse coordinates are passed. | |||||
Done Inline ActionsPlease use the standard x,y and w,h order we use everywhere else in Blender. brecht: Please use the standard x,y and w,h order we use everywhere else in Blender. | |||||
| */ | |||||
| bool _bli_array_iter_spiral_square(const void *arr_v, | |||||
| const int arr_shape[2], | |||||
| size_t elem_size, | |||||
Done Inline ActionsThis stride handling is too complicated. All you need is the size of an element, and you can multiply with that at the very end when calling test_fn, using it earlier makes things hard to understand. brecht: This stride handling is too complicated.
All you need is the size of an element, and you can… | |||||
Done Inline Actions
I feel that the patch will have to change a lot if it is to implement another way of dealing with the offsets. test_fn(arr + offset_other + offset_iter, user_data) mano-wii: > (...) and you can multiply with that at the very end when calling `test_fn`, using it earlier… | |||||
| const int center[2], | |||||
| const bool (*test_fn)(const void *arr_item, void *user_data), | |||||
| void *user_data) | |||||
| { | |||||
| BLI_assert(center[0] >= 0 && center[1] >= 0 && center[0] < arr_shape[0] && | |||||
| center[1] < arr_shape[1]); | |||||
| const char *arr = arr_v; | |||||
| const int stride[2] = {arr_shape[1] * (int)elem_size, (int)elem_size}; | |||||
| int offset[2] = {center[0] * stride[0], center[1] * stride[1]}; | |||||
| if (test_fn(arr + offset[0] + offset[1], user_data)) { | |||||
| return true; | |||||
| } | |||||
| int step_num = 1; | |||||
| int limits[2]; | |||||
| limits[0] = (arr_shape[0] - 1) * stride[0]; | |||||
| limits[1] = stride[0] - stride[1]; | |||||
| bool sign = false; | |||||
| while (true) { | |||||
| int axis = 2; | |||||
| while (axis--) { | |||||
| int offset_step = stride[axis]; | |||||
| if (!sign) { | |||||
| offset_step *= -1; | |||||
| } | |||||
| int offset_iter = offset[axis] + offset_step; | |||||
| int offset_end = offset[axis] + step_num * offset_step; | |||||
| /* Even if the offset_end is out bound, update the result. */ | |||||
| offset[axis] = offset_end; | |||||
| int offset_other = offset[!axis]; | |||||
| if (offset_other < 0 || offset_other > limits[!axis]) { | |||||
| /* This entire range is out of bound. */ | |||||
| continue; | |||||
| } | |||||
| CLAMP(offset_iter, 0, limits[axis]); | |||||
| CLAMP(offset_end, 0, limits[axis]); | |||||
| /* Iterate each value in the range. */ | |||||
| while (true) { | |||||
| if (test_fn(arr + offset_other + offset_iter, user_data)) { | |||||
| return true; | |||||
| } | |||||
| if (offset_iter == offset_end) { | |||||
| break; | |||||
Done Inline ActionsUse start/end rather then src/dst, the latter is usually used to copy something from src to dst, not for iteration. brecht: Use start/end rather then src/dst, the latter is usually used to copy something from src to dst… | |||||
| } | |||||
| offset_iter += offset_step; | |||||
| } | |||||
| } | |||||
| if ((offset[0] < 0 || offset[0] > limits[0]) && (offset[1] < 0 || offset[1] > limits[1])) { | |||||
| return false; | |||||
| } | |||||
| step_num++; | |||||
| sign = !sign; | |||||
| } | |||||
| } | |||||
Done Inline ActionsComputing step_max in advance looks tricky, can you terminate in a way similar to the old code, but checking both axes? if ((offset[0] < 0 || offset[0] > limits[0]) &&
(offset[1] < 0 || offset[1] > limits[1]))brecht: Computing `step_max` in advance looks tricky, can you terminate in a way similar to the old… | |||||
Why flip the x/y order? I'm having a hard time reading the code since I have to mentally flip the axes all the time.