Actual source code: drawimage.h
1: #ifndef _PETSCIMAGE_H
2: #define _PETSCIMAGE_H
4: #include <petscdraw.h>
6: typedef struct _n_PetscImage *PetscImage;
7: typedef struct _n_PetscImage {
8: unsigned char *buffer; /* raster buffer */
9: int w, h; /* width, height */
10: int clip[4]; /* clip ranges */
11: unsigned char palette[256][3]; /* colormap */
12: } _n_PetscImage;
14: static inline void PetscImageSetClip(PetscImage img, int x, int y, int w, int h)
15: {
16: img->clip[0] = PetscClipInterval(x, 0, img->w - 1); /* xmin */
17: img->clip[1] = PetscClipInterval(y, 0, img->h - 1); /* ymin */
18: img->clip[2] = PetscClipInterval(x + w, 0, img->w); /* xmax+1 */
19: img->clip[3] = PetscClipInterval(y + h, 0, img->h); /* ymax+1 */
20: }
22: static inline void PetscImageClear(PetscImage img)
23: {
24: int x, xs = img->clip[0], xe = img->clip[2];
25: int y, ys = img->clip[1], ye = img->clip[3];
26: for (y = ys; y < ye; y++)
27: for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = 0;
28: }
30: static inline void PetscImageDrawPixel(PetscImage img, int x, int y, int c)
31: {
32: if (x < img->clip[0] || x >= img->clip[2]) return;
33: if (y < img->clip[1] || y >= img->clip[3]) return;
34: img->buffer[y * img->w + x] = (unsigned char)c;
35: }
37: static inline void PetscImageDrawLine(PetscImage img, int x_1, int y_1, int x_2, int y_2, int c)
38: {
39: if (y_1 == y_2) {
40: /* Horizontal line */
41: if (x_2 - x_1 < 0) {
42: int tmp = x_1;
43: x_1 = x_2;
44: x_2 = tmp;
45: }
46: while (x_1 <= x_2) PetscImageDrawPixel(img, x_1++, y_1, c);
47: } else if (x_1 == x_2) {
48: /* Vertical line */
49: if (y_2 - y_1 < 0) {
50: int tmp = y_1;
51: y_1 = y_2;
52: y_2 = tmp;
53: }
54: while (y_1 <= y_2) PetscImageDrawPixel(img, x_1, y_1++, c);
55: } else {
56: /* Bresenham's line drawing algorithm */
57: int dx = PetscAbs(x_2 - x_1), sx = (x_2 - x_1) >= 0 ? +1 : -1;
58: int dy = PetscAbs(y_2 - y_1), sy = (y_2 - y_1) >= 0 ? +1 : -1;
59: int error = (dx > dy ? dx : -dy) / 2, err;
60: while (1) {
61: PetscImageDrawPixel(img, x_1, y_1, c);
62: if (x_1 == x_2 && y_1 == y_2) break;
63: err = error;
64: if (err > -dx) {
65: error -= dy;
66: x_1 += sx;
67: }
68: if (err < +dy) {
69: error += dx;
70: y_1 += sy;
71: }
72: }
73: }
74: }
76: static inline void PetscImageDrawRectangle(PetscImage img, int x, int y, int w, int h, int c)
77: {
78: int xs = PetscMax(x, img->clip[0]), xe = PetscMin(x + w, img->clip[2]);
79: int ys = PetscMax(y, img->clip[1]), ye = PetscMin(y + h, img->clip[3]);
80: if (xs >= xe || ys >= ye) return;
81: for (y = ys; y < ye; y++)
82: for (x = xs; x < xe; x++) img->buffer[y * img->w + x] = (unsigned char)c;
83: }
85: static inline void PetscImageDrawEllipse(PetscImage img, int xc, int yc, int w, int h, int c)
86: {
87: /* Bresenham's circle/ellipse drawing algorithm */
88: int x, y, s, a2 = w * w, b2 = h * h;
89: for (x = 0, y = h, s = 2 * b2 + a2 * (1 - 2 * h); b2 * x <= a2 * y; x++) {
90: PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
91: PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
92: if (s >= 0) {
93: s += 4 * a2 * (1 - y);
94: y--;
95: }
96: s += b2 * ((4 * x) + 6);
97: }
98: for (x = w, y = 0, s = 2 * a2 + b2 * (1 - 2 * w); a2 * y <= b2 * x; y++) {
99: PetscImageDrawLine(img, xc + x, yc + y, xc - x, yc + y, c);
100: PetscImageDrawLine(img, xc + x, yc - y, xc - x, yc - y, c);
101: if (s >= 0) {
102: s += 4 * b2 * (1 - x);
103: x--;
104: }
105: s += a2 * ((4 * y) + 6);
106: }
107: }
109: 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)
110: {
111: const int SHIFT_VAL = 6;
112: const int xmin = img->clip[0], xmax = img->clip[2] - 1;
113: const int ymin = img->clip[1], ymax = img->clip[3] - 1;
114: float rfrac, lfrac, one = 1;
115: float R_y2_y1, R_y3_y1, R_y3_y2;
116: int lc, rc = 0, lx, rx = 0, xx, y, c;
117: int rc_lc, rx_lx, t2_t1, x2_x1, t3_t1, x3_x1, t3_t2, x3_x2;
119: /* Is triangle ever visible in image? */
120: if (x_1 < xmin && x_2 < xmin && x_3 < xmin) return;
121: if (y_1 < ymin && y_2 < ymin && y_3 < ymin) return;
122: if (x_1 > xmax && x_2 > xmax && x_3 > xmax) return;
123: if (y_1 > ymax && y_2 > ymax && y_3 > ymax) return;
125: t_1 = t_1 << SHIFT_VAL;
126: t_2 = t_2 << SHIFT_VAL;
127: t_3 = t_3 << SHIFT_VAL;
129: /* Sort the vertices */
130: #define SWAP(a, b) \
131: do { \
132: int _tmp; \
133: _tmp = a; \
134: a = b; \
135: b = _tmp; \
136: } while (0)
137: if (y_1 > y_2) {
138: SWAP(x_1, x_2);
139: SWAP(y_1, y_2);
140: SWAP(t_1, t_2);
141: }
142: if (y_1 > y_3) {
143: SWAP(x_1, x_3);
144: SWAP(y_1, y_3);
145: SWAP(t_1, t_3);
146: }
147: if (y_2 > y_3) {
148: SWAP(x_2, x_3);
149: SWAP(y_2, y_3);
150: SWAP(t_2, t_3);
151: }
152: #undef SWAP
154: /* This code is decidedly non-optimal;
155: it is intended to be a start at an implementation */
157: t2_t1 = t_2 - t_1;
158: x2_x1 = x_2 - x_1;
159: R_y2_y1 = (y_2 != y_1) ? one / (y_2 - y_1) : 0;
160: R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
161: x3_x1 = x_3 - x_1;
162: t3_t1 = t_3 - t_1;
164: for (y = y_1; y <= y_2; y++) {
165: /* Draw a line with the correct color from t1-t2 to t1-t3 */
166: /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
167: lfrac = (y - y_1) * R_y2_y1;
168: lc = (int)(lfrac * (t2_t1) + t_1);
169: lx = (int)(lfrac * (x2_x1) + x_1);
170: /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
171: rfrac = (y - y_1) * R_y3_y1;
172: rc = (int)(rfrac * (t3_t1) + t_1);
173: rx = (int)(rfrac * (x3_x1) + x_1);
174: /* Draw the line */
175: rc_lc = rc - lc;
176: rx_lx = rx - lx;
177: if (rx > lx) {
178: for (xx = lx; xx <= rx; xx++) {
179: c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
180: PetscImageDrawPixel(img, xx, y, c);
181: }
182: } else if (rx < lx) {
183: for (xx = lx; xx >= rx; xx--) {
184: c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
185: PetscImageDrawPixel(img, xx, y, c);
186: }
187: } else {
188: c = lc >> SHIFT_VAL;
189: PetscImageDrawPixel(img, lx, y, c);
190: }
191: }
193: /* For simplicity,"move" t1 to the intersection of t1-t3 with the line y=y2.
194: We take advantage of the previous iteration. */
195: if (y_2 >= y_3) return;
196: if (y_1 < y_2) {
197: x_1 = rx;
198: y_1 = y_2;
199: t_1 = rc;
200: x3_x1 = x_3 - x_1;
201: t3_t1 = t_3 - t_1;
202: }
203: R_y3_y1 = (y_3 != y_1) ? one / (y_3 - y_1) : 0;
204: R_y3_y2 = (y_3 != y_2) ? one / (y_3 - y_2) : 0;
205: x3_x2 = x_3 - x_2;
206: t3_t2 = t_3 - t_2;
208: for (y = y_2; y <= y_3; y++) {
209: /* Draw a line with the correct color from t2-t3 to t1-t3 */
210: /* Left color is (y-y1)/(y2-y1) * (t2-t1) + t1 */
211: lfrac = (y - y_2) * R_y3_y2;
212: lc = (int)(lfrac * (t3_t2) + t_2);
213: lx = (int)(lfrac * (x3_x2) + x_2);
214: /* Right color is (y-y1)/(y3-y1) * (t3-t1) + t1 */
215: rfrac = (y - y_1) * R_y3_y1;
216: rc = (int)(rfrac * (t3_t1) + t_1);
217: rx = (int)(rfrac * (x3_x1) + x_1);
218: /* Draw the line */
219: rc_lc = rc - lc;
220: rx_lx = rx - lx;
221: if (rx > lx) {
222: for (xx = lx; xx <= rx; xx++) {
223: c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
224: PetscImageDrawPixel(img, xx, y, c);
225: }
226: } else if (rx < lx) {
227: for (xx = lx; xx >= rx; xx--) {
228: c = (((xx - lx) * (rc_lc)) / (rx_lx) + lc) >> SHIFT_VAL;
229: PetscImageDrawPixel(img, xx, y, c);
230: }
231: } else {
232: c = lc >> SHIFT_VAL;
233: PetscImageDrawPixel(img, lx, y, c);
234: }
235: }
236: }
238: #define PetscImageFontWidth 6
239: #define PetscImageFontHeight 10
240: static const unsigned char PetscImageFontBitmap[128 - 32][10] = {
241: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* */
242: {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ! */
243: {0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* " */
244: {0x00, 0x14, 0x14, 0x3E, 0x14, 0x3E, 0x14, 0x14, 0x00, 0x00}, /* # */
245: {0x00, 0x08, 0x1C, 0x28, 0x1C, 0x0A, 0x1C, 0x08, 0x00, 0x00}, /* $ */
246: {0x00, 0x12, 0x2A, 0x14, 0x08, 0x14, 0x2A, 0x24, 0x00, 0x00}, /* % */
247: {0x00, 0x10, 0x28, 0x28, 0x10, 0x2A, 0x24, 0x1A, 0x00, 0x00}, /* & */
248: {0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ' */
249: {0x00, 0x04, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, 0x00, 0x00}, /* ( */
250: {0x00, 0x10, 0x08, 0x04, 0x04, 0x04, 0x08, 0x10, 0x00, 0x00}, /*) */
251: {0x00, 0x00, 0x22, 0x14, 0x3E, 0x14, 0x22, 0x00, 0x00, 0x00}, /* * */
252: {0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00, 0x00}, /* + */
253: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* , */
254: {0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00}, /* - */
255: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* . */
256: {0x00, 0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00, 0x00}, /* / */
257: {0x00, 0x08, 0x14, 0x22, 0x22, 0x22, 0x14, 0x08, 0x00, 0x00}, /* 0 */
258: {0x00, 0x08, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00}, /* 1 */
259: {0x00, 0x1C, 0x22, 0x02, 0x0C, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* 2 */
260: {0x00, 0x3E, 0x02, 0x04, 0x0C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 3 */
261: {0x00, 0x04, 0x0C, 0x14, 0x24, 0x3E, 0x04, 0x04, 0x00, 0x00}, /* 4 */
262: {0x00, 0x3E, 0x20, 0x2C, 0x32, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* 5 */
263: {0x00, 0x0C, 0x10, 0x20, 0x2C, 0x32, 0x22, 0x1C, 0x00, 0x00}, /* 6 */
264: {0x00, 0x3E, 0x02, 0x04, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00}, /* 7 */
265: {0x00, 0x1C, 0x22, 0x22, 0x1C, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* 8 */
266: {0x00, 0x1C, 0x22, 0x26, 0x1A, 0x02, 0x04, 0x18, 0x00, 0x00}, /* 9 */
267: {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x08, 0x1C, 0x08, 0x00}, /* : */
268: {0x00, 0x00, 0x08, 0x1C, 0x08, 0x00, 0x0C, 0x08, 0x10, 0x00}, /* } */
269: {0x00, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, /* < */
270: {0x00, 0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00}, /* = */
271: {0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00}, /* > */
272: {0x00, 0x1C, 0x22, 0x04, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00}, /* ? */
273: {0x00, 0x1C, 0x22, 0x26, 0x2A, 0x2C, 0x20, 0x1C, 0x00, 0x00}, /* @ */
274: {0x00, 0x08, 0x14, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x00, 0x00}, /* A */
275: {0x00, 0x3C, 0x12, 0x12, 0x1C, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* B */
276: {0x00, 0x1C, 0x22, 0x20, 0x20, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* C */
277: {0x00, 0x3C, 0x12, 0x12, 0x12, 0x12, 0x12, 0x3C, 0x00, 0x00}, /* D */
278: {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* E */
279: {0x00, 0x3E, 0x20, 0x20, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* F */
280: {0x00, 0x1C, 0x22, 0x20, 0x20, 0x26, 0x22, 0x1C, 0x00, 0x00}, /* G */
281: {0x00, 0x22, 0x22, 0x22, 0x3E, 0x22, 0x22, 0x22, 0x00, 0x00}, /* H */
282: {0x00, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* I */
283: {0x00, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x24, 0x18, 0x00, 0x00}, /* J */
284: {0x00, 0x22, 0x24, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00, 0x00}, /* K */
285: {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3E, 0x00, 0x00}, /* L */
286: {0x00, 0x22, 0x22, 0x36, 0x2A, 0x22, 0x22, 0x22, 0x00, 0x00}, /* M */
287: {0x00, 0x22, 0x22, 0x32, 0x2A, 0x26, 0x22, 0x22, 0x00, 0x00}, /* N */
288: {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* O */
289: {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20, 0x20, 0x00, 0x00}, /* P */
290: {0x00, 0x1C, 0x22, 0x22, 0x22, 0x22, 0x2A, 0x1C, 0x02, 0x00}, /* Q */
291: {0x00, 0x3C, 0x22, 0x22, 0x3C, 0x28, 0x24, 0x22, 0x00, 0x00}, /* R */
292: {0x00, 0x1C, 0x22, 0x20, 0x1C, 0x02, 0x22, 0x1C, 0x00, 0x00}, /* S */
293: {0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* T */
294: {0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* U */
295: {0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00}, /* V */
296: {0x00, 0x22, 0x22, 0x22, 0x2A, 0x2A, 0x36, 0x22, 0x00, 0x00}, /* W */
297: {0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00}, /* X */
298: {0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* Y */
299: {0x00, 0x3E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x3E, 0x00, 0x00}, /* Z */
300: {0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x00, 0x00}, /* [ */
301: {0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x00, 0x00}, /* \ */
302: {0x00, 0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x00, 0x00}, /* ] */
303: {0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ^ */
304: {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00}, /* _ */
305: {0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ` */
306: {0x00, 0x00, 0x00, 0x1C, 0x02, 0x1E, 0x22, 0x1E, 0x00, 0x00}, /* a */
307: {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x00, 0x00}, /* b */
308: {0x00, 0x00, 0x00, 0x1C, 0x22, 0x20, 0x22, 0x1C, 0x00, 0x00}, /* c */
309: {0x00, 0x02, 0x02, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* d */
310: {0x00, 0x00, 0x00, 0x1C, 0x22, 0x3E, 0x20, 0x1C, 0x00, 0x00}, /* e */
311: {0x00, 0x0C, 0x12, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x00, 0x00}, /* f */
312: {0x00, 0x00, 0x00, 0x1E, 0x22, 0x22, 0x1E, 0x02, 0x22, 0x1C}, /* g */
313: {0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* h */
314: {0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* i */
315: {0x00, 0x02, 0x00, 0x06, 0x02, 0x02, 0x02, 0x12, 0x12, 0x0C}, /* j */
316: {0x00, 0x20, 0x20, 0x22, 0x24, 0x38, 0x24, 0x22, 0x00, 0x00}, /* k */
317: {0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00, 0x00}, /* l */
318: {0x00, 0x00, 0x00, 0x34, 0x2A, 0x2A, 0x2A, 0x22, 0x00, 0x00}, /* m */
319: {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00, 0x00}, /* n */
320: {0x00, 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00, 0x00}, /* o */
321: {0x00, 0x00, 0x00, 0x2C, 0x32, 0x22, 0x32, 0x2C, 0x20, 0x20}, /* p */
322: {0x00, 0x00, 0x00, 0x1A, 0x26, 0x22, 0x26, 0x1A, 0x02, 0x02}, /* q */
323: {0x00, 0x00, 0x00, 0x2C, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00}, /* r */
324: {0x00, 0x00, 0x00, 0x1C, 0x20, 0x1C, 0x02, 0x3C, 0x00, 0x00}, /* s */
325: {0x00, 0x10, 0x10, 0x3C, 0x10, 0x10, 0x12, 0x0C, 0x00, 0x00}, /* t */
326: {0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00, 0x00}, /* u */
327: {0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00}, /* v */
328: {0x00, 0x00, 0x00, 0x22, 0x22, 0x2A, 0x2A, 0x14, 0x00, 0x00}, /* w */
329: {0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00}, /* x */
330: {0x00, 0x00, 0x00, 0x22, 0x22, 0x26, 0x1A, 0x02, 0x22, 0x1C}, /* y */
331: {0x00, 0x00, 0x00, 0x3E, 0x04, 0x08, 0x10, 0x3E, 0x00, 0x00}, /* z */
332: {0x00, 0x06, 0x08, 0x04, 0x18, 0x04, 0x08, 0x06, 0x00, 0x00}, /* { */
333: {0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, /* | */
334: {0x00, 0x18, 0x04, 0x08, 0x06, 0x08, 0x04, 0x18, 0x00, 0x00}, /* } */
335: {0x00, 0x12, 0x2A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ~ */
336: {0x00, 0x2A, 0x00, 0x22, 0x00, 0x22, 0x00, 0x2A, 0x00, 0x00}, /* ASCII 127 */
337: };
339: static inline void PetscImageDrawText(PetscImage img, int x, int y, int c, const char text[])
340: {
341: int i, j, k, tw = PetscImageFontWidth, th = PetscImageFontHeight;
342: for (i = 0; i < th; i++) {
343: for (k = 0; text[k]; k++) {
344: int chr = PetscClipInterval(text[k], 32, 127);
345: for (j = 0; j < tw; j++) {
346: if (PetscImageFontBitmap[chr - 32][i] & (1 << (tw - 1 - j))) PetscImageDrawPixel(img, x + j + k * tw, y + i - th, c);
347: }
348: }
349: }
350: }
352: #endif