Commit | Line | Data |
---|---|---|
df4f9147 PG |
1 | /* |
2 | * drawtext.c: print text over the screen | |
0a6de063 | 3 | ****************************************************************************** |
df4f9147 | 4 | * Options: |
0a6de063 PG |
5 | * -f <filename> font filename (MANDATORY!!!) |
6 | * -s <pixel_size> font size in pixels [default 16] | |
df4f9147 PG |
7 | * -b print background |
8 | * -o outline glyphs (use the bg color) | |
0a6de063 PG |
9 | * -x <pos> x position ( >= 0) [default 0] |
10 | * -y <pos> y position ( >= 0) [default 0] | |
df4f9147 | 11 | * -t <text> text to print (will be passed to strftime()) |
115329f1 DB |
12 | * MANDATORY: will be used even when -T is used. |
13 | * in this case, -t will be used if some error | |
0a6de063 PG |
14 | * occurs |
15 | * -T <filename> file with the text (re-read every frame) | |
16 | * -c <#RRGGBB> foreground color ('internet' way) [default #ffffff] | |
17 | * -C <#RRGGBB> background color ('internet' way) [default #000000] | |
df4f9147 | 18 | * |
0a6de063 PG |
19 | ****************************************************************************** |
20 | * Features: | |
21 | * - True Type, Type1 and others via FreeType2 library | |
22 | * - Font kerning (better output) | |
23 | * - Line Wrap (if the text doesn't fit, the next char go to the next line) | |
24 | * - Background box | |
25 | * - Outline | |
26 | ****************************************************************************** | |
df4f9147 PG |
27 | * Author: Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br> |
28 | * | |
b78e7197 DB |
29 | * This file is part of FFmpeg. |
30 | * | |
31 | * FFmpeg is free software; you can redistribute it and/or | |
df4f9147 PG |
32 | * modify it under the terms of the GNU Lesser General Public |
33 | * License as published by the Free Software Foundation; either | |
b78e7197 | 34 | * version 2.1 of the License, or (at your option) any later version. |
df4f9147 | 35 | * |
b78e7197 | 36 | * FFmpeg is distributed in the hope that it will be useful, |
df4f9147 PG |
37 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
38 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
39 | * Lesser General Public License for more details. | |
40 | * | |
41 | * You should have received a copy of the GNU Lesser General Public | |
b78e7197 | 42 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 43 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
df4f9147 | 44 | */ |
0a6de063 PG |
45 | |
46 | #define MAXSIZE_TEXT 1024 | |
47 | ||
00a3c8b8 AB |
48 | #include "framehook.h" |
49 | ||
df4f9147 PG |
50 | #include <stdio.h> |
51 | #include <stdlib.h> | |
52 | #include <fcntl.h> | |
53 | #include <stdarg.h> | |
54 | #include <string.h> | |
55 | #include <unistd.h> | |
00a3c8b8 | 56 | #undef time |
df4f9147 PG |
57 | #include <sys/time.h> |
58 | #include <time.h> | |
59 | ||
df4f9147 PG |
60 | #include <ft2build.h> |
61 | #include FT_FREETYPE_H | |
0a6de063 | 62 | #include FT_GLYPH_H |
df4f9147 | 63 | |
95b09624 GSB |
64 | #define SCALEBITS 10 |
65 | #define ONE_HALF (1 << (SCALEBITS - 1)) | |
66 | #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) | |
67 | ||
68 | #define RGB_TO_YUV(rgb_color, yuv_color) do { \ | |
69 | yuv_color[0] = (FIX(0.29900) * rgb_color[0] + FIX(0.58700) * rgb_color[1] + FIX(0.11400) * rgb_color[2] + ONE_HALF) >> SCALEBITS; \ | |
70 | yuv_color[2] = ((FIX(0.50000) * rgb_color[0] - FIX(0.41869) * rgb_color[1] - FIX(0.08131) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \ | |
71 | yuv_color[1] = ((- FIX(0.16874) * rgb_color[0] - FIX(0.33126) * rgb_color[1] + FIX(0.50000) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \ | |
72 | } while (0) | |
df4f9147 PG |
73 | |
74 | #define COPY_3(dst,src) { \ | |
75 | dst[0]=src[0]; \ | |
76 | dst[1]=src[1]; \ | |
77 | dst[2]=src[2]; \ | |
78 | } | |
79 | ||
80 | ||
81 | ||
82 | #define SET_PIXEL(picture, yuv_color, x, y) { \ | |
83 | picture->data[0][ (x) + (y)*picture->linesize[0] ] = yuv_color[0]; \ | |
84 | picture->data[1][ ((x/2) + (y/2)*picture->linesize[1]) ] = yuv_color[1]; \ | |
85 | picture->data[2][ ((x/2) + (y/2)*picture->linesize[2]) ] = yuv_color[2]; \ | |
86 | } | |
87 | ||
88 | #define GET_PIXEL(picture, yuv_color, x, y) { \ | |
89 | yuv_color[0] = picture->data[0][ (x) + (y)*picture->linesize[0] ]; \ | |
90 | yuv_color[1] = picture->data[1][ (x/2) + (y/2)*picture->linesize[1] ]; \ | |
91 | yuv_color[2] = picture->data[2][ (x/2) + (y/2)*picture->linesize[2] ]; \ | |
92 | } | |
93 | ||
94 | ||
95 | typedef struct { | |
0a6de063 | 96 | unsigned char *text; |
2959ba80 | 97 | char *file; |
df4f9147 PG |
98 | unsigned int x; |
99 | unsigned int y; | |
100 | int bg; | |
101 | int outline; | |
102 | unsigned char bgcolor[3]; /* YUV */ | |
103 | unsigned char fgcolor[3]; /* YUV */ | |
0a6de063 PG |
104 | FT_Library library; |
105 | FT_Face face; | |
115329f1 | 106 | FT_Glyph glyphs[ 255 ]; |
0a6de063 PG |
107 | FT_Bitmap bitmaps[ 255 ]; |
108 | int advance[ 255 ]; | |
109 | int bitmap_left[ 255 ]; | |
110 | int bitmap_top[ 255 ]; | |
111 | unsigned int glyphs_index[ 255 ]; | |
112 | int text_height; | |
113 | int baseline; | |
114 | int use_kerning; | |
df4f9147 PG |
115 | } ContextInfo; |
116 | ||
117 | ||
118 | void Release(void *ctx) | |
119 | { | |
120 | if (ctx) | |
121 | av_free(ctx); | |
122 | } | |
123 | ||
124 | ||
efce1a8f | 125 | static int ParseColor(char *text, unsigned char yuv_color[3]) |
df4f9147 PG |
126 | { |
127 | char tmp[3]; | |
128 | unsigned char rgb_color[3]; | |
129 | int i; | |
130 | ||
131 | tmp[2] = '\0'; | |
132 | ||
133 | if ((!text) || (strlen(text) != 7) || (text[0] != '#') ) | |
134 | return -1; | |
135 | ||
136 | for (i=0; i < 3; i++) | |
137 | { | |
138 | tmp[0] = text[i*2+1]; | |
139 | tmp[1] = text[i*2+2]; | |
140 | ||
141 | rgb_color[i] = strtol(tmp, NULL, 16); | |
142 | } | |
143 | ||
144 | RGB_TO_YUV(rgb_color, yuv_color); | |
145 | ||
df4f9147 PG |
146 | return 0; |
147 | } | |
148 | ||
149 | int Configure(void **ctxp, int argc, char *argv[]) | |
150 | { | |
151 | int c; | |
152 | int error; | |
153 | ContextInfo *ci=NULL; | |
154 | char *font=NULL; | |
155 | unsigned int size=16; | |
0a6de063 PG |
156 | FT_BBox bbox; |
157 | int yMax, yMin; | |
df4f9147 PG |
158 | *ctxp = av_mallocz(sizeof(ContextInfo)); |
159 | ci = (ContextInfo *) *ctxp; | |
160 | ||
161 | /* configure Context Info */ | |
162 | ci->text = NULL; | |
0a6de063 | 163 | ci->file = NULL; |
df4f9147 PG |
164 | ci->x = ci->y = 0; |
165 | ci->fgcolor[0]=255; | |
166 | ci->fgcolor[1]=128; | |
167 | ci->fgcolor[2]=128; | |
168 | ci->bgcolor[0]=0; | |
169 | ci->fgcolor[1]=128; | |
170 | ci->fgcolor[2]=128; | |
171 | ci->bg = 0; | |
172 | ci->outline = 0; | |
0a6de063 | 173 | ci->text_height = 0; |
df4f9147 PG |
174 | |
175 | optind = 0; | |
0a6de063 | 176 | while ((c = getopt(argc, argv, "f:t:T:x:y:s:c:C:bo")) > 0) { |
df4f9147 PG |
177 | switch (c) { |
178 | case 'f': | |
bb270c08 DB |
179 | font = optarg; |
180 | break; | |
df4f9147 | 181 | case 't': |
bb270c08 DB |
182 | ci->text = av_strdup(optarg); |
183 | break; | |
0a6de063 | 184 | case 'T': |
bb270c08 DB |
185 | ci->file = av_strdup(optarg); |
186 | break; | |
df4f9147 | 187 | case 'x': |
bb270c08 DB |
188 | ci->x = (unsigned int) atoi(optarg); |
189 | break; | |
df4f9147 | 190 | case 'y': |
bb270c08 DB |
191 | ci->y = (unsigned int) atoi(optarg); |
192 | break; | |
df4f9147 | 193 | case 's': |
bb270c08 DB |
194 | size = (unsigned int) atoi(optarg); |
195 | break; | |
df4f9147 | 196 | case 'c': |
bb270c08 DB |
197 | if (ParseColor(optarg, ci->fgcolor) == -1) |
198 | { | |
aaf78bde | 199 | av_log(NULL, AV_LOG_ERROR, "Invalid foreground color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -c #ffffff (for white foreground)\n", optarg); |
bb270c08 DB |
200 | return -1; |
201 | } | |
202 | break; | |
df4f9147 | 203 | case 'C': |
bb270c08 DB |
204 | if (ParseColor(optarg, ci->bgcolor) == -1) |
205 | { | |
79815f62 | 206 | av_log(NULL, AV_LOG_ERROR, "Invalid background color: '%s'. You must specify the color in the internet way(packaged hex): #RRGGBB, ie: -C #ffffff (for white background)\n", optarg); |
bb270c08 DB |
207 | return -1; |
208 | } | |
209 | break; | |
df4f9147 | 210 | case 'b': |
bb270c08 DB |
211 | ci->bg=1; |
212 | break; | |
df4f9147 | 213 | case 'o': |
bb270c08 DB |
214 | ci->outline=1; |
215 | break; | |
df4f9147 | 216 | case '?': |
aaf78bde | 217 | av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%s'\n", argv[optind]); |
bb270c08 | 218 | return -1; |
df4f9147 PG |
219 | } |
220 | } | |
221 | ||
115329f1 | 222 | if (!ci->text) |
df4f9147 | 223 | { |
aaf78bde | 224 | av_log(NULL, AV_LOG_ERROR, "No text provided (-t text)\n"); |
bb270c08 | 225 | return -1; |
df4f9147 PG |
226 | } |
227 | ||
0a6de063 PG |
228 | if (ci->file) |
229 | { | |
bb270c08 DB |
230 | FILE *fp; |
231 | if ((fp=fopen(ci->file, "r")) == NULL) | |
232 | { | |
aaf78bde | 233 | av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno)); |
bb270c08 DB |
234 | } |
235 | else | |
236 | { | |
237 | fclose(fp); | |
238 | } | |
0a6de063 PG |
239 | } |
240 | ||
df4f9147 PG |
241 | if (!font) |
242 | { | |
aaf78bde | 243 | av_log(NULL, AV_LOG_ERROR, "No font file provided! (-f filename)\n"); |
bb270c08 | 244 | return -1; |
df4f9147 PG |
245 | } |
246 | ||
0a6de063 | 247 | if ((error = FT_Init_FreeType(&(ci->library))) != 0) |
df4f9147 | 248 | { |
aaf78bde | 249 | av_log(NULL, AV_LOG_ERROR, "Could not load FreeType (error# %d).\n", error); |
bb270c08 | 250 | return -1; |
df4f9147 PG |
251 | } |
252 | ||
0a6de063 | 253 | if ((error = FT_New_Face( ci->library, font, 0, &(ci->face) )) != 0) |
df4f9147 | 254 | { |
aaf78bde | 255 | av_log(NULL, AV_LOG_ERROR, "Could not load face: %s (error# %d).\n", font, error); |
bb270c08 | 256 | return -1; |
df4f9147 | 257 | } |
115329f1 | 258 | |
0a6de063 | 259 | if ((error = FT_Set_Pixel_Sizes( ci->face, 0, size)) != 0) |
df4f9147 | 260 | { |
aaf78bde | 261 | av_log(NULL, AV_LOG_ERROR, "Could not set font size to %d pixels (error# %d).\n", size, error); |
bb270c08 | 262 | return -1; |
df4f9147 | 263 | } |
0a6de063 PG |
264 | |
265 | ci->use_kerning = FT_HAS_KERNING(ci->face); | |
266 | ||
267 | /* load and cache glyphs */ | |
268 | yMax = -32000; | |
269 | yMin = 32000; | |
270 | for (c=0; c < 256; c++) | |
271 | { | |
bb270c08 DB |
272 | /* Load char */ |
273 | error = FT_Load_Char( ci->face, (unsigned char) c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME ); | |
274 | if (error) continue; /* ignore errors */ | |
275 | ||
276 | /* Save bitmap */ | |
277 | ci->bitmaps[c] = ci->face->glyph->bitmap; | |
278 | /* Save bitmap left */ | |
279 | ci->bitmap_left[c] = ci->face->glyph->bitmap_left; | |
280 | /* Save bitmap top */ | |
281 | ci->bitmap_top[c] = ci->face->glyph->bitmap_top; | |
282 | ||
283 | /* Save advance */ | |
284 | ci->advance[c] = ci->face->glyph->advance.x >> 6; | |
285 | ||
286 | /* Save glyph */ | |
287 | error = FT_Get_Glyph( ci->face->glyph, &(ci->glyphs[c]) ); | |
288 | /* Save glyph index */ | |
289 | ci->glyphs_index[c] = FT_Get_Char_Index( ci->face, (unsigned char) c ); | |
290 | ||
291 | /* Measure text height to calculate text_height (or the maximum text height) */ | |
292 | FT_Glyph_Get_CBox( ci->glyphs[ c ], ft_glyph_bbox_pixels, &bbox ); | |
293 | if (bbox.yMax > yMax) | |
294 | yMax = bbox.yMax; | |
295 | if (bbox.yMin < yMin) | |
296 | yMin = bbox.yMin; | |
115329f1 | 297 | |
0a6de063 PG |
298 | } |
299 | ||
300 | ci->text_height = yMax - yMin; | |
301 | ci->baseline = yMax; | |
302 | ||
df4f9147 PG |
303 | return 0; |
304 | } | |
305 | ||
306 | ||
0a6de063 PG |
307 | |
308 | ||
efce1a8f | 309 | static inline void draw_glyph(AVPicture *picture, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_fgcolor[3], unsigned char yuv_bgcolor[3], int outline) |
df4f9147 PG |
310 | { |
311 | int r, c; | |
312 | int spixel, dpixel[3], in_glyph=0; | |
313 | ||
314 | if (bitmap->pixel_mode == ft_pixel_mode_mono) | |
315 | { | |
316 | in_glyph = 0; | |
317 | for (r=0; (r < bitmap->rows) && (r+y < height); r++) | |
bb270c08 DB |
318 | { |
319 | for (c=0; (c < bitmap->width) && (c+x < width); c++) | |
320 | { | |
321 | /* pixel in the picture (destination) */ | |
322 | GET_PIXEL(picture, dpixel, (c+x), (y+r)); | |
323 | ||
324 | /* pixel in the glyph bitmap (source) */ | |
325 | spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8)); | |
326 | ||
327 | if (spixel) | |
328 | COPY_3(dpixel, yuv_fgcolor); | |
329 | ||
330 | if (outline) | |
331 | { | |
332 | /* border detection: */ | |
333 | if ( (!in_glyph) && (spixel) ) | |
334 | /* left border detected */ | |
335 | { | |
336 | in_glyph = 1; | |
337 | /* draw left pixel border */ | |
338 | if (c-1 >= 0) | |
339 | SET_PIXEL(picture, yuv_bgcolor, (c+x-1), (y+r)); | |
340 | } | |
341 | else if ( (in_glyph) && (!spixel) ) | |
342 | /* right border detected */ | |
343 | { | |
344 | in_glyph = 0; | |
345 | /* 'draw' right pixel border */ | |
346 | COPY_3(dpixel, yuv_bgcolor); | |
347 | } | |
348 | ||
349 | if (in_glyph) | |
350 | /* see if we have a top/bottom border */ | |
351 | { | |
352 | /* top */ | |
353 | if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) | |
354 | /* we have a top border */ | |
355 | SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r-1)); | |
356 | ||
357 | /* bottom */ | |
358 | if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) | |
359 | /* we have a bottom border */ | |
360 | SET_PIXEL(picture, yuv_bgcolor, (c+x), (y+r+1)); | |
361 | ||
362 | } | |
363 | } | |
364 | ||
365 | SET_PIXEL(picture, dpixel, (c+x), (y+r)); | |
366 | } | |
367 | } | |
df4f9147 PG |
368 | } |
369 | } | |
370 | ||
371 | ||
efce1a8f | 372 | static inline void draw_box(AVPicture *picture, unsigned int x, unsigned int y, unsigned int width, unsigned int height, unsigned char yuv_color[3]) |
0a6de063 PG |
373 | { |
374 | int i, j; | |
375 | ||
376 | for (j = 0; (j < height); j++) | |
115329f1 DB |
377 | for (i = 0; (i < width); i++) |
378 | { | |
bb270c08 | 379 | SET_PIXEL(picture, yuv_color, (i+x), (y+j)); |
0a6de063 | 380 | } |
115329f1 | 381 | |
0a6de063 PG |
382 | } |
383 | ||
384 | ||
385 | ||
386 | ||
244b8613 | 387 | void Process(void *ctx, AVPicture *picture, enum PixelFormat pix_fmt, int width, int height, int64_t pts) |
df4f9147 PG |
388 | { |
389 | ContextInfo *ci = (ContextInfo *) ctx; | |
0a6de063 | 390 | FT_Face face = ci->face; |
115329f1 | 391 | FT_GlyphSlot slot = face->glyph; |
0a6de063 PG |
392 | unsigned char *text = ci->text; |
393 | unsigned char c; | |
394 | int x = 0, y = 0, i=0, size=0; | |
395 | unsigned char buff[MAXSIZE_TEXT]; | |
396 | unsigned char tbuff[MAXSIZE_TEXT]; | |
df4f9147 | 397 | time_t now = time(0); |
0a6de063 | 398 | int str_w, str_w_max; |
115329f1 | 399 | FT_Vector pos[MAXSIZE_TEXT]; |
0a6de063 PG |
400 | FT_Vector delta; |
401 | ||
115329f1 | 402 | if (ci->file) |
0a6de063 PG |
403 | { |
404 | int fd = open(ci->file, O_RDONLY); | |
115329f1 DB |
405 | |
406 | if (fd < 0) | |
bb270c08 DB |
407 | { |
408 | text = ci->text; | |
aaf78bde | 409 | av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be opened. Using text provided with -t switch: %s", strerror(errno)); |
bb270c08 | 410 | } |
115329f1 | 411 | else |
bb270c08 DB |
412 | { |
413 | int l = read(fd, tbuff, sizeof(tbuff) - 1); | |
414 | ||
415 | if (l >= 0) | |
416 | { | |
417 | tbuff[l] = 0; | |
418 | text = tbuff; | |
419 | } | |
420 | else | |
421 | { | |
422 | text = ci->text; | |
aaf78bde | 423 | av_log(NULL, AV_LOG_INFO, "WARNING: The file could not be read. Using text provided with -t switch: %s", strerror(errno)); |
bb270c08 DB |
424 | } |
425 | close(fd); | |
426 | } | |
0a6de063 PG |
427 | } |
428 | else | |
429 | { | |
430 | text = ci->text; | |
431 | } | |
df4f9147 PG |
432 | |
433 | strftime(buff, sizeof(buff), text, localtime(&now)); | |
434 | ||
435 | text = buff; | |
436 | ||
437 | size = strlen(text); | |
115329f1 | 438 | |
df4f9147 PG |
439 | |
440 | ||
0a6de063 PG |
441 | |
442 | /* measure string size and save glyphs position*/ | |
443 | str_w = str_w_max = 0; | |
115329f1 | 444 | x = ci->x; |
0a6de063 | 445 | y = ci->y; |
df4f9147 PG |
446 | for (i=0; i < size; i++) |
447 | { | |
0a6de063 | 448 | c = text[i]; |
df4f9147 | 449 | |
0a6de063 PG |
450 | /* kerning */ |
451 | if ( (ci->use_kerning) && (i > 0) && (ci->glyphs_index[c]) ) | |
bb270c08 DB |
452 | { |
453 | FT_Get_Kerning( ci->face, | |
454 | ci->glyphs_index[ text[i-1] ], | |
455 | ci->glyphs_index[c], | |
456 | ft_kerning_default, | |
457 | &delta ); | |
115329f1 | 458 | |
bb270c08 DB |
459 | x += delta.x >> 6; |
460 | } | |
115329f1 | 461 | |
0a6de063 | 462 | if (( (x + ci->advance[ c ]) >= width ) || ( c == '\n' )) |
bb270c08 DB |
463 | { |
464 | str_w = width - ci->x - 1; | |
0a6de063 | 465 | |
bb270c08 DB |
466 | y += ci->text_height; |
467 | x = ci->x; | |
468 | } | |
0a6de063 PG |
469 | |
470 | ||
471 | /* save position */ | |
472 | pos[i].x = x + ci->bitmap_left[c]; | |
473 | pos[i].y = y - ci->bitmap_top[c] + ci->baseline; | |
474 | ||
475 | ||
476 | x += ci->advance[c]; | |
477 | ||
478 | ||
479 | if (str_w > str_w_max) | |
bb270c08 | 480 | str_w_max = str_w; |
0a6de063 PG |
481 | |
482 | } | |
483 | ||
115329f1 | 484 | |
0a6de063 PG |
485 | |
486 | ||
487 | if (ci->bg) | |
488 | { | |
489 | /* Check if it doesn't pass the limits */ | |
490 | if ( str_w_max + ci->x >= width ) | |
bb270c08 | 491 | str_w_max = width - ci->x - 1; |
0a6de063 | 492 | if ( y >= height ) |
bb270c08 | 493 | y = height - 1 - 2*ci->y; |
0a6de063 PG |
494 | |
495 | /* Draw Background */ | |
115329f1 | 496 | draw_box( picture, ci->x, ci->y, str_w_max, y - ci->y, ci->bgcolor ); |
df4f9147 PG |
497 | } |
498 | ||
499 | ||
df4f9147 PG |
500 | |
501 | /* Draw Glyphs */ | |
502 | for (i=0; i < size; i++) | |
503 | { | |
0a6de063 PG |
504 | c = text[i]; |
505 | ||
506 | if ( | |
bb270c08 DB |
507 | ( (c == '_') && (text == ci->text) ) || /* skip '_' (consider as space) |
508 | IF text was specified in cmd line | |
509 | (which doesn't like neasted quotes) */ | |
510 | ( c == '\n' ) /* Skip new line char, just go to new line */ | |
511 | ) | |
512 | continue; | |
513 | ||
514 | /* now, draw to our target surface */ | |
515 | draw_glyph( picture, | |
516 | &(ci->bitmaps[ c ]), | |
517 | pos[i].x, | |
518 | pos[i].y, | |
519 | width, | |
520 | height, | |
521 | ci->fgcolor, | |
522 | ci->bgcolor, | |
523 | ci->outline ); | |
115329f1 | 524 | |
df4f9147 PG |
525 | /* increment pen position */ |
526 | x += slot->advance.x >> 6; | |
527 | } | |
528 | ||
529 | ||
530 | } | |
531 |