| 1 | #include "cursor.h" |
| 2 | |
| 3 | void sg_word(uint8_t *bytes, uint32_t value) { |
| 4 | bytes[0] = (uint8_t)(value >> 24); |
| 5 | bytes[1] = (uint8_t)(value >> 16); |
| 6 | bytes[2] = (uint8_t)(value >> 8); |
| 7 | bytes[3] = (uint8_t)value; |
| 8 | } |
| 9 | |
| 10 | int sg_difference(const uint8_t *before, const uint8_t *after, uint32_t width, uint32_t height, struct sg_rect *rect) { |
| 11 | uint32_t x, y, left = width, top = height, right = 0, bottom = 0; |
| 12 | if (!width || !height || width > SG_MAX_DIMENSION || height > SG_MAX_DIMENSION || width * height > SG_MAX_PIXELS) return -1; |
| 13 | for (y = 0; y < height; ++y) { |
| 14 | for (x = 0; x < width; ++x) { |
| 15 | size_t pixel = ((size_t)y * width + x) * 4; |
| 16 | if (before[pixel] == after[pixel] && before[pixel + 1] == after[pixel + 1] && before[pixel + 2] == after[pixel + 2]) continue; |
| 17 | if (x < left) left = x; |
| 18 | if (y < top) top = y; |
| 19 | if (x >= right) right = x + 1; |
| 20 | if (y >= bottom) bottom = y + 1; |
| 21 | } |
| 22 | } |
| 23 | if (left == width) return 0; |
| 24 | rect->x = left; rect->y = top; rect->width = right - left; rect->height = bottom - top; |
| 25 | return 1; |
| 26 | } |
| 27 | |
| 28 | int sg_rgba(const uint8_t *black, const uint8_t *white, uint8_t *rgba, uint8_t *invert, size_t pixels) { |
| 29 | size_t i; |
| 30 | for (i = 0; i < pixels; ++i) { |
| 31 | int difference = (int)white[i * 4] - black[i * 4]; |
| 32 | int green = (int)white[i * 4 + 1] - black[i * 4 + 1]; |
| 33 | int red = (int)white[i * 4 + 2] - black[i * 4 + 2]; |
| 34 | unsigned alpha; |
| 35 | invert[i] = 0; |
| 36 | if (difference < 0 || green < 0 || red < 0 || green - difference > 1 || difference - green > 1 || red - difference > 1 || difference - red > 1) { |
| 37 | unsigned channel; |
| 38 | for (channel = 0; channel < 3; ++channel) { |
| 39 | uint8_t value = black[i * 4 + channel]; |
| 40 | if ((value != 0 && value != 255) || (value ^ white[i * 4 + channel]) != 255) return 0; |
| 41 | } |
| 42 | invert[i] = (black[i * 4 + 2] ? SG_XOR_RED : 0) | (black[i * 4 + 1] ? SG_XOR_GREEN : 0) | (black[i * 4] ? SG_XOR_BLUE : 0); |
| 43 | alpha = 0; |
| 44 | } else alpha = 255u - (unsigned)((difference + green + red + 1) / 3); |
| 45 | rgba[i * 4 + 3] = (uint8_t)alpha; |
| 46 | { |
| 47 | unsigned channel; |
| 48 | for (channel = 0; channel < 3; ++channel) { |
| 49 | unsigned value = alpha ? (black[i * 4 + 2 - channel] * 255u + alpha / 2) / alpha : 0; |
| 50 | rgba[i * 4 + channel] = (uint8_t)(value > 255 ? 255 : value); |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | return 1; |
| 55 | } |
| 56 | |
| 57 | void *memcpy(void *destination, const void *source, size_t length) { |
| 58 | uint8_t *out = destination; |
| 59 | const uint8_t *in = source; |
| 60 | size_t i; |
| 61 | for (i = 0; i < length; ++i) out[i] = in[i]; |
| 62 | return destination; |
| 63 | } |
| 64 | |
| 65 | void *memset(void *destination, int value, size_t length) { |
| 66 | uint8_t *out = destination; |
| 67 | size_t i; |
| 68 | for (i = 0; i < length; ++i) out[i] = (uint8_t)value; |
| 69 | return destination; |
| 70 | } |