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