xref: /petsc/src/sys/classes/draw/impls/image/drawimage.h (revision 6524c165f7ddaf30fd7457737f668f984c8ababf)
1*6524c165SJacob 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 
149371c9d4SSatish Balay static inline void PetscImageSetClip(PetscImage img, int x, int y, int w, int h) {
152b8d69caSLisandro Dalcin   img->clip[0] = PetscClipInterval(x, 0, img->w - 1); /* xmin   */
162b8d69caSLisandro Dalcin   img->clip[1] = PetscClipInterval(y, 0, img->h - 1); /* ymin   */
172b8d69caSLisandro Dalcin   img->clip[2] = PetscClipInterval(x + w, 0, img->w); /* xmax+1 */
182b8d69caSLisandro Dalcin   img->clip[3] = PetscClipInterval(y + h, 0, img->h); /* ymax+1 */
192b8d69caSLisandro Dalcin }
202b8d69caSLisandro Dalcin 
219371c9d4SSatish Balay static inline void PetscImageClear(PetscImage img) {
222b8d69caSLisandro Dalcin   int x, xs = img->clip[0], xe = img->clip[2];
232b8d69caSLisandro Dalcin   int y, ys = img->clip[1], ye = img->clip[3];
242b8d69caSLisandro Dalcin   for (y = ys; y < ye; y++)
259371c9d4SSatish Balay     for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = 0;
262b8d69caSLisandro Dalcin }
272b8d69caSLisandro Dalcin 
289371c9d4SSatish Balay static inline void PetscImageDrawPixel(PetscImage img, int x, int y, int c) {
292b8d69caSLisandro Dalcin   if (x < img->clip[0] || x >= img->clip[2]) return;
302b8d69caSLisandro Dalcin   if (y < img->clip[1] || y >= img->clip[3]) return;
312b8d69caSLisandro Dalcin   img->buffer[y * img->w + x] = (unsigned char)c;
322b8d69caSLisandro Dalcin }
332b8d69caSLisandro Dalcin 
349371c9d4SSatish Balay static inline void PetscImageDrawLine(PetscImage img, int x_1, int y_1, int x_2, int y_2, int c) {
352b8d69caSLisandro Dalcin   if (y_1 == y_2) {
362b8d69caSLisandro Dalcin     /* Horizontal line */
379371c9d4SSatish Balay     if (x_2 - x_1 < 0) {
389371c9d4SSatish Balay       int tmp = x_1;
399371c9d4SSatish Balay       x_1     = x_2;
409371c9d4SSatish Balay       x_2     = tmp;
419371c9d4SSatish Balay     }
422b8d69caSLisandro Dalcin     while (x_1 <= x_2) PetscImageDrawPixel(img, x_1++, y_1, c);
432b8d69caSLisandro Dalcin   } else if (x_1 == x_2) {
442b8d69caSLisandro Dalcin     /* Vertical line */
459371c9d4SSatish Balay     if (y_2 - y_1 < 0) {
469371c9d4SSatish Balay       int tmp = y_1;
479371c9d4SSatish Balay       y_1     = y_2;
489371c9d4SSatish Balay       y_2     = tmp;
499371c9d4SSatish Balay     }
502b8d69caSLisandro Dalcin     while (y_1 <= y_2) PetscImageDrawPixel(img, x_1, y_1++, c);
512b8d69caSLisandro Dalcin   } else {
522b8d69caSLisandro Dalcin     /* Bresenham's line drawing algorithm */
532b8d69caSLisandro Dalcin     int dx = PetscAbs(x_2 - x_1), sx = (x_2 - x_1) >= 0 ? +1 : -1;
542b8d69caSLisandro Dalcin     int dy = PetscAbs(y_2 - y_1), sy = (y_2 - y_1) >= 0 ? +1 : -1;
552b8d69caSLisandro Dalcin     int error = (dx > dy ? dx : -dy) / 2, err;
562b8d69caSLisandro Dalcin     while (1) {
572b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, x_1, y_1, c);
582b8d69caSLisandro Dalcin       if (x_1 == x_2 && y_1 == y_2) break;
592b8d69caSLisandro Dalcin       err = error;
609371c9d4SSatish Balay       if (err > -dx) {
619371c9d4SSatish Balay         error -= dy;
629371c9d4SSatish Balay         x_1 += sx;
639371c9d4SSatish Balay       }
649371c9d4SSatish Balay       if (err < +dy) {
659371c9d4SSatish Balay         error += dx;
669371c9d4SSatish Balay         y_1 += sy;
679371c9d4SSatish Balay       }
682b8d69caSLisandro Dalcin     }
692b8d69caSLisandro Dalcin   }
702b8d69caSLisandro Dalcin }
712b8d69caSLisandro Dalcin 
729371c9d4SSatish Balay static inline void PetscImageDrawRectangle(PetscImage img, int x, int y, int w, int h, int c) {
732b8d69caSLisandro Dalcin   int xs = PetscMax(x, img->clip[0]), xe = PetscMin(x + w, img->clip[2]);
742b8d69caSLisandro Dalcin   int ys = PetscMax(y, img->clip[1]), ye = PetscMin(y + h, img->clip[3]);
752b8d69caSLisandro Dalcin   if (xs >= xe || ys >= ye) return;
762b8d69caSLisandro Dalcin   for (y = ys; y < ye; y++)
779371c9d4SSatish Balay     for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = (unsigned char)c;
782b8d69caSLisandro Dalcin }
792b8d69caSLisandro Dalcin 
809371c9d4SSatish Balay static inline void PetscImageDrawEllipse(PetscImage img, int xc, int yc, int w, int h, int c) {
812b8d69caSLisandro Dalcin   /* Bresenham's circle/ellipse drawing algorithm */
822b8d69caSLisandro Dalcin   int x, y, s, a2 = w * w, b2 = h * h;
832b8d69caSLisandro Dalcin   for (x = 0, y = h, s = 2 * b2 + a2 * (1 - 2 * h); b2 * x <= a2 * y; x++) {
842b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
852b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
869371c9d4SSatish Balay     if (s >= 0) {
879371c9d4SSatish Balay       s += 4 * a2 * (1 - y);
889371c9d4SSatish Balay       y--;
899371c9d4SSatish Balay     }
902b8d69caSLisandro Dalcin     s += b2 * ((4 * x) + 6);
912b8d69caSLisandro Dalcin   }
922b8d69caSLisandro Dalcin   for (x = w, y = 0, s = 2 * a2 + b2 * (1 - 2 * w); a2 * y <= b2 * x; y++) {
932b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
942b8d69caSLisandro Dalcin     PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
959371c9d4SSatish Balay     if (s >= 0) {
969371c9d4SSatish Balay       s += 4 * b2 * (1 - x);
979371c9d4SSatish Balay       x--;
989371c9d4SSatish Balay     }
992b8d69caSLisandro Dalcin     s += a2 * ((4 * y) + 6);
1002b8d69caSLisandro Dalcin   }
1012b8d69caSLisandro Dalcin }
1022b8d69caSLisandro Dalcin 
1039371c9d4SSatish Balay 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) {
1042b8d69caSLisandro Dalcin   const int SHIFT_VAL = 6;
1052b8d69caSLisandro Dalcin   const int xmin = img->clip[0], xmax = img->clip[2] - 1;
1062b8d69caSLisandro Dalcin   const int ymin = img->clip[1], ymax = img->clip[3] - 1;
1072b8d69caSLisandro Dalcin   float     rfrac, lfrac, one = 1;
1082b8d69caSLisandro Dalcin   float     R_y2_y1, R_y3_y1, R_y3_y2;
1092b8d69caSLisandro Dalcin   int       lc, rc = 0, lx, rx = 0, xx, y, c;
1102b8d69caSLisandro Dalcin   int       rc_lc, rx_lx, t2_t1, x2_x1, t3_t1, x3_x1, t3_t2, x3_x2;
1112b8d69caSLisandro Dalcin 
1122b8d69caSLisandro Dalcin   /* Is triangle ever visible in image? */
1132b8d69caSLisandro Dalcin   if (x_1 < xmin && x_2 < xmin && x_3 < xmin) return;
1142b8d69caSLisandro Dalcin   if (y_1 < ymin && y_2 < ymin && y_3 < ymin) return;
1152b8d69caSLisandro Dalcin   if (x_1 > xmax && x_2 > xmax && x_3 > xmax) return;
1162b8d69caSLisandro Dalcin   if (y_1 > ymax && y_2 > ymax && y_3 > ymax) return;
1172b8d69caSLisandro Dalcin 
1182b8d69caSLisandro Dalcin   t_1 = t_1 << SHIFT_VAL;
1192b8d69caSLisandro Dalcin   t_2 = t_2 << SHIFT_VAL;
1202b8d69caSLisandro Dalcin   t_3 = t_3 << SHIFT_VAL;
1212b8d69caSLisandro Dalcin 
1222b8d69caSLisandro Dalcin   /* Sort the vertices */
1239371c9d4SSatish Balay #define SWAP(a, b) \
1249371c9d4SSatish Balay   do { \
1259371c9d4SSatish Balay     int _tmp; \
1269371c9d4SSatish Balay     _tmp = a; \
1279371c9d4SSatish Balay     a    = b; \
1289371c9d4SSatish Balay     b    = _tmp; \
1299371c9d4SSatish Balay   } while (0)
1309371c9d4SSatish Balay   if (y_1 > y_2) {
1319371c9d4SSatish Balay     SWAP(x_1, x_2);
1329371c9d4SSatish Balay     SWAP(y_1, y_2);
1339371c9d4SSatish Balay     SWAP(t_1, t_2);
1349371c9d4SSatish Balay   }
1359371c9d4SSatish Balay   if (y_1 > y_3) {
1369371c9d4SSatish Balay     SWAP(x_1, x_3);
1379371c9d4SSatish Balay     SWAP(y_1, y_3);
1389371c9d4SSatish Balay     SWAP(t_1, t_3);
1399371c9d4SSatish Balay   }
1409371c9d4SSatish Balay   if (y_2 > y_3) {
1419371c9d4SSatish Balay     SWAP(x_2, x_3);
1429371c9d4SSatish Balay     SWAP(y_2, y_3);
1439371c9d4SSatish Balay     SWAP(t_2, t_3);
1449371c9d4SSatish Balay   }
1452b8d69caSLisandro Dalcin #undef SWAP
1462b8d69caSLisandro Dalcin 
1472b8d69caSLisandro Dalcin   /* This code is decidely non-optimal;
1482b8d69caSLisandro Dalcin    it is intended to be a start at an implementation */
1492b8d69caSLisandro Dalcin 
1502b8d69caSLisandro Dalcin   t2_t1   = t_2 - t_1;
1512b8d69caSLisandro Dalcin   x2_x1   = x_2 - x_1;
1522b8d69caSLisandro Dalcin   R_y2_y1 = (y_2 != y_1) ? one / (y_2 - y_1) : 0;
1532b8d69caSLisandro Dalcin   R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
1542b8d69caSLisandro Dalcin   x3_x1   = x_3 - x_1;
1552b8d69caSLisandro Dalcin   t3_t1   = t_3 - t_1;
1562b8d69caSLisandro Dalcin 
1572b8d69caSLisandro Dalcin   for (y = y_1; y <= y_2; y++) {
1582b8d69caSLisandro Dalcin     /* Draw a line with the correct color from t1-t2 to t1-t3 */
1592b8d69caSLisandro Dalcin     /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
1602b8d69caSLisandro Dalcin     lfrac = (y - y_1) * R_y2_y1;
1612b8d69caSLisandro Dalcin     lc    = (int)(lfrac * (t2_t1) + t_1);
1622b8d69caSLisandro Dalcin     lx    = (int)(lfrac * (x2_x1) + x_1);
1632b8d69caSLisandro Dalcin     /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
1642b8d69caSLisandro Dalcin     rfrac = (y - y_1) * R_y3_y1;
1652b8d69caSLisandro Dalcin     rc    = (int)(rfrac * (t3_t1) + t_1);
1662b8d69caSLisandro Dalcin     rx    = (int)(rfrac * (x3_x1) + x_1);
1672b8d69caSLisandro Dalcin     /* Draw the line */
1682b8d69caSLisandro Dalcin     rc_lc = rc - lc;
1692b8d69caSLisandro Dalcin     rx_lx = rx - lx;
1702b8d69caSLisandro Dalcin     if (rx > lx) {
1712b8d69caSLisandro Dalcin       for (xx = lx; xx <= rx; xx++) {
1722b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
1732b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
1742b8d69caSLisandro Dalcin       }
1752b8d69caSLisandro Dalcin     } else if (rx < lx) {
1762b8d69caSLisandro Dalcin       for (xx = lx; xx >= rx; xx--) {
1772b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
1782b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
1792b8d69caSLisandro Dalcin       }
1802b8d69caSLisandro Dalcin     } else {
1812b8d69caSLisandro Dalcin       c = lc >> SHIFT_VAL;
1822b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, lx, y, c);
1832b8d69caSLisandro Dalcin     }
1842b8d69caSLisandro Dalcin   }
1852b8d69caSLisandro Dalcin 
1862b8d69caSLisandro Dalcin   /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2.
1872b8d69caSLisandro Dalcin      We take advantage of the previous iteration. */
1882b8d69caSLisandro Dalcin   if (y_2 >= y_3) return;
1892b8d69caSLisandro Dalcin   if (y_1 < y_2) {
1902b8d69caSLisandro Dalcin     x_1   = rx;
1912b8d69caSLisandro Dalcin     y_1   = y_2;
1922b8d69caSLisandro Dalcin     t_1   = rc;
1932b8d69caSLisandro Dalcin     x3_x1 = x_3 - x_1;
1942b8d69caSLisandro Dalcin     t3_t1 = t_3 - t_1;
1952b8d69caSLisandro Dalcin   }
1962b8d69caSLisandro Dalcin   R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
1972b8d69caSLisandro Dalcin   R_y3_y2 = (y_3 != y_2) ? one / (y_3 - y_2) : 0;
1982b8d69caSLisandro Dalcin   x3_x2   = x_3 - x_2;
1992b8d69caSLisandro Dalcin   t3_t2   = t_3 - t_2;
2002b8d69caSLisandro Dalcin 
2012b8d69caSLisandro Dalcin   for (y = y_2; y <= y_3; y++) {
2022b8d69caSLisandro Dalcin     /* Draw a line with the correct color from t2-t3 to t1-t3 */
2032b8d69caSLisandro Dalcin     /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
2042b8d69caSLisandro Dalcin     lfrac = (y - y_2) * R_y3_y2;
2052b8d69caSLisandro Dalcin     lc    = (int)(lfrac * (t3_t2) + t_2);
2062b8d69caSLisandro Dalcin     lx    = (int)(lfrac * (x3_x2) + x_2);
2072b8d69caSLisandro Dalcin     /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
2082b8d69caSLisandro Dalcin     rfrac = (y - y_1) * R_y3_y1;
2092b8d69caSLisandro Dalcin     rc    = (int)(rfrac * (t3_t1) + t_1);
2102b8d69caSLisandro Dalcin     rx    = (int)(rfrac * (x3_x1) + x_1);
2112b8d69caSLisandro Dalcin     /* Draw the line */
2122b8d69caSLisandro Dalcin     rc_lc = rc - lc;
2132b8d69caSLisandro Dalcin     rx_lx = rx - lx;
2142b8d69caSLisandro Dalcin     if (rx > lx) {
2152b8d69caSLisandro Dalcin       for (xx = lx; xx <= rx; xx++) {
2162b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
2172b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
2182b8d69caSLisandro Dalcin       }
2192b8d69caSLisandro Dalcin     } else if (rx < lx) {
2202b8d69caSLisandro Dalcin       for (xx = lx; xx >= rx; xx--) {
2212b8d69caSLisandro Dalcin         c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
2222b8d69caSLisandro Dalcin         PetscImageDrawPixel(img, xx, y, c);
2232b8d69caSLisandro Dalcin       }
2242b8d69caSLisandro Dalcin     } else {
2252b8d69caSLisandro Dalcin       c = lc >> SHIFT_VAL;
2262b8d69caSLisandro Dalcin       PetscImageDrawPixel(img, lx, y, c);
2272b8d69caSLisandro Dalcin     }
2282b8d69caSLisandro Dalcin   }
2292b8d69caSLisandro Dalcin }
2302b8d69caSLisandro Dalcin 
2312b8d69caSLisandro Dalcin #define PetscImageFontWidth  6
2322b8d69caSLisandro Dalcin #define PetscImageFontHeight 10
2332b8d69caSLisandro Dalcin static const unsigned char PetscImageFontBitmap[128 - 32][10] = {
2342b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*   */
2352b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ! */
2362b8d69caSLisandro Dalcin   {0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
2372b8d69caSLisandro Dalcin   {0x00, 0x14, 0x14, 0x3E, 0x14, 0x3E, 0x14, 0x14, 0x00, 0x00}, /* # */
2382b8d69caSLisandro Dalcin   {0x00, 0x08, 0x1C, 0x28, 0x1C, 0x0A, 0x1C, 0x08, 0x00, 0x00}, /* $ */
2392b8d69caSLisandro Dalcin   {0x00, 0x12, 0x2A, 0x14, 0x08, 0x14, 0x2A, 0x24, 0x00, 0x00}, /* % */
2402b8d69caSLisandro Dalcin   {0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00}, /* & */
2412b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
2422b8d69caSLisandro Dalcin   {0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, 0x00}, /* ( */
2432b8d69caSLisandro Dalcin   {0x00, 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00, 0x00}, /*) */
2442b8d69caSLisandro Dalcin   {0x00, 0x00, 0x22, 0x14, 0x3E, 0x14, 0x22, 0x00, 0x00, 0x00}, /* * */
2452b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00}, /* + */
2462b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* , */
2472b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00}, /* - */
2482b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* . */
2492b8d69caSLisandro Dalcin   {0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00}, /* / */
2502b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x00}, /* 0 */
2512b8d69caSLisandro Dalcin   {0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /* 1 */
2522b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x02, 0x0C, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* 2 */
2532b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x0C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 3 */
2542b8d69caSLisandro Dalcin   {0x00, 0x04, 0x0C, 0x14, 0x24, 0x3E, 0x04, 0x04, 0x00, 0x00}, /* 4 */
2552b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x2C, 0x32, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 5 */
2562b8d69caSLisandro Dalcin   {0x00, 0x0C, 0x10, 0x20, 0x2C, 0x32, 0x22, 0x1C, 0x00, 0x00}, /* 6 */
2572b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00}, /* 7 */
2582b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* 8 */
2592b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x26, 0x1A, 0x02, 0x04, 0x18, 0x00, 0x00}, /* 9 */
2602b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* : */
2612b8d69caSLisandro Dalcin   {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* } */
2622b8d69caSLisandro Dalcin   {0x00, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /* < */
2632b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, /* = */
2642b8d69caSLisandro Dalcin   {0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00}, /* > */
2652b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ? */
2662b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x26, 0x2A, 0x2C, 0x20, 0x1C, 0x00, 0x00}, /* @ */
2672b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00}, /* A */
2682b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* B */
2692b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* C */
2702b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* D */
2712b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* E */
2722b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* F */
2732b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x20, 0x26, 0x22, 0x1C, 0x00, 0x00}, /* G */
2742b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00}, /* H */
2752b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* I */
2762b8d69caSLisandro Dalcin   {0x00, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x00}, /* J */
2772b8d69caSLisandro Dalcin   {0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00}, /* K */
2782b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* L */
2792b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00}, /* M */
2802b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x00, 0x00}, /* N */
2812b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* O */
2822b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* P */
2832b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x2A, 0x1C, 0x02, 0x00}, /* Q */
2842b8d69caSLisandro Dalcin   {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00}, /* R */
2852b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x22, 0x20, 0x1C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* S */
2862b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* T */
2872b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* U */
2882b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00}, /* V */
2892b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00}, /* W */
2902b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00}, /* X */
2912b8d69caSLisandro Dalcin   {0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* Y */
2922b8d69caSLisandro Dalcin   {0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* Z */
2932b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x00, 0x00}, /* [ */
2942b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00}, /* \ */
2952b8d69caSLisandro Dalcin   {0x00, 0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x00, 0x00}, /* ] */
2962b8d69caSLisandro Dalcin   {0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ^ */
2972b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00}, /* _ */
2982b8d69caSLisandro Dalcin   {0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
2992b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00}, /* a */
3002b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x00, 0x00}, /* b */
3012b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* c */
3022b8d69caSLisandro Dalcin   {0x00, 0x02, 0x02, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* d */
3032b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00}, /* e */
3042b8d69caSLisandro Dalcin   {0x00, 0x0C, 0x12, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x00, 0x00}, /* f */
3052b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x1E, 0x02, 0x22, 0x1C}, /* g */
3062b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* h */
3072b8d69caSLisandro Dalcin   {0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* i */
3082b8d69caSLisandro Dalcin   {0x00, 0x02, 0x00, 0x06, 0x02, 0x02, 0x02, 0x12, 0x12, 0x0C}, /* j */
3092b8d69caSLisandro Dalcin   {0x00, 0x20, 0x20, 0x22, 0x24, 0x38, 0x24, 0x22, 0x00, 0x00}, /* k */
3102b8d69caSLisandro Dalcin   {0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* l */
3112b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x34, 0x2A, 0x2A, 0x2A, 0x22, 0x00, 0x00}, /* m */
3122b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* n */
3132b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* o */
3142b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x20, 0x20}, /* p */
3152b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x02, 0x02}, /* q */
3162b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00}, /* r */
3172b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x1C, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00}, /* s */
3182b8d69caSLisandro Dalcin   {0x00, 0x10, 0x10, 0x3C, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00}, /* t */
3192b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* u */
3202b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00}, /* v */
3212b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x2A, 0x2A, 0x14, 0x00, 0x00}, /* w */
3222b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00}, /* x */
3232b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x22, 0x22, 0x26, 0x1A, 0x02, 0x22, 0x1C}, /* y */
3242b8d69caSLisandro Dalcin   {0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00}, /* z */
3252b8d69caSLisandro Dalcin   {0x00, 0x06, 0x08, 0x04, 0x18, 0x04, 0x08, 0x06, 0x00, 0x00}, /* { */
3262b8d69caSLisandro Dalcin   {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* | */
3272b8d69caSLisandro Dalcin   {0x00, 0x18, 0x04, 0x08, 0x06, 0x08, 0x04, 0x18, 0x00, 0x00}, /* } */
3282b8d69caSLisandro Dalcin   {0x00, 0x12, 0x2A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ~ */
3292b8d69caSLisandro Dalcin   {0x00, 0x2A, 0x00, 0x22, 0x00, 0x22, 0x00, 0x2A, 0x00, 0x00}, /* ASCII 127 */
3302b8d69caSLisandro Dalcin };
3312b8d69caSLisandro Dalcin 
3329371c9d4SSatish Balay static inline void PetscImageDrawText(PetscImage img, int x, int y, int c, const char text[]) {
3332b8d69caSLisandro Dalcin   int i, j, k, tw = PetscImageFontWidth, th = PetscImageFontHeight;
3342b8d69caSLisandro Dalcin   for (i = 0; i < th; i++) {
3352b8d69caSLisandro Dalcin     for (k = 0; text[k]; k++) {
3362b8d69caSLisandro Dalcin       int chr = PetscClipInterval(text[k], 32, 127);
3372b8d69caSLisandro Dalcin       for (j = 0; j < tw; j++) {
3389371c9d4SSatish Balay         if (PetscImageFontBitmap[chr - 32][i] & (1 << (tw - 1 - j))) PetscImageDrawPixel(img, x + j + k * tw, y + i - th, c);
3392b8d69caSLisandro Dalcin       }
3402b8d69caSLisandro Dalcin     }
3412b8d69caSLisandro Dalcin   }
3422b8d69caSLisandro Dalcin }
3432b8d69caSLisandro Dalcin 
3442b8d69caSLisandro Dalcin #endif
345