1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2012 Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker *
4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker *
6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker *
12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker *
18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker *
24*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker */
26*2d1272b8SAndroid Build Coastguard Worker
27*2d1272b8SAndroid Build Coastguard Worker #ifndef ANSI_PRINT_HH
28*2d1272b8SAndroid Build Coastguard Worker #define ANSI_PRINT_HH
29*2d1272b8SAndroid Build Coastguard Worker
30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
31*2d1272b8SAndroid Build Coastguard Worker
32*2d1272b8SAndroid Build Coastguard Worker #include <cairo.h>
33*2d1272b8SAndroid Build Coastguard Worker
34*2d1272b8SAndroid Build Coastguard Worker #include <assert.h>
35*2d1272b8SAndroid Build Coastguard Worker #include <stdlib.h>
36*2d1272b8SAndroid Build Coastguard Worker #include <stddef.h>
37*2d1272b8SAndroid Build Coastguard Worker #include <string.h>
38*2d1272b8SAndroid Build Coastguard Worker #include <math.h>
39*2d1272b8SAndroid Build Coastguard Worker
40*2d1272b8SAndroid Build Coastguard Worker #if defined (_MSC_VER) && (_MSC_VER < 1800)
41*2d1272b8SAndroid Build Coastguard Worker static inline long int
lround(double x)42*2d1272b8SAndroid Build Coastguard Worker lround (double x)
43*2d1272b8SAndroid Build Coastguard Worker {
44*2d1272b8SAndroid Build Coastguard Worker if (x >= 0)
45*2d1272b8SAndroid Build Coastguard Worker return floor (x + 0.5);
46*2d1272b8SAndroid Build Coastguard Worker else
47*2d1272b8SAndroid Build Coastguard Worker return ceil (x - 0.5);
48*2d1272b8SAndroid Build Coastguard Worker }
49*2d1272b8SAndroid Build Coastguard Worker #endif
50*2d1272b8SAndroid Build Coastguard Worker
51*2d1272b8SAndroid Build Coastguard Worker #define CELL_W 8
52*2d1272b8SAndroid Build Coastguard Worker #define CELL_H (2 * CELL_W)
53*2d1272b8SAndroid Build Coastguard Worker
54*2d1272b8SAndroid Build Coastguard Worker struct color_diff_t
55*2d1272b8SAndroid Build Coastguard Worker {
dotcolor_diff_t56*2d1272b8SAndroid Build Coastguard Worker int dot (const color_diff_t &o)
57*2d1272b8SAndroid Build Coastguard Worker { return v[0]*o.v[0] + v[1]*o.v[1] + v[2]*o.v[2] + v[3]*o.v[3]; }
58*2d1272b8SAndroid Build Coastguard Worker
59*2d1272b8SAndroid Build Coastguard Worker int v[4];
60*2d1272b8SAndroid Build Coastguard Worker };
61*2d1272b8SAndroid Build Coastguard Worker
62*2d1272b8SAndroid Build Coastguard Worker struct color_t
63*2d1272b8SAndroid Build Coastguard Worker {
from_ansicolor_t64*2d1272b8SAndroid Build Coastguard Worker static color_t from_ansi (unsigned int x)
65*2d1272b8SAndroid Build Coastguard Worker {
66*2d1272b8SAndroid Build Coastguard Worker color_t c = {(0xFFu<<24) | ((0xFFu*(x&1))<<16) | ((0xFFu*((x >> 1)&1))<<8) | (0xFFu*((x >> 2)&1))};
67*2d1272b8SAndroid Build Coastguard Worker return c;
68*2d1272b8SAndroid Build Coastguard Worker }
to_ansicolor_t69*2d1272b8SAndroid Build Coastguard Worker unsigned int to_ansi ()
70*2d1272b8SAndroid Build Coastguard Worker {
71*2d1272b8SAndroid Build Coastguard Worker return ((v >> 23) & 1) | ((v >> 14)&2) | ((v >> 5)&4);
72*2d1272b8SAndroid Build Coastguard Worker }
73*2d1272b8SAndroid Build Coastguard Worker
diffcolor_t74*2d1272b8SAndroid Build Coastguard Worker color_diff_t diff (const color_t &o)
75*2d1272b8SAndroid Build Coastguard Worker {
76*2d1272b8SAndroid Build Coastguard Worker color_diff_t d;
77*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < 4; i++)
78*2d1272b8SAndroid Build Coastguard Worker d.v[i] = (int) ((v >> (i*8))&0xFF) - (int) ((o.v >> (i*8))&0xFF);
79*2d1272b8SAndroid Build Coastguard Worker return d;
80*2d1272b8SAndroid Build Coastguard Worker }
81*2d1272b8SAndroid Build Coastguard Worker
82*2d1272b8SAndroid Build Coastguard Worker uint32_t v;
83*2d1272b8SAndroid Build Coastguard Worker };
84*2d1272b8SAndroid Build Coastguard Worker
85*2d1272b8SAndroid Build Coastguard Worker struct image_t
86*2d1272b8SAndroid Build Coastguard Worker {
87*2d1272b8SAndroid Build Coastguard Worker public:
88*2d1272b8SAndroid Build Coastguard Worker
image_timage_t89*2d1272b8SAndroid Build Coastguard Worker image_t (unsigned int width_,
90*2d1272b8SAndroid Build Coastguard Worker unsigned int height_,
91*2d1272b8SAndroid Build Coastguard Worker const uint32_t *data_,
92*2d1272b8SAndroid Build Coastguard Worker unsigned int stride_) :
93*2d1272b8SAndroid Build Coastguard Worker width (width_),
94*2d1272b8SAndroid Build Coastguard Worker height (height_),
95*2d1272b8SAndroid Build Coastguard Worker own_data (false),
96*2d1272b8SAndroid Build Coastguard Worker data ((color_t *) data_),
97*2d1272b8SAndroid Build Coastguard Worker stride (stride_) {}
image_timage_t98*2d1272b8SAndroid Build Coastguard Worker image_t (unsigned int width_,
99*2d1272b8SAndroid Build Coastguard Worker unsigned int height_) :
100*2d1272b8SAndroid Build Coastguard Worker width (width_),
101*2d1272b8SAndroid Build Coastguard Worker height (height_),
102*2d1272b8SAndroid Build Coastguard Worker own_data (true),
103*2d1272b8SAndroid Build Coastguard Worker data ((color_t *) malloc (sizeof (data[0]) * width * height)),
104*2d1272b8SAndroid Build Coastguard Worker stride (width) {}
~image_timage_t105*2d1272b8SAndroid Build Coastguard Worker ~image_t ()
106*2d1272b8SAndroid Build Coastguard Worker { if (own_data) free (data); }
107*2d1272b8SAndroid Build Coastguard Worker
operator ()image_t108*2d1272b8SAndroid Build Coastguard Worker color_t &operator () (unsigned int x, unsigned int y)
109*2d1272b8SAndroid Build Coastguard Worker { return data[x + y * stride]; }
110*2d1272b8SAndroid Build Coastguard Worker
operator ()image_t111*2d1272b8SAndroid Build Coastguard Worker color_t operator () (unsigned int x, unsigned int y) const
112*2d1272b8SAndroid Build Coastguard Worker { return data[x + y * stride]; }
113*2d1272b8SAndroid Build Coastguard Worker
114*2d1272b8SAndroid Build Coastguard Worker void
copy_sub_imageimage_t115*2d1272b8SAndroid Build Coastguard Worker copy_sub_image (const image_t &s,
116*2d1272b8SAndroid Build Coastguard Worker unsigned int x, unsigned int y,
117*2d1272b8SAndroid Build Coastguard Worker unsigned int w, unsigned int h)
118*2d1272b8SAndroid Build Coastguard Worker {
119*2d1272b8SAndroid Build Coastguard Worker assert (x < width);
120*2d1272b8SAndroid Build Coastguard Worker assert (y < height);
121*2d1272b8SAndroid Build Coastguard Worker for (unsigned int row = 0; row < h; row++) {
122*2d1272b8SAndroid Build Coastguard Worker color_t *p = data + x + hb_min (y + row, height - 1) * stride;
123*2d1272b8SAndroid Build Coastguard Worker color_t *q = s.data + row * s.stride;
124*2d1272b8SAndroid Build Coastguard Worker if (x + w <= width)
125*2d1272b8SAndroid Build Coastguard Worker for (unsigned int col = 0; col < w; col++)
126*2d1272b8SAndroid Build Coastguard Worker *q++ = *p++;
127*2d1272b8SAndroid Build Coastguard Worker else {
128*2d1272b8SAndroid Build Coastguard Worker unsigned int limit = width - x;
129*2d1272b8SAndroid Build Coastguard Worker for (unsigned int col = 0; col < limit; col++)
130*2d1272b8SAndroid Build Coastguard Worker *q++ = *p++;
131*2d1272b8SAndroid Build Coastguard Worker p--;
132*2d1272b8SAndroid Build Coastguard Worker for (unsigned int col = limit; col < w; col++)
133*2d1272b8SAndroid Build Coastguard Worker *q++ = *p;
134*2d1272b8SAndroid Build Coastguard Worker }
135*2d1272b8SAndroid Build Coastguard Worker }
136*2d1272b8SAndroid Build Coastguard Worker }
137*2d1272b8SAndroid Build Coastguard Worker
138*2d1272b8SAndroid Build Coastguard Worker const unsigned int width;
139*2d1272b8SAndroid Build Coastguard Worker const unsigned int height;
140*2d1272b8SAndroid Build Coastguard Worker
141*2d1272b8SAndroid Build Coastguard Worker private:
142*2d1272b8SAndroid Build Coastguard Worker bool own_data;
143*2d1272b8SAndroid Build Coastguard Worker color_t * const data;
144*2d1272b8SAndroid Build Coastguard Worker const unsigned int stride;
145*2d1272b8SAndroid Build Coastguard Worker };
146*2d1272b8SAndroid Build Coastguard Worker
147*2d1272b8SAndroid Build Coastguard Worker struct biimage_t
148*2d1272b8SAndroid Build Coastguard Worker {
149*2d1272b8SAndroid Build Coastguard Worker public:
150*2d1272b8SAndroid Build Coastguard Worker
biimage_tbiimage_t151*2d1272b8SAndroid Build Coastguard Worker biimage_t (unsigned int width, unsigned int height) :
152*2d1272b8SAndroid Build Coastguard Worker width (width),
153*2d1272b8SAndroid Build Coastguard Worker height (height),
154*2d1272b8SAndroid Build Coastguard Worker bg (0), fg (0), unicolor (true),
155*2d1272b8SAndroid Build Coastguard Worker data ((uint8_t *) malloc (sizeof (data[0]) * width * height)) {}
~biimage_tbiimage_t156*2d1272b8SAndroid Build Coastguard Worker ~biimage_t ()
157*2d1272b8SAndroid Build Coastguard Worker { free (data); }
158*2d1272b8SAndroid Build Coastguard Worker
setbiimage_t159*2d1272b8SAndroid Build Coastguard Worker void set (const image_t &image)
160*2d1272b8SAndroid Build Coastguard Worker {
161*2d1272b8SAndroid Build Coastguard Worker assert (image.width == width);
162*2d1272b8SAndroid Build Coastguard Worker assert (image.height == height);
163*2d1272b8SAndroid Build Coastguard Worker int freq[8] = {0};
164*2d1272b8SAndroid Build Coastguard Worker for (unsigned int y = 0; y < height; y++)
165*2d1272b8SAndroid Build Coastguard Worker for (unsigned int x = 0; x < width; x++) {
166*2d1272b8SAndroid Build Coastguard Worker color_t c = image (x, y);
167*2d1272b8SAndroid Build Coastguard Worker freq[c.to_ansi ()]++;
168*2d1272b8SAndroid Build Coastguard Worker }
169*2d1272b8SAndroid Build Coastguard Worker bg = 0;
170*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 1; i < 8; i++)
171*2d1272b8SAndroid Build Coastguard Worker if (freq[bg] < freq[i])
172*2d1272b8SAndroid Build Coastguard Worker bg = i;
173*2d1272b8SAndroid Build Coastguard Worker fg = 8;
174*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < 8; i++)
175*2d1272b8SAndroid Build Coastguard Worker if (i != bg && (fg == 8 || freq[fg] < freq[i]))
176*2d1272b8SAndroid Build Coastguard Worker fg = i;
177*2d1272b8SAndroid Build Coastguard Worker if (freq[fg] == 0) {
178*2d1272b8SAndroid Build Coastguard Worker fg = bg;
179*2d1272b8SAndroid Build Coastguard Worker unicolor = true;
180*2d1272b8SAndroid Build Coastguard Worker }
181*2d1272b8SAndroid Build Coastguard Worker else
182*2d1272b8SAndroid Build Coastguard Worker unicolor = false;
183*2d1272b8SAndroid Build Coastguard Worker
184*2d1272b8SAndroid Build Coastguard Worker /* Set the data... */
185*2d1272b8SAndroid Build Coastguard Worker
186*2d1272b8SAndroid Build Coastguard Worker if (unicolor) {
187*2d1272b8SAndroid Build Coastguard Worker memset (data, 0, sizeof (data[0]) * width * height);
188*2d1272b8SAndroid Build Coastguard Worker return;
189*2d1272b8SAndroid Build Coastguard Worker }
190*2d1272b8SAndroid Build Coastguard Worker
191*2d1272b8SAndroid Build Coastguard Worker color_t bgc = color_t::from_ansi (bg);
192*2d1272b8SAndroid Build Coastguard Worker color_t fgc = color_t::from_ansi (fg);
193*2d1272b8SAndroid Build Coastguard Worker color_diff_t diff = fgc.diff (bgc);
194*2d1272b8SAndroid Build Coastguard Worker double dd = sqrt (diff.dot (diff));
195*2d1272b8SAndroid Build Coastguard Worker for (unsigned int y = 0; y < height; y++)
196*2d1272b8SAndroid Build Coastguard Worker for (unsigned int x = 0; x < width; x++) {
197*2d1272b8SAndroid Build Coastguard Worker double d = sqrt (diff.dot (image (x, y).diff (bgc)));
198*2d1272b8SAndroid Build Coastguard Worker (*this)(x, y) = d <= 0 ? 0 : d >= dd ? 255 : lround (d / dd * 255.);
199*2d1272b8SAndroid Build Coastguard Worker }
200*2d1272b8SAndroid Build Coastguard Worker }
201*2d1272b8SAndroid Build Coastguard Worker
operator ()biimage_t202*2d1272b8SAndroid Build Coastguard Worker uint8_t &operator () (unsigned int x, unsigned int y)
203*2d1272b8SAndroid Build Coastguard Worker { return data[x + y * width]; }
204*2d1272b8SAndroid Build Coastguard Worker
operator ()biimage_t205*2d1272b8SAndroid Build Coastguard Worker uint8_t operator () (unsigned int x, unsigned int y) const
206*2d1272b8SAndroid Build Coastguard Worker { return data[x + y * width]; }
207*2d1272b8SAndroid Build Coastguard Worker
208*2d1272b8SAndroid Build Coastguard Worker const unsigned int width;
209*2d1272b8SAndroid Build Coastguard Worker const unsigned int height;
210*2d1272b8SAndroid Build Coastguard Worker unsigned int bg;
211*2d1272b8SAndroid Build Coastguard Worker unsigned int fg;
212*2d1272b8SAndroid Build Coastguard Worker bool unicolor;
213*2d1272b8SAndroid Build Coastguard Worker
214*2d1272b8SAndroid Build Coastguard Worker private:
215*2d1272b8SAndroid Build Coastguard Worker uint8_t * const data;
216*2d1272b8SAndroid Build Coastguard Worker };
217*2d1272b8SAndroid Build Coastguard Worker
218*2d1272b8SAndroid Build Coastguard Worker static const char *
block_best(const biimage_t & bi,bool * inverse)219*2d1272b8SAndroid Build Coastguard Worker block_best (const biimage_t &bi, bool *inverse)
220*2d1272b8SAndroid Build Coastguard Worker {
221*2d1272b8SAndroid Build Coastguard Worker assert (bi.width <= CELL_W);
222*2d1272b8SAndroid Build Coastguard Worker assert (bi.height <= CELL_H);
223*2d1272b8SAndroid Build Coastguard Worker
224*2d1272b8SAndroid Build Coastguard Worker unsigned int score = UINT_MAX;
225*2d1272b8SAndroid Build Coastguard Worker unsigned int row_sum[CELL_H] = {0};
226*2d1272b8SAndroid Build Coastguard Worker unsigned int col_sum[CELL_W] = {0};
227*2d1272b8SAndroid Build Coastguard Worker unsigned int row_sum_i[CELL_H] = {0};
228*2d1272b8SAndroid Build Coastguard Worker unsigned int col_sum_i[CELL_W] = {0};
229*2d1272b8SAndroid Build Coastguard Worker unsigned int quad[2][2] = {{0}};
230*2d1272b8SAndroid Build Coastguard Worker unsigned int quad_i[2][2] = {{0}};
231*2d1272b8SAndroid Build Coastguard Worker unsigned int total = 0;
232*2d1272b8SAndroid Build Coastguard Worker unsigned int total_i = 0;
233*2d1272b8SAndroid Build Coastguard Worker for (unsigned int y = 0; y < bi.height; y++)
234*2d1272b8SAndroid Build Coastguard Worker for (unsigned int x = 0; x < bi.width; x++) {
235*2d1272b8SAndroid Build Coastguard Worker unsigned int c = bi (x, y);
236*2d1272b8SAndroid Build Coastguard Worker unsigned int c_i = 255 - c;
237*2d1272b8SAndroid Build Coastguard Worker row_sum[y] += c;
238*2d1272b8SAndroid Build Coastguard Worker row_sum_i[y] += c_i;
239*2d1272b8SAndroid Build Coastguard Worker col_sum[x] += c;
240*2d1272b8SAndroid Build Coastguard Worker col_sum_i[x] += c_i;
241*2d1272b8SAndroid Build Coastguard Worker quad[2 * y / bi.height][2 * x / bi.width] += c;
242*2d1272b8SAndroid Build Coastguard Worker quad_i[2 * y / bi.height][2 * x / bi.width] += c_i;
243*2d1272b8SAndroid Build Coastguard Worker total += c;
244*2d1272b8SAndroid Build Coastguard Worker total_i += c_i;
245*2d1272b8SAndroid Build Coastguard Worker }
246*2d1272b8SAndroid Build Coastguard Worker
247*2d1272b8SAndroid Build Coastguard Worker /* Make the sums cumulative */
248*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 1; i < bi.height; i++) {
249*2d1272b8SAndroid Build Coastguard Worker row_sum[i] += row_sum[i - 1];
250*2d1272b8SAndroid Build Coastguard Worker row_sum_i[i] += row_sum_i[i - 1];
251*2d1272b8SAndroid Build Coastguard Worker }
252*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 1; i < bi.width; i++) {
253*2d1272b8SAndroid Build Coastguard Worker col_sum[i] += col_sum[i - 1];
254*2d1272b8SAndroid Build Coastguard Worker col_sum_i[i] += col_sum_i[i - 1];
255*2d1272b8SAndroid Build Coastguard Worker }
256*2d1272b8SAndroid Build Coastguard Worker
257*2d1272b8SAndroid Build Coastguard Worker const char *best_c = " ";
258*2d1272b8SAndroid Build Coastguard Worker
259*2d1272b8SAndroid Build Coastguard Worker /* Maybe empty is better! */
260*2d1272b8SAndroid Build Coastguard Worker if (total < score) {
261*2d1272b8SAndroid Build Coastguard Worker score = total;
262*2d1272b8SAndroid Build Coastguard Worker *inverse = false;
263*2d1272b8SAndroid Build Coastguard Worker best_c = " ";
264*2d1272b8SAndroid Build Coastguard Worker }
265*2d1272b8SAndroid Build Coastguard Worker /* Maybe full is better! */
266*2d1272b8SAndroid Build Coastguard Worker if (total_i < score) {
267*2d1272b8SAndroid Build Coastguard Worker score = total_i;
268*2d1272b8SAndroid Build Coastguard Worker *inverse = true;
269*2d1272b8SAndroid Build Coastguard Worker best_c = " ";
270*2d1272b8SAndroid Build Coastguard Worker }
271*2d1272b8SAndroid Build Coastguard Worker
272*2d1272b8SAndroid Build Coastguard Worker /* Find best lower line */
273*2d1272b8SAndroid Build Coastguard Worker if (1) {
274*2d1272b8SAndroid Build Coastguard Worker unsigned int best_s = UINT_MAX;
275*2d1272b8SAndroid Build Coastguard Worker bool best_inv = false;
276*2d1272b8SAndroid Build Coastguard Worker int best_i = 0;
277*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < bi.height - 1; i++)
278*2d1272b8SAndroid Build Coastguard Worker {
279*2d1272b8SAndroid Build Coastguard Worker unsigned int s;
280*2d1272b8SAndroid Build Coastguard Worker s = row_sum[i] + total_i - row_sum_i[i];
281*2d1272b8SAndroid Build Coastguard Worker if (s < best_s) {
282*2d1272b8SAndroid Build Coastguard Worker best_s = s;
283*2d1272b8SAndroid Build Coastguard Worker best_i = i;
284*2d1272b8SAndroid Build Coastguard Worker best_inv = false;
285*2d1272b8SAndroid Build Coastguard Worker }
286*2d1272b8SAndroid Build Coastguard Worker s = row_sum_i[i] + total - row_sum[i];
287*2d1272b8SAndroid Build Coastguard Worker if (s < best_s) {
288*2d1272b8SAndroid Build Coastguard Worker best_s = s;
289*2d1272b8SAndroid Build Coastguard Worker best_i = i;
290*2d1272b8SAndroid Build Coastguard Worker best_inv = true;
291*2d1272b8SAndroid Build Coastguard Worker }
292*2d1272b8SAndroid Build Coastguard Worker }
293*2d1272b8SAndroid Build Coastguard Worker if (best_s < score) {
294*2d1272b8SAndroid Build Coastguard Worker static const char *lower[7] = {"▁", "▂", "▃", "▄", "▅", "▆", "▇"};
295*2d1272b8SAndroid Build Coastguard Worker unsigned int which = lround ((double) ((best_i + 1) * 8) / bi.height);
296*2d1272b8SAndroid Build Coastguard Worker if (1 <= which && which <= 7) {
297*2d1272b8SAndroid Build Coastguard Worker score = best_s;
298*2d1272b8SAndroid Build Coastguard Worker *inverse = best_inv;
299*2d1272b8SAndroid Build Coastguard Worker best_c = lower[7 - which];
300*2d1272b8SAndroid Build Coastguard Worker }
301*2d1272b8SAndroid Build Coastguard Worker }
302*2d1272b8SAndroid Build Coastguard Worker }
303*2d1272b8SAndroid Build Coastguard Worker
304*2d1272b8SAndroid Build Coastguard Worker /* Find best left line */
305*2d1272b8SAndroid Build Coastguard Worker if (1) {
306*2d1272b8SAndroid Build Coastguard Worker unsigned int best_s = UINT_MAX;
307*2d1272b8SAndroid Build Coastguard Worker bool best_inv = false;
308*2d1272b8SAndroid Build Coastguard Worker int best_i = 0;
309*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < bi.width - 1; i++)
310*2d1272b8SAndroid Build Coastguard Worker {
311*2d1272b8SAndroid Build Coastguard Worker unsigned int s;
312*2d1272b8SAndroid Build Coastguard Worker s = col_sum[i] + total_i - col_sum_i[i];
313*2d1272b8SAndroid Build Coastguard Worker if (s < best_s) {
314*2d1272b8SAndroid Build Coastguard Worker best_s = s;
315*2d1272b8SAndroid Build Coastguard Worker best_i = i;
316*2d1272b8SAndroid Build Coastguard Worker best_inv = true;
317*2d1272b8SAndroid Build Coastguard Worker }
318*2d1272b8SAndroid Build Coastguard Worker s = col_sum_i[i] + total - col_sum[i];
319*2d1272b8SAndroid Build Coastguard Worker if (s < best_s) {
320*2d1272b8SAndroid Build Coastguard Worker best_s = s;
321*2d1272b8SAndroid Build Coastguard Worker best_i = i;
322*2d1272b8SAndroid Build Coastguard Worker best_inv = false;
323*2d1272b8SAndroid Build Coastguard Worker }
324*2d1272b8SAndroid Build Coastguard Worker }
325*2d1272b8SAndroid Build Coastguard Worker if (best_s < score) {
326*2d1272b8SAndroid Build Coastguard Worker static const char *left [7] = {"▏", "▎", "▍", "▌", "▋", "▊", "▉"};
327*2d1272b8SAndroid Build Coastguard Worker unsigned int which = lround ((double) ((best_i + 1) * 8) / bi.width);
328*2d1272b8SAndroid Build Coastguard Worker if (1 <= which && which <= 7) {
329*2d1272b8SAndroid Build Coastguard Worker score = best_s;
330*2d1272b8SAndroid Build Coastguard Worker *inverse = best_inv;
331*2d1272b8SAndroid Build Coastguard Worker best_c = left[which - 1];
332*2d1272b8SAndroid Build Coastguard Worker }
333*2d1272b8SAndroid Build Coastguard Worker }
334*2d1272b8SAndroid Build Coastguard Worker }
335*2d1272b8SAndroid Build Coastguard Worker
336*2d1272b8SAndroid Build Coastguard Worker /* Find best quadrant */
337*2d1272b8SAndroid Build Coastguard Worker if (1) {
338*2d1272b8SAndroid Build Coastguard Worker unsigned int q = 0;
339*2d1272b8SAndroid Build Coastguard Worker unsigned int qs = 0;
340*2d1272b8SAndroid Build Coastguard Worker for (unsigned int i = 0; i < 2; i++)
341*2d1272b8SAndroid Build Coastguard Worker for (unsigned int j = 0; j < 2; j++)
342*2d1272b8SAndroid Build Coastguard Worker if (quad[i][j] > quad_i[i][j]) {
343*2d1272b8SAndroid Build Coastguard Worker q += 1 << (2 * i + j);
344*2d1272b8SAndroid Build Coastguard Worker qs += quad_i[i][j];
345*2d1272b8SAndroid Build Coastguard Worker } else
346*2d1272b8SAndroid Build Coastguard Worker qs += quad[i][j];
347*2d1272b8SAndroid Build Coastguard Worker if (qs < score) {
348*2d1272b8SAndroid Build Coastguard Worker const char *c = nullptr;
349*2d1272b8SAndroid Build Coastguard Worker bool inv = false;
350*2d1272b8SAndroid Build Coastguard Worker switch (q) {
351*2d1272b8SAndroid Build Coastguard Worker case 1: c = "▟"; inv = true; break;
352*2d1272b8SAndroid Build Coastguard Worker case 2: c = "▙"; inv = true; break;
353*2d1272b8SAndroid Build Coastguard Worker case 4: c = "▖"; inv = false; break;
354*2d1272b8SAndroid Build Coastguard Worker case 6: c = "▞"; inv = false; break;
355*2d1272b8SAndroid Build Coastguard Worker case 7: c = "▛"; inv = false; break;
356*2d1272b8SAndroid Build Coastguard Worker case 8: c = "▗"; inv = false; break;
357*2d1272b8SAndroid Build Coastguard Worker case 9: c = "▚"; inv = false; break;
358*2d1272b8SAndroid Build Coastguard Worker case 11: c = "▜"; inv = false; break;
359*2d1272b8SAndroid Build Coastguard Worker case 13: c = "▙"; inv = false; break;
360*2d1272b8SAndroid Build Coastguard Worker case 14: c = "▟"; inv = false; break;
361*2d1272b8SAndroid Build Coastguard Worker }
362*2d1272b8SAndroid Build Coastguard Worker if (c) {
363*2d1272b8SAndroid Build Coastguard Worker score = qs;
364*2d1272b8SAndroid Build Coastguard Worker *inverse = inv;
365*2d1272b8SAndroid Build Coastguard Worker best_c = c;
366*2d1272b8SAndroid Build Coastguard Worker }
367*2d1272b8SAndroid Build Coastguard Worker }
368*2d1272b8SAndroid Build Coastguard Worker }
369*2d1272b8SAndroid Build Coastguard Worker
370*2d1272b8SAndroid Build Coastguard Worker return best_c;
371*2d1272b8SAndroid Build Coastguard Worker }
372*2d1272b8SAndroid Build Coastguard Worker
373*2d1272b8SAndroid Build Coastguard Worker static inline void
ansi_print_image_rgb24(const uint32_t * data,unsigned int width,unsigned int height,unsigned int stride,cairo_write_func_t write_func,void * closure)374*2d1272b8SAndroid Build Coastguard Worker ansi_print_image_rgb24 (const uint32_t *data,
375*2d1272b8SAndroid Build Coastguard Worker unsigned int width,
376*2d1272b8SAndroid Build Coastguard Worker unsigned int height,
377*2d1272b8SAndroid Build Coastguard Worker unsigned int stride,
378*2d1272b8SAndroid Build Coastguard Worker cairo_write_func_t write_func,
379*2d1272b8SAndroid Build Coastguard Worker void *closure)
380*2d1272b8SAndroid Build Coastguard Worker {
381*2d1272b8SAndroid Build Coastguard Worker image_t image (width, height, data, stride);
382*2d1272b8SAndroid Build Coastguard Worker
383*2d1272b8SAndroid Build Coastguard Worker unsigned int rows = (height + CELL_H - 1) / CELL_H;
384*2d1272b8SAndroid Build Coastguard Worker unsigned int cols = (width + CELL_W - 1) / CELL_W;
385*2d1272b8SAndroid Build Coastguard Worker image_t cell (CELL_W, CELL_H);
386*2d1272b8SAndroid Build Coastguard Worker biimage_t bi (CELL_W, CELL_H);
387*2d1272b8SAndroid Build Coastguard Worker unsigned int last_bg = -1, last_fg = -1;
388*2d1272b8SAndroid Build Coastguard Worker for (unsigned int row = 0; row < rows; row++)
389*2d1272b8SAndroid Build Coastguard Worker {
390*2d1272b8SAndroid Build Coastguard Worker for (unsigned int col = 0; col < cols; col++)
391*2d1272b8SAndroid Build Coastguard Worker {
392*2d1272b8SAndroid Build Coastguard Worker image.copy_sub_image (cell, col * CELL_W, row * CELL_H, CELL_W, CELL_H);
393*2d1272b8SAndroid Build Coastguard Worker bi.set (cell);
394*2d1272b8SAndroid Build Coastguard Worker if (bi.unicolor)
395*2d1272b8SAndroid Build Coastguard Worker {
396*2d1272b8SAndroid Build Coastguard Worker if (last_bg != bi.bg)
397*2d1272b8SAndroid Build Coastguard Worker {
398*2d1272b8SAndroid Build Coastguard Worker char buf[] = "\033[40m";
399*2d1272b8SAndroid Build Coastguard Worker buf[3] += bi.bg;
400*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) buf, 5);
401*2d1272b8SAndroid Build Coastguard Worker last_bg = bi.bg;
402*2d1272b8SAndroid Build Coastguard Worker }
403*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) " ", 1);
404*2d1272b8SAndroid Build Coastguard Worker }
405*2d1272b8SAndroid Build Coastguard Worker else
406*2d1272b8SAndroid Build Coastguard Worker {
407*2d1272b8SAndroid Build Coastguard Worker /* Figure out the closest character to the biimage */
408*2d1272b8SAndroid Build Coastguard Worker bool inverse = false;
409*2d1272b8SAndroid Build Coastguard Worker const char *c = block_best (bi, &inverse);
410*2d1272b8SAndroid Build Coastguard Worker if (inverse)
411*2d1272b8SAndroid Build Coastguard Worker {
412*2d1272b8SAndroid Build Coastguard Worker if (last_bg != bi.fg || last_fg != bi.bg)
413*2d1272b8SAndroid Build Coastguard Worker {
414*2d1272b8SAndroid Build Coastguard Worker char buf[] = "\033[30;40m";
415*2d1272b8SAndroid Build Coastguard Worker buf[3] += bi.bg;
416*2d1272b8SAndroid Build Coastguard Worker buf[6] += bi.fg;
417*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) buf, 8);
418*2d1272b8SAndroid Build Coastguard Worker last_bg = bi.fg;
419*2d1272b8SAndroid Build Coastguard Worker last_fg = bi.bg;
420*2d1272b8SAndroid Build Coastguard Worker }
421*2d1272b8SAndroid Build Coastguard Worker }
422*2d1272b8SAndroid Build Coastguard Worker else
423*2d1272b8SAndroid Build Coastguard Worker {
424*2d1272b8SAndroid Build Coastguard Worker if (last_bg != bi.bg || last_fg != bi.fg)
425*2d1272b8SAndroid Build Coastguard Worker {
426*2d1272b8SAndroid Build Coastguard Worker char buf[] = "\033[40;30m";
427*2d1272b8SAndroid Build Coastguard Worker buf[3] += bi.bg;
428*2d1272b8SAndroid Build Coastguard Worker buf[6] += bi.fg;
429*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) buf, 8);
430*2d1272b8SAndroid Build Coastguard Worker last_bg = bi.bg;
431*2d1272b8SAndroid Build Coastguard Worker last_fg = bi.fg;
432*2d1272b8SAndroid Build Coastguard Worker }
433*2d1272b8SAndroid Build Coastguard Worker }
434*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) c, strlen (c));
435*2d1272b8SAndroid Build Coastguard Worker }
436*2d1272b8SAndroid Build Coastguard Worker }
437*2d1272b8SAndroid Build Coastguard Worker write_func (closure, (unsigned char *) "\033[0m\n", 5); /* Reset */
438*2d1272b8SAndroid Build Coastguard Worker last_bg = last_fg = -1;
439*2d1272b8SAndroid Build Coastguard Worker }
440*2d1272b8SAndroid Build Coastguard Worker }
441*2d1272b8SAndroid Build Coastguard Worker
442*2d1272b8SAndroid Build Coastguard Worker #endif
443