18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CONCAT_I(a, b) a ## b
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CONCAT(a, b) CONCAT_I(a, b)
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define pixel_t CONCAT(uint, CONCAT(BPP, _t))
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef GENERIC
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAME CONCAT(generic_, BPP)
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NAME BPP
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                             int x, int y, int w, int h,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                             void *last_bg_,
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                             void *last_fg_,
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                             int *has_bg, int *has_fg)
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pixel_t *irow = (pixel_t *)row;
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int j, i;
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pixel_t *last_bg = (pixel_t *)last_bg_;
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pixel_t *last_fg = (pixel_t *)last_fg_;
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pixel_t bg = 0;
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pixel_t fg = 0;
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n_colors = 0;
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bg_count = 0;
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fg_count = 0;
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int flags = 0;
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16];
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n_data = 0;
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n_subtiles = 0;
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (j = 0; j < h; j++) {
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (i = 0; i < w; i++) {
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    switch (n_colors) {
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 0:
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		bg = irow[i];
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n_colors = 1;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 1:
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (irow[i] != bg) {
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    fg = irow[i];
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_colors = 2;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 2:
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (irow[i] != bg && irow[i] != fg) {
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_colors = 3;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else {
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    if (irow[i] == bg)
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			bg_count++;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    else if (irow[i] == fg)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			fg_count++;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    default:
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n_colors > 2)
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    break;
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n_colors > 1 && fg_count > bg_count) {
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	pixel_t tmp = fg;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	fg = bg;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	bg = tmp;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!*has_bg || *last_bg != bg) {
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	flags |= 0x02;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*has_bg = 1;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*last_bg = bg;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	flags |= 0x04;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*has_fg = 1;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*last_fg = fg;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (n_colors) {
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n_data = 0;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	flags |= 0x08;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	irow = (pixel_t *)row;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (j = 0; j < h; j++) {
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    int min_x = -1;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    for (i = 0; i < w; i++) {
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (irow[i] == fg) {
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    if (min_x == -1)
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			min_x = i;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else if (min_x != -1) {
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_data += 2;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_subtiles++;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    min_x = -1;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (min_x != -1) {
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n_data += 2;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n_subtiles++;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3:
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	flags |= 0x18;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	irow = (pixel_t *)row;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (!*has_bg || *last_bg != bg)
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    flags |= 0x02;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (j = 0; j < h; j++) {
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    int has_color = 0;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    int min_x = -1;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    pixel_t color = 0; /* shut up gcc */
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    for (i = 0; i < w; i++) {
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (!has_color) {
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    if (irow[i] == bg)
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			continue;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    color = irow[i];
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    min_x = i;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    has_color = 1;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else if (irow[i] != color) {
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    has_color = 0;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef GENERIC
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    vnc_convert_pixel(vs, data + n_data, color);
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    n_data += vs->clientds.pf.bytes_per_pixel;
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    memcpy(data + n_data, &color, sizeof(color));
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n_data += sizeof(pixel_t);
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_data += 2;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    n_subtiles++;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    min_x = -1;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    if (irow[i] != bg) {
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			color = irow[i];
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			min_x = i;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			has_color = 1;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    }
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (has_color) {
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef GENERIC
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                vnc_convert_pixel(vs, data + n_data, color);
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                n_data += vs->clientds.pf.bytes_per_pixel;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                memcpy(data + n_data, &color, sizeof(color));
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                n_data += sizeof(pixel_t);
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n_data += 2;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n_subtiles++;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* A SubrectsColoured subtile invalidates the foreground color */
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*has_fg = 0;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n_data > (w * h * sizeof(pixel_t))) {
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    n_colors = 4;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    flags = 0x01;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    *has_bg = 0;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /* we really don't have to invalidate either the bg or fg
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	       but we've lost the old values.  oh well. */
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n_colors > 3) {
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	flags = 0x01;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*has_fg = 0;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*has_bg = 0;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n_colors = 4;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vnc_write_u8(vs, flags);
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n_colors < 4) {
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (flags & 0x02)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    vs->write_pixels(vs, last_bg, sizeof(pixel_t));
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (flags & 0x04)
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    vs->write_pixels(vs, last_fg, sizeof(pixel_t));
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n_subtiles) {
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    vnc_write_u8(vs, n_subtiles);
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    vnc_write(vs, data, n_data);
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (j = 0; j < h; j++) {
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    row += ds_get_linesize(vs->ds);
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef NAME
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef pixel_t
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef CONCAT_I
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef CONCAT
210