xref: /petsc/src/sys/classes/draw/impls/image/drawimage.h (revision da81f9329be15cc55f054c8a00978087195c9247)
16524c165SJacob Faibussowitsch #ifndef _PETSCIMAGE_H
22b8d69caSLisandro Dalcin #define _PETSCIMAGE_H
32b8d69caSLisandro Dalcin 
42b8d69caSLisandro Dalcin #include <petscdraw.h>
52b8d69caSLisandro Dalcin 
62b8d69caSLisandro Dalcin typedef struct _n_PetscImage *PetscImage;
72b8d69caSLisandro Dalcin typedef struct _n_PetscImage {
82b8d69caSLisandro Dalcin   unsigned char *buffer;          /* raster buffer  */
92b8d69caSLisandro Dalcin   int            w, h;            /* width, height  */
102b8d69caSLisandro Dalcin   int            clip[4];         /* clip ranges    */
112b8d69caSLisandro Dalcin   unsigned char  palette[256][3]; /* colormap       */
122b8d69caSLisandro Dalcin } _n_PetscImage;
132b8d69caSLisandro Dalcin 
14d71ae5a4SJacob Faibussowitsch static inline void PetscImageSetClip(PetscImage img, int x, int y, int w, int h)
15d71ae5a4SJacob Faibussowitsch {
162b8d69caSLisandro Dalcin   img->clip[0] = PetscClipInterval(x, 0, img->w - 1); /* xmin   */
172b8d69caSLisandro Dalcin   img->clip[1] = PetscClipInterval(y, 0, img->h - 1); /* ymin   */
182b8d69caSLisandro Dalcin   img->clip[2] = PetscClipInterval(x + w, 0, img->w); /* xmax+1 */
192b8d69caSLisandro Dalcin   img->clip[3] = PetscClipInterval(y + h, 0, img->h); /* ymax+1 */
202b8d69caSLisandro Dalcin }
212b8d69caSLisandro Dalcin 
22d71ae5a4SJacob Faibussowitsch static inline void PetscImageClear(PetscImage img)
23d71ae5a4SJacob Faibussowitsch {
242b8d69caSLisandro Dalcin   int x, xs = img->clip[0], xe = img->clip[2];
252b8d69caSLisandro Dalcin   int y, ys = img->clip[1], ye = img->clip[3];
262b8d69caSLisandro Dalcin   for (y = ys; y < ye; y++)
279371c9d4SSatish Balay     for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = 0;
282b8d69caSLisandro Dalcin }
292b8d69caSLisandro Dalcin 
30d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawPixel(PetscImage img, int x, int y, int c)
31d71ae5a4SJacob Faibussowitsch {
322b8d69caSLisandro Dalcin   if (x < img->clip[0] || x >= img->clip[2]) return;
332b8d69caSLisandro Dalcin   if (y < img->clip[1] || y >= img->clip[3]) return;
342b8d69caSLisandro Dalcin   img->buffer[y * img->w + x] = (unsigned char)c;
352b8d69caSLisandro Dalcin }
362b8d69caSLisandro Dalcin 
37d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawLine(PetscImage img, int x_1, int y_1, int x_2, int y_2, int c)
38d71ae5a4SJacob Faibussowitsch {
392b8d69caSLisandro Dalcin   if (y_1 == y_2) {
402b8d69caSLisandro Dalcin     /* Horizontal line */
419371c9d4SSatish Balay     if (x_2 - x_1 < 0) {
429371c9d4SSatish Balay       int tmp = x_1;
439371c9d4SSatish Balay       x_1     = x_2;
449371c9d4SSatish Balay       x_2     = tmp;
459371c9d4SSatish Balay     }
462b8d69caSLisandro Dalcin     while (x_1 <= x_2) PetscImageDrawPixel(img, x_1++, y_1, c);
472b8d69caSLisandro Dalcin   } else if (x_1 == x_2) {
482b8d69caSLisandro Dalcin     /* Vertical line */
499371c9d4SSatish Balay     if (y_2 - y_1 < 0) {
509371c9d4SSatish Balay       int tmp = y_1;
519371c9d4SSatish Balay       y_1     = y_2;
529371c9d4SSatish Balay       y_2     = tmp;
539371c9d4SSatish Balay     }
542b8d69caSLisandro Dalcin     while (y_1 <= y_2) PetscImageDrawPixel(img, x_1, y_1++, c);
552b8d69caSLisandro Dalcin   } else {
562b8d69caSLisandro Dalcin     /* Bresenham's line drawing algorithm */
572b8d69caSLisandro Dalcin     int dx = PetscAbs(x_2 - x_1), sx = (x_2 - x_1) >= 0 ? +1 : -1;
582b8d69caSLisandro Dalcin     int dy = PetscAbs(y_2 - y_1), sy = (y_2 - y_1) >= 0 ? +1 : -1;
592b8d69caSLisandro Dalcin     int error = (dx > dy ? dx : -dy) / 2, err;
602b8d69caSLisandro Dalcin     while (1) {
612b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, x_1, y_1, c);
622b8d69caSLisandro Dalcin       if (x_1 == x_2 && y_1 == y_2) break;
632b8d69caSLisandro Dalcin       err = error;
649371c9d4SSatish Balay       if (err > -dx) {
659371c9d4SSatish Balay         error -= dy;
669371c9d4SSatish Balay         x_1 += sx;
679371c9d4SSatish Balay       }
689371c9d4SSatish Balay       if (err < +dy) {
699371c9d4SSatish Balay         error += dx;
709371c9d4SSatish Balay         y_1 += sy;
719371c9d4SSatish Balay       }
722b8d69caSLisandro Dalcin     }
732b8d69caSLisandro Dalcin   }
742b8d69caSLisandro Dalcin }
752b8d69caSLisandro Dalcin 
76d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawRectangle(PetscImage img, int x, int y, int w, int h, int c)
77d71ae5a4SJacob Faibussowitsch {
782b8d69caSLisandro Dalcin   int xs = PetscMax(x, img->clip[0]), xe = PetscMin(x + w, img->clip[2]);
792b8d69caSLisandro Dalcin   int ys = PetscMax(y, img->clip[1]), ye = PetscMin(y + h, img->clip[3]);
802b8d69caSLisandro Dalcin   if (xs >= xe || ys >= ye) return;
812b8d69caSLisandro Dalcin   for (y = ys; y < ye; y++)
829371c9d4SSatish Balay     for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = (unsigned char)c;
832b8d69caSLisandro Dalcin }
842b8d69caSLisandro Dalcin 
85d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawEllipse(PetscImage img, int xc, int yc, int w, int h, int c)
86d71ae5a4SJacob Faibussowitsch {
872b8d69caSLisandro Dalcin   /* Bresenham's circle/ellipse drawing algorithm */
882b8d69caSLisandro Dalcin   int x, y, s, a2 = w * w, b2 = h * h;
892b8d69caSLisandro Dalcin   for (x = 0, y = h, s = 2 * b2 + a2 * (1 - 2 * h); b2 * x <= a2 * y; x++) {
902b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
912b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
929371c9d4SSatish Balay     if (s >= 0) {
939371c9d4SSatish Balay       s += 4 * a2 * (1 - y);
949371c9d4SSatish Balay       y--;
959371c9d4SSatish Balay     }
962b8d69caSLisandro Dalcin     s += b2 * ((4 * x) + 6);
972b8d69caSLisandro Dalcin   }
982b8d69caSLisandro Dalcin   for (x = w, y = 0, s = 2 * a2 + b2 * (1 - 2 * w); a2 * y <= b2 * x; y++) {
992b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
1002b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
1019371c9d4SSatish Balay     if (s >= 0) {
1029371c9d4SSatish Balay       s += 4 * b2 * (1 - x);
1039371c9d4SSatish Balay       x--;
1049371c9d4SSatish Balay     }
1052b8d69caSLisandro Dalcin     s += a2 * ((4 * y) + 6);
1062b8d69caSLisandro Dalcin   }
1072b8d69caSLisandro Dalcin }
1082b8d69caSLisandro Dalcin 
109d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawTriangle(PetscImage img, int x_1, int y_1, int t_1, int x_2, int y_2, int t_2, int x_3, int y_3, int t_3)
110d71ae5a4SJacob Faibussowitsch {
1112b8d69caSLisandro Dalcin   const int SHIFT_VAL = 6;
1122b8d69caSLisandro Dalcin   const int xmin = img->clip[0], xmax = img->clip[2] - 1;
1132b8d69caSLisandro Dalcin   const int ymin = img->clip[1], ymax = img->clip[3] - 1;
1142b8d69caSLisandro Dalcin   float     rfrac, lfrac, one = 1;
1152b8d69caSLisandro Dalcin   float     R_y2_y1, R_y3_y1, R_y3_y2;
1162b8d69caSLisandro Dalcin   int       lc, rc = 0, lx, rx = 0, xx, y, c;
1172b8d69caSLisandro Dalcin   int       rc_lc, rx_lx, t2_t1, x2_x1, t3_t1, x3_x1, t3_t2, x3_x2;
1182b8d69caSLisandro Dalcin 
1192b8d69caSLisandro Dalcin   /* Is triangle ever visible in image? */
1202b8d69caSLisandro Dalcin   if (x_1 < xmin && x_2 < xmin && x_3 < xmin) return;
1212b8d69caSLisandro Dalcin   if (y_1 < ymin && y_2 < ymin && y_3 < ymin) return;
1222b8d69caSLisandro Dalcin   if (x_1 > xmax && x_2 > xmax && x_3 > xmax) return;
1232b8d69caSLisandro Dalcin   if (y_1 > ymax && y_2 > ymax && y_3 > ymax) return;
1242b8d69caSLisandro Dalcin 
1252b8d69caSLisandro Dalcin   t_1 = t_1 << SHIFT_VAL;
1262b8d69caSLisandro Dalcin   t_2 = t_2 << SHIFT_VAL;
1272b8d69caSLisandro Dalcin   t_3 = t_3 << SHIFT_VAL;
1282b8d69caSLisandro Dalcin 
1292b8d69caSLisandro Dalcin   /* Sort the vertices */
1309371c9d4SSatish Balay #define SWAP(a, b) \
1319371c9d4SSatish Balay   do { \
1329371c9d4SSatish Balay     int _tmp; \
1339371c9d4SSatish Balay     _tmp = a; \
1349371c9d4SSatish Balay     a    = b; \
1359371c9d4SSatish Balay     b    = _tmp; \
1369371c9d4SSatish Balay   } while (0)
1379371c9d4SSatish Balay   if (y_1 > y_2) {
1389371c9d4SSatish Balay     SWAP(x_1, x_2);
1399371c9d4SSatish Balay     SWAP(y_1, y_2);
1409371c9d4SSatish Balay     SWAP(t_1, t_2);
1419371c9d4SSatish Balay   }
1429371c9d4SSatish Balay   if (y_1 > y_3) {
1439371c9d4SSatish Balay     SWAP(x_1, x_3);
1449371c9d4SSatish Balay     SWAP(y_1, y_3);
1459371c9d4SSatish Balay     SWAP(t_1, t_3);
1469371c9d4SSatish Balay   }
1479371c9d4SSatish Balay   if (y_2 > y_3) {
1489371c9d4SSatish Balay     SWAP(x_2, x_3);
1499371c9d4SSatish Balay     SWAP(y_2, y_3);
1509371c9d4SSatish Balay     SWAP(t_2, t_3);
1519371c9d4SSatish Balay   }
1522b8d69caSLisandro Dalcin #undef SWAP
1532b8d69caSLisandro Dalcin 
154*da81f932SPierre Jolivet   /* This code is decidedly non-optimal;
1552b8d69caSLisandro Dalcin    it is intended to be a start at an implementation */
1562b8d69caSLisandro Dalcin 
1572b8d69caSLisandro Dalcin   t2_t1   = t_2 - t_1;
1582b8d69caSLisandro Dalcin   x2_x1   = x_2 - x_1;
1592b8d69caSLisandro Dalcin   R_y2_y1 = (y_2 != y_1) ? one / (y_2 - y_1) : 0;
1602b8d69caSLisandro Dalcin   R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
1612b8d69caSLisandro Dalcin   x3_x1   = x_3 - x_1;
1622b8d69caSLisandro Dalcin   t3_t1   = t_3 - t_1;
1632b8d69caSLisandro Dalcin 
1642b8d69caSLisandro Dalcin   for (y = y_1; y <= y_2; y++) {
1652b8d69caSLisandro Dalcin     /* Draw a line with the correct color from t1-t2 to t1-t3 */
1662b8d69caSLisandro Dalcin     /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
1672b8d69caSLisandro Dalcin     lfrac = (y - y_1) * R_y2_y1;
1682b8d69caSLisandro Dalcin     lc    = (int)(lfrac * (t2_t1) + t_1);
1692b8d69caSLisandro Dalcin     lx    = (int)(lfrac * (x2_x1) + x_1);
1702b8d69caSLisandro Dalcin     /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
1712b8d69caSLisandro Dalcin     rfrac = (y - y_1) * R_y3_y1;
1722b8d69caSLisandro Dalcin     rc    = (int)(rfrac * (t3_t1) + t_1);
1732b8d69caSLisandro Dalcin     rx    = (int)(rfrac * (x3_x1) + x_1);
1742b8d69caSLisandro Dalcin     /* Draw the line */
1752b8d69caSLisandro Dalcin     rc_lc = rc - lc;
1762b8d69caSLisandro Dalcin     rx_lx = rx - lx;
1772b8d69caSLisandro Dalcin     if (rx > lx) {
1782b8d69caSLisandro Dalcin       for (xx = lx; xx <= rx; xx++) {
1792b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
1802b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
1812b8d69caSLisandro Dalcin       }
1822b8d69caSLisandro Dalcin     } else if (rx < lx) {
1832b8d69caSLisandro Dalcin       for (xx = lx; xx >= rx; xx--) {
1842b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
1852b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
1862b8d69caSLisandro Dalcin       }
1872b8d69caSLisandro Dalcin     } else {
1882b8d69caSLisandro Dalcin       c = lc >> SHIFT_VAL;
1892b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, lx, y, c);
1902b8d69caSLisandro Dalcin     }
1912b8d69caSLisandro Dalcin   }
1922b8d69caSLisandro Dalcin 
1932b8d69caSLisandro Dalcin   /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2.
1942b8d69caSLisandro Dalcin      We take advantage of the previous iteration. */
1952b8d69caSLisandro Dalcin   if (y_2 >= y_3) return;
1962b8d69caSLisandro Dalcin   if (y_1 < y_2) {
1972b8d69caSLisandro Dalcin     x_1   = rx;
1982b8d69caSLisandro Dalcin     y_1   = y_2;
1992b8d69caSLisandro Dalcin     t_1   = rc;
2002b8d69caSLisandro Dalcin     x3_x1 = x_3 - x_1;
2012b8d69caSLisandro Dalcin     t3_t1 = t_3 - t_1;
2022b8d69caSLisandro Dalcin   }
2032b8d69caSLisandro Dalcin   R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
2042b8d69caSLisandro Dalcin   R_y3_y2 = (y_3 != y_2) ? one / (y_3 - y_2) : 0;
2052b8d69caSLisandro Dalcin   x3_x2   = x_3 - x_2;
2062b8d69caSLisandro Dalcin   t3_t2   = t_3 - t_2;
2072b8d69caSLisandro Dalcin 
2082b8d69caSLisandro Dalcin   for (y = y_2; y <= y_3; y++) {
2092b8d69caSLisandro Dalcin     /* Draw a line with the correct color from t2-t3 to t1-t3 */
2102b8d69caSLisandro Dalcin     /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
2112b8d69caSLisandro Dalcin     lfrac = (y - y_2) * R_y3_y2;
2122b8d69caSLisandro Dalcin     lc    = (int)(lfrac * (t3_t2) + t_2);
2132b8d69caSLisandro Dalcin     lx    = (int)(lfrac * (x3_x2) + x_2);
2142b8d69caSLisandro Dalcin     /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
2152b8d69caSLisandro Dalcin     rfrac = (y - y_1) * R_y3_y1;
2162b8d69caSLisandro Dalcin     rc    = (int)(rfrac * (t3_t1) + t_1);
2172b8d69caSLisandro Dalcin     rx    = (int)(rfrac * (x3_x1) + x_1);
2182b8d69caSLisandro Dalcin     /* Draw the line */
2192b8d69caSLisandro Dalcin     rc_lc = rc - lc;
2202b8d69caSLisandro Dalcin     rx_lx = rx - lx;
2212b8d69caSLisandro Dalcin     if (rx > lx) {
2222b8d69caSLisandro Dalcin       for (xx = lx; xx <= rx; xx++) {
2232b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
2242b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
2252b8d69caSLisandro Dalcin       }
2262b8d69caSLisandro Dalcin     } else if (rx < lx) {
2272b8d69caSLisandro Dalcin       for (xx = lx; xx >= rx; xx--) {
2282b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
2292b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
2302b8d69caSLisandro Dalcin       }
2312b8d69caSLisandro Dalcin     } else {
2322b8d69caSLisandro Dalcin       c = lc >> SHIFT_VAL;
2332b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, lx, y, c);
2342b8d69caSLisandro Dalcin     }
2352b8d69caSLisandro Dalcin   }
2362b8d69caSLisandro Dalcin }
2372b8d69caSLisandro Dalcin 
2382b8d69caSLisandro Dalcin #define PetscImageFontWidth  6
2392b8d69caSLisandro Dalcin #define PetscImageFontHeight 10
2402b8d69caSLisandro Dalcin static const unsigned char PetscImageFontBitmap[128 - 32][10] = {
2412b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*   */
2422b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ! */
2432b8d69caSLisandro Dalcin   {0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
2442b8d69caSLisandro Dalcin   {0x00, 0x14, 0x14, 0x3E, 0x14, 0x3E, 0x14, 0x14, 0x00, 0x00}, /* # */
2452b8d69caSLisandro Dalcin   {0x00, 0x08, 0x1C, 0x28, 0x1C, 0x0A, 0x1C, 0x08, 0x00, 0x00}, /* $ */
2462b8d69caSLisandro Dalcin   {0x00, 0x12, 0x2A, 0x14, 0x08, 0x14, 0x2A, 0x24, 0x00, 0x00}, /* % */
2472b8d69caSLisandro Dalcin   {0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00}, /* & */
2482b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
2492b8d69caSLisandro Dalcin   {0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, 0x00}, /* ( */
2502b8d69caSLisandro Dalcin   {0x00, 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00, 0x00}, /*) */
2512b8d69caSLisandro Dalcin   {0x00, 0x00, 0x22, 0x14, 0x3E, 0x14, 0x22, 0x00, 0x00, 0x00}, /* * */
2522b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00}, /* + */
2532b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* , */
2542b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00}, /* - */
2552b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* . */
2562b8d69caSLisandro Dalcin   {0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00}, /* / */
2572b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x00}, /* 0 */
2582b8d69caSLisandro Dalcin   {0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /* 1 */
2592b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x02, 0x0C, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* 2 */
2602b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x0C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 3 */
2612b8d69caSLisandro Dalcin   {0x00, 0x04, 0x0C, 0x14, 0x24, 0x3E, 0x04, 0x04, 0x00, 0x00}, /* 4 */
2622b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x2C, 0x32, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 5 */
2632b8d69caSLisandro Dalcin   {0x00, 0x0C, 0x10, 0x20, 0x2C, 0x32, 0x22, 0x1C, 0x00, 0x00}, /* 6 */
2642b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00}, /* 7 */
2652b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* 8 */
2662b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x26, 0x1A, 0x02, 0x04, 0x18, 0x00, 0x00}, /* 9 */
2672b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* : */
2682b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* } */
2692b8d69caSLisandro Dalcin   {0x00, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /* < */
2702b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, /* = */
2712b8d69caSLisandro Dalcin   {0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00}, /* > */
2722b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ? */
2732b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x26, 0x2A, 0x2C, 0x20, 0x1C, 0x00, 0x00}, /* @ */
2742b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00}, /* A */
2752b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* B */
2762b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* C */
2772b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* D */
2782b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* E */
2792b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* F */
2802b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x20, 0x26, 0x22, 0x1C, 0x00, 0x00}, /* G */
2812b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00}, /* H */
2822b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* I */
2832b8d69caSLisandro Dalcin   {0x00, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x00}, /* J */
2842b8d69caSLisandro Dalcin   {0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00}, /* K */
2852b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* L */
2862b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00}, /* M */
2872b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x00, 0x00}, /* N */
2882b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* O */
2892b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* P */
2902b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x2A, 0x1C, 0x02, 0x00}, /* Q */
2912b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00}, /* R */
2922b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x1C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* S */
2932b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* T */
2942b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* U */
2952b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00}, /* V */
2962b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00}, /* W */
2972b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00}, /* X */
2982b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* Y */
2992b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* Z */
3002b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x00, 0x00}, /* [ */
3012b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00}, /* \ */
3022b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x00, 0x00}, /* ] */
3032b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ^ */
3042b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00}, /* _ */
3052b8d69caSLisandro Dalcin   {0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
3062b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00}, /* a */
3072b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x00, 0x00}, /* b */
3082b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* c */
3092b8d69caSLisandro Dalcin   {0x00, 0x02, 0x02, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* d */
3102b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00}, /* e */
3112b8d69caSLisandro Dalcin   {0x00, 0x0C, 0x12, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x00, 0x00}, /* f */
3122b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x1E, 0x02, 0x22, 0x1C}, /* g */
3132b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* h */
3142b8d69caSLisandro Dalcin   {0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* i */
3152b8d69caSLisandro Dalcin   {0x00, 0x02, 0x00, 0x06, 0x02, 0x02, 0x02, 0x12, 0x12, 0x0C}, /* j */
3162b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x22, 0x24, 0x38, 0x24, 0x22, 0x00, 0x00}, /* k */
3172b8d69caSLisandro Dalcin   {0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* l */
3182b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x34, 0x2A, 0x2A, 0x2A, 0x22, 0x00, 0x00}, /* m */
3192b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* n */
3202b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* o */
3212b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x20, 0x20}, /* p */
3222b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x02, 0x02}, /* q */
3232b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00}, /* r */
3242b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00}, /* s */
3252b8d69caSLisandro Dalcin   {0x00, 0x10, 0x10, 0x3C, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00}, /* t */
3262b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* u */
3272b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00}, /* v */
3282b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x2A, 0x2A, 0x14, 0x00, 0x00}, /* w */
3292b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00}, /* x */
3302b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x26, 0x1A, 0x02, 0x22, 0x1C}, /* y */
3312b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00}, /* z */
3322b8d69caSLisandro Dalcin   {0x00, 0x06, 0x08, 0x04, 0x18, 0x04, 0x08, 0x06, 0x00, 0x00}, /* { */
3332b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* | */
3342b8d69caSLisandro Dalcin   {0x00, 0x18, 0x04, 0x08, 0x06, 0x08, 0x04, 0x18, 0x00, 0x00}, /* } */
3352b8d69caSLisandro Dalcin   {0x00, 0x12, 0x2A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ~ */
3362b8d69caSLisandro Dalcin   {0x00, 0x2A, 0x00, 0x22, 0x00, 0x22, 0x00, 0x2A, 0x00, 0x00}, /* ASCII 127 */
3372b8d69caSLisandro Dalcin };
3382b8d69caSLisandro Dalcin 
339d71ae5a4SJacob Faibussowitsch static inline void PetscImageDrawText(PetscImage img, int x, int y, int c, const char text[])
340d71ae5a4SJacob Faibussowitsch {
3412b8d69caSLisandro Dalcin   int i, j, k, tw = PetscImageFontWidth, th = PetscImageFontHeight;
3422b8d69caSLisandro Dalcin   for (i = 0; i < th; i++) {
3432b8d69caSLisandro Dalcin     for (k = 0; text[k]; k++) {
3442b8d69caSLisandro Dalcin       int chr = PetscClipInterval(text[k], 32, 127);
3452b8d69caSLisandro Dalcin       for (j = 0; j < tw; j++) {
3469371c9d4SSatish Balay         if (PetscImageFontBitmap[chr - 32][i] & (1 << (tw - 1 - j))) PetscImageDrawPixel(img, x + j + k * tw, y + i - th, c);
3472b8d69caSLisandro Dalcin       }
3482b8d69caSLisandro Dalcin     }
3492b8d69caSLisandro Dalcin   }
3502b8d69caSLisandro Dalcin }
3512b8d69caSLisandro Dalcin 
3522b8d69caSLisandro Dalcin #endif
353