Changeset View
Standalone View
source/blender/blenlib/intern/array_utils.c
| Show All 21 Lines | |||||
| * and only included for the cases where the performance is acceptable. | * and only included for the cases where the performance is acceptable. | ||||
| * Use with care. | * Use with care. | ||||
| */ | */ | ||||
| #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_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_math_base.h" | |||||
| #include "BLI_strict_flags.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_array_utils.h" | ||||
| /** | /** | ||||
| *In-place array reverse. | *In-place array reverse. | ||||
| * | * | ||||
| * Access via #BLI_array_reverse | * Access via #BLI_array_reverse | ||||
| */ | */ | ||||
| void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) | void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 268 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: dimensions [w, h]. | |||||
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. | |||||
| * \param center: coordinates [x, y] indicating where to start transversing. | |||||
| */ | |||||
| bool _bli_array_iter_spiral_square(const void *arr_v, | |||||
| const int arr_shape[2], | |||||
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… | |||||
| size_t elem_size, | |||||
| 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}; | |||||
| /* Test center first. */ | |||||
| int ofs[2] = {center[0] * stride[0], center[1] * stride[1]}; | |||||
| if (test_fn(arr + ofs[0] + ofs[1], user_data)) { | |||||
| return true; | |||||
| } | |||||
| /* #steps_in and #steps_out are the "diameters" of the inscribed and ciscunscript squares in the | |||||
| * rectangle. Each step smaller than #steps_in does not need to check bounds. */ | |||||
| int steps_in, steps_out; | |||||
| { | |||||
| int x_minus = center[0]; | |||||
| int x_plus = arr_shape[0] - center[0] - 1; | |||||
| int y_minus = center[1]; | |||||
| int y_plus = arr_shape[1] - center[1] - 1; | |||||
| steps_in = 2 * min_iiii(x_minus, x_plus, y_minus, y_plus); | |||||
| steps_out = 2 * max_iiii(x_minus, x_plus, y_minus, y_plus); | |||||
| } | |||||
| /* For check_bounds. */ | |||||
| int limits[2] = {(arr_shape[0] - 1) * stride[0], stride[0] - stride[1]}; | |||||
| int steps = 0; | |||||
| while (steps < steps_out) { | |||||
| steps += 2; | |||||
| /* Move one step to the diagonal of the negative quadrant. */ | |||||
| ofs[0] -= stride[0]; | |||||
| ofs[1] -= stride[1]; | |||||
| bool check_bounds = steps > steps_in; | |||||
| /* sign: 0 neg; 1 pos */ | |||||
| for (int sign = 2; sign--;) { | |||||
| /* axis: 0 x; 1 y */ | |||||
| for (int axis = 2; axis--;) { | |||||
| int ofs_step = stride[axis]; | |||||
| if (!sign) { | |||||
| ofs_step *= -1; | |||||
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… | |||||
| } | |||||
| int ofs_iter = ofs[axis] + ofs_step; | |||||
| int ofs_dest = ofs[axis] + steps * ofs_step; | |||||
| int ofs_other = ofs[!axis]; | |||||
| ofs[axis] = ofs_dest; | |||||
| if (check_bounds) { | |||||
| if (ofs_other < 0 || ofs_other > limits[!axis]) { | |||||
| /* Out of bounds. */ | |||||
| continue; | |||||
| } | |||||
| CLAMP(ofs_iter, 0, limits[axis]); | |||||
| CLAMP(ofs_dest, 0, limits[axis]); | |||||
| } | |||||
| while (true) { | |||||
Done Inline ActionsKeep it simple: CLAMP(offset_src, 0, limits[axis]); CLAMP(offset_dst, 0, limits[axis]); brecht: Keep it simple:
```
CLAMP(offset_src, 0, limits[axis]);
CLAMP(offset_dst, 0, limits[axis]);
``` | |||||
| if (test_fn(arr + ofs_other + ofs_iter, user_data)) { | |||||
| return true; | |||||
| } | |||||
| if (ofs_iter == ofs_dest) { | |||||
| break; | |||||
| } | |||||
| ofs_iter += ofs_step; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
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.