1#include "cursor.h"
2
3void 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
10int 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
28int 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
57void *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
65void *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}