"Fossies" - the Fresh Open Source Software Archive

Member "SDL2_ttf-2.20.2/external/harfbuzz/util/ansi-print.hh" (25 May 2022, 10576 Bytes) of package /linux/misc/SDL2_ttf-2.20.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ansi-print.hh" see the Fossies "Dox" file reference documentation.

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