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