• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CONCAT(send_hextile_tile_,NAME)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 = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
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->clientds.pf.bytes_per_pixel + 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 (n_colors < 3 && (!*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->clientds.pf.bytes_per_pixel;
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->clientds.pf.bytes_per_pixel;
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 * ds_get_bytes_per_pixel(vs->ds));
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
210