]>
Commit | Line | Data |
---|---|---|
24236869 FB |
1 | #define CONCAT_I(a, b) a ## b |
2 | #define CONCAT(a, b) CONCAT_I(a, b) | |
3 | #define pixel_t CONCAT(uint, CONCAT(BPP, _t)) | |
4 | ||
5 | static void CONCAT(send_hextile_tile_, BPP)(VncState *vs, | |
6 | int x, int y, int w, int h, | |
7 | pixel_t *last_bg, pixel_t *last_fg, | |
8 | int *has_bg, int *has_fg) | |
9 | { | |
10 | char *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth); | |
11 | pixel_t *irow = (pixel_t *)row; | |
12 | int j, i; | |
13 | pixel_t bg = 0; | |
14 | pixel_t fg = 0; | |
15 | int n_colors = 0; | |
16 | int bg_count = 0; | |
17 | int fg_count = 0; | |
18 | int flags = 0; | |
19 | uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16]; | |
20 | int n_data = 0; | |
21 | int n_subtiles = 0; | |
22 | ||
23 | for (j = 0; j < h; j++) { | |
24 | for (i = 0; i < w; i++) { | |
25 | switch (n_colors) { | |
26 | case 0: | |
27 | bg = irow[i]; | |
28 | n_colors = 1; | |
29 | break; | |
30 | case 1: | |
31 | if (irow[i] != bg) { | |
32 | fg = irow[i]; | |
33 | n_colors = 2; | |
34 | } | |
35 | break; | |
36 | case 2: | |
37 | if (irow[i] != bg && irow[i] != fg) { | |
38 | n_colors = 3; | |
39 | } else { | |
40 | if (irow[i] == bg) | |
41 | bg_count++; | |
42 | else if (irow[i] == fg) | |
43 | fg_count++; | |
44 | } | |
45 | break; | |
46 | default: | |
47 | break; | |
48 | } | |
49 | } | |
50 | if (n_colors > 2) | |
51 | break; | |
52 | irow += vs->ds->linesize / sizeof(pixel_t); | |
53 | } | |
54 | ||
55 | if (n_colors > 1 && fg_count > bg_count) { | |
56 | pixel_t tmp = fg; | |
57 | fg = bg; | |
58 | bg = tmp; | |
59 | } | |
60 | ||
61 | if (!*has_bg || *last_bg != bg) { | |
62 | flags |= 0x02; | |
63 | *has_bg = 1; | |
64 | *last_bg = bg; | |
65 | } | |
66 | ||
67 | if (!*has_fg || *last_fg != fg) { | |
68 | flags |= 0x04; | |
69 | *has_fg = 1; | |
70 | *last_fg = fg; | |
71 | } | |
72 | ||
73 | switch (n_colors) { | |
74 | case 1: | |
75 | n_data = 0; | |
76 | break; | |
77 | case 2: | |
78 | flags |= 0x08; | |
79 | ||
80 | irow = (pixel_t *)row; | |
81 | ||
82 | for (j = 0; j < h; j++) { | |
83 | int min_x = -1; | |
84 | for (i = 0; i < w; i++) { | |
85 | if (irow[i] == fg) { | |
86 | if (min_x == -1) | |
87 | min_x = i; | |
88 | } else if (min_x != -1) { | |
89 | hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1); | |
90 | n_data += 2; | |
91 | n_subtiles++; | |
92 | min_x = -1; | |
93 | } | |
94 | } | |
95 | if (min_x != -1) { | |
96 | hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1); | |
97 | n_data += 2; | |
98 | n_subtiles++; | |
99 | } | |
100 | irow += vs->ds->linesize / sizeof(pixel_t); | |
101 | } | |
102 | break; | |
103 | case 3: | |
104 | flags |= 0x18; | |
105 | ||
106 | irow = (pixel_t *)row; | |
107 | ||
108 | if (!*has_bg || *last_bg != bg) | |
109 | flags |= 0x02; | |
110 | ||
111 | for (j = 0; j < h; j++) { | |
112 | int has_color = 0; | |
113 | int min_x = -1; | |
114 | pixel_t color; | |
115 | ||
116 | for (i = 0; i < w; i++) { | |
117 | if (!has_color) { | |
118 | if (irow[i] == bg) | |
119 | continue; | |
120 | color = irow[i]; | |
121 | min_x = i; | |
122 | has_color = 1; | |
123 | } else if (irow[i] != color) { | |
124 | has_color = 0; | |
125 | ||
126 | memcpy(data + n_data, &color, sizeof(color)); | |
127 | hextile_enc_cord(data + n_data + sizeof(pixel_t), min_x, j, i - min_x, 1); | |
128 | n_data += 2 + sizeof(pixel_t); | |
129 | n_subtiles++; | |
130 | ||
131 | min_x = -1; | |
132 | if (irow[i] != bg) { | |
133 | color = irow[i]; | |
134 | min_x = i; | |
135 | has_color = 1; | |
136 | } | |
137 | } | |
138 | } | |
139 | if (has_color) { | |
140 | memcpy(data + n_data, &color, sizeof(color)); | |
141 | hextile_enc_cord(data + n_data + sizeof(pixel_t), min_x, j, i - min_x, 1); | |
142 | n_data += 2 + sizeof(pixel_t); | |
143 | n_subtiles++; | |
144 | } | |
145 | irow += vs->ds->linesize / sizeof(pixel_t); | |
146 | } | |
147 | ||
148 | /* A SubrectsColoured subtile invalidates the foreground color */ | |
149 | *has_fg = 0; | |
150 | if (n_data > (w * h * sizeof(pixel_t))) { | |
151 | n_colors = 4; | |
152 | flags = 0x01; | |
153 | *has_bg = 0; | |
154 | ||
155 | /* we really don't have to invalidate either the bg or fg | |
156 | but we've lost the old values. oh well. */ | |
157 | } | |
158 | default: | |
159 | break; | |
160 | } | |
161 | ||
162 | if (n_colors > 3) { | |
163 | flags = 0x01; | |
164 | *has_fg = 0; | |
165 | *has_bg = 0; | |
166 | n_colors = 4; | |
167 | } | |
168 | ||
169 | vnc_write_u8(vs, flags); | |
170 | if (n_colors < 4) { | |
171 | if (flags & 0x02) | |
172 | vnc_write(vs, last_bg, sizeof(pixel_t)); | |
173 | if (flags & 0x04) | |
174 | vnc_write(vs, last_fg, sizeof(pixel_t)); | |
175 | if (n_subtiles) { | |
176 | vnc_write_u8(vs, n_subtiles); | |
177 | vnc_write(vs, data, n_data); | |
178 | } | |
179 | } else { | |
180 | for (j = 0; j < h; j++) { | |
181 | vnc_write(vs, row, w * vs->depth); | |
182 | row += vs->ds->linesize; | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | #undef pixel_t | |
188 | #undef CONCAT_I | |
189 | #undef CONCAT |