00001 #define CONCAT_I(a, b) a ## b
00002 #define CONCAT(a, b) CONCAT_I(a, b)
00003 #define pixel_t CONCAT(uint, CONCAT(BPP, _t))
00004 #ifdef GENERIC
00005 #define NAME CONCAT(generic_, BPP)
00006 #else
00007 #define NAME BPP
00008 #endif
00009
00010 static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
00011 int x, int y, int w, int h,
00012 void *last_bg_,
00013 void *last_fg_,
00014 int *has_bg, int *has_fg)
00015 {
00016 uint8_t *row = (ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds));
00017 pixel_t *irow = (pixel_t *)row;
00018 int j, i;
00019 pixel_t *last_bg = (pixel_t *)last_bg_;
00020 pixel_t *last_fg = (pixel_t *)last_fg_;
00021 pixel_t bg = 0;
00022 pixel_t fg = 0;
00023 int n_colors = 0;
00024 int bg_count = 0;
00025 int fg_count = 0;
00026 int flags = 0;
00027 uint8_t data[(vs->clientds.pf.bytes_per_pixel + 2) * 16 * 16];
00028 int n_data = 0;
00029 int n_subtiles = 0;
00030
00031 for (j = 0; j < h; j++) {
00032 for (i = 0; i < w; i++) {
00033 switch (n_colors) {
00034 case 0:
00035 bg = irow[i];
00036 n_colors = 1;
00037 break;
00038 case 1:
00039 if (irow[i] != bg) {
00040 fg = irow[i];
00041 n_colors = 2;
00042 }
00043 break;
00044 case 2:
00045 if (irow[i] != bg && irow[i] != fg) {
00046 n_colors = 3;
00047 } else {
00048 if (irow[i] == bg)
00049 bg_count++;
00050 else if (irow[i] == fg)
00051 fg_count++;
00052 }
00053 break;
00054 default:
00055 break;
00056 }
00057 }
00058 if (n_colors > 2)
00059 break;
00060 irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
00061 }
00062
00063 if (n_colors > 1 && fg_count > bg_count) {
00064 pixel_t tmp = fg;
00065 fg = bg;
00066 bg = tmp;
00067 }
00068
00069 if (!*has_bg || *last_bg != bg) {
00070 flags |= 0x02;
00071 *has_bg = 1;
00072 *last_bg = bg;
00073 }
00074
00075 if (!*has_fg || *last_fg != fg) {
00076 flags |= 0x04;
00077 *has_fg = 1;
00078 *last_fg = fg;
00079 }
00080
00081 switch (n_colors) {
00082 case 1:
00083 n_data = 0;
00084 break;
00085 case 2:
00086 flags |= 0x08;
00087
00088 irow = (pixel_t *)row;
00089
00090 for (j = 0; j < h; j++) {
00091 int min_x = -1;
00092 for (i = 0; i < w; i++) {
00093 if (irow[i] == fg) {
00094 if (min_x == -1)
00095 min_x = i;
00096 } else if (min_x != -1) {
00097 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
00098 n_data += 2;
00099 n_subtiles++;
00100 min_x = -1;
00101 }
00102 }
00103 if (min_x != -1) {
00104 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
00105 n_data += 2;
00106 n_subtiles++;
00107 }
00108 irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
00109 }
00110 break;
00111 case 3:
00112 flags |= 0x18;
00113
00114 irow = (pixel_t *)row;
00115
00116 if (!*has_bg || *last_bg != bg)
00117 flags |= 0x02;
00118
00119 for (j = 0; j < h; j++) {
00120 int has_color = 0;
00121 int min_x = -1;
00122 pixel_t color = 0;
00123
00124 for (i = 0; i < w; i++) {
00125 if (!has_color) {
00126 if (irow[i] == bg)
00127 continue;
00128 color = irow[i];
00129 min_x = i;
00130 has_color = 1;
00131 } else if (irow[i] != color) {
00132 has_color = 0;
00133 #ifdef GENERIC
00134 vnc_convert_pixel(vs, data + n_data, color);
00135 n_data += vs->clientds.pf.bytes_per_pixel;
00136 #else
00137 memcpy(data + n_data, &color, sizeof(color));
00138 n_data += sizeof(pixel_t);
00139 #endif
00140 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
00141 n_data += 2;
00142 n_subtiles++;
00143
00144 min_x = -1;
00145 if (irow[i] != bg) {
00146 color = irow[i];
00147 min_x = i;
00148 has_color = 1;
00149 }
00150 }
00151 }
00152 if (has_color) {
00153 #ifdef GENERIC
00154 vnc_convert_pixel(vs, data + n_data, color);
00155 n_data += vs->clientds.pf.bytes_per_pixel;
00156 #else
00157 memcpy(data + n_data, &color, sizeof(color));
00158 n_data += sizeof(pixel_t);
00159 #endif
00160 hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
00161 n_data += 2;
00162 n_subtiles++;
00163 }
00164 irow += ds_get_linesize(vs->ds) / sizeof(pixel_t);
00165 }
00166
00167
00168 *has_fg = 0;
00169 if (n_data > (w * h * sizeof(pixel_t))) {
00170 n_colors = 4;
00171 flags = 0x01;
00172 *has_bg = 0;
00173
00174
00175
00176 }
00177 default:
00178 break;
00179 }
00180
00181 if (n_colors > 3) {
00182 flags = 0x01;
00183 *has_fg = 0;
00184 *has_bg = 0;
00185 n_colors = 4;
00186 }
00187
00188 vnc_write_u8(vs, flags);
00189 if (n_colors < 4) {
00190 if (flags & 0x02)
00191 vs->write_pixels(vs, last_bg, sizeof(pixel_t));
00192 if (flags & 0x04)
00193 vs->write_pixels(vs, last_fg, sizeof(pixel_t));
00194 if (n_subtiles) {
00195 vnc_write_u8(vs, n_subtiles);
00196 vnc_write(vs, data, n_data);
00197 }
00198 } else {
00199 for (j = 0; j < h; j++) {
00200 vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
00201 row += ds_get_linesize(vs->ds);
00202 }
00203 }
00204 }
00205
00206 #undef NAME
00207 #undef pixel_t
00208 #undef CONCAT_I
00209 #undef CONCAT