Mercurial > mplayer.hg
annotate gui/skin/font.c @ 36989:0b80003f6542
Relocate the cut functions.
Put them into the string functions file.
author | ib |
---|---|
date | Thu, 27 Mar 2014 09:15:47 +0000 |
parents | c17e58ec1e65 |
children | fa8b6892b0bf |
rev | line source |
---|---|
26458 | 1 /* |
2 * This file is part of MPlayer. | |
3 * | |
4 * MPlayer is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; either version 2 of the License, or | |
7 * (at your option) any later version. | |
8 * | |
9 * MPlayer is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License along | |
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
17 */ | |
23077 | 18 |
33973 | 19 /** |
20 * @file | |
21 * @brief Font file parser and font rendering | |
22 */ | |
23 | |
36013 | 24 #include <glib.h> |
33123
9566100d88a1
Replace inttypes.h by stdint.h and remove inttypes.h where unneeded.
ib
parents:
33082
diff
changeset
|
25 #include <stdint.h> |
23077 | 26 #include <stdlib.h> |
27 #include <string.h> | |
28 | |
29 #include "font.h" | |
35530 | 30 #include "skin.h" |
33739 | 31 #include "gui/util/mem.h" |
33048 | 32 #include "gui/util/string.h" |
32869 | 33 |
36032 | 34 #include "mp_msg.h" |
32869 | 35 #include "libavutil/avstring.h" |
36 | |
33269 | 37 #define MAX_FONTS 25 |
38 | |
39 #define fntAlignLeft 0 | |
40 #define fntAlignCenter 1 | |
41 #define fntAlignRight 2 | |
42 | |
32869 | 43 static bmpFont *Fonts[MAX_FONTS]; |
23077 | 44 |
33973 | 45 /** |
46 * @brief Add a font to #Fonts. | |
47 * | |
48 * @param name name of the font | |
49 * | |
50 * @return an identification >= 0 (ok), -1 (out of memory) or -2 (#MAX_FONTS exceeded) | |
51 */ | |
32869 | 52 static int fntAddNewFont(char *name) |
53 { | |
54 int id, i; | |
23077 | 55 |
32869 | 56 for (id = 0; id < MAX_FONTS; id++) |
57 if (!Fonts[id]) | |
58 break; | |
23077 | 59 |
32869 | 60 if (id == MAX_FONTS) |
61 return -2; | |
23077 | 62 |
32869 | 63 Fonts[id] = calloc(1, sizeof(*Fonts[id])); |
23077 | 64 |
32869 | 65 if (!Fonts[id]) |
66 return -1; | |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
67 |
32869 | 68 av_strlcpy(Fonts[id]->name, name, MAX_FONT_NAME); |
23077 | 69 |
32869 | 70 for (i = 0; i < ASCII_CHRS + EXTRA_CHRS; i++) { |
36983 | 71 Fonts[id]->Fnt[i].x = -1; |
72 Fonts[id]->Fnt[i].y = -1; | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
73 Fonts[id]->Fnt[i].w = -1; |
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
74 Fonts[id]->Fnt[i].h = -1; |
32869 | 75 } |
23077 | 76 |
32869 | 77 return id; |
23077 | 78 } |
79 | |
33973 | 80 /** |
81 * @brief Free all memory allocated to fonts. | |
82 */ | |
32869 | 83 void fntFreeFont(void) |
23077 | 84 { |
32869 | 85 int i; |
86 | |
87 for (i = 0; i < MAX_FONTS; i++) { | |
88 if (Fonts[i]) { | |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
89 bpFree(&Fonts[i]->Bitmap); |
33739 | 90 nfree(Fonts[i]); |
32869 | 91 } |
23077 | 92 } |
93 } | |
94 | |
33973 | 95 /** |
96 * @brief Read and parse a font file. | |
97 * | |
98 * @param path directory the font file is in | |
99 * @param fname name of the font | |
100 * | |
101 * @return 0 (ok), -1 or -2 (return code of #fntAddNewFont()), | |
102 * -3 (file error) or -4 (#skinImageRead() error) | |
103 */ | |
32869 | 104 int fntRead(char *path, char *fname) |
23077 | 105 { |
34578 | 106 FILE *file; |
33082 | 107 unsigned char buf[512]; |
108 unsigned char item[32]; | |
32869 | 109 unsigned char param[256]; |
110 int id, n, i; | |
32817 | 111 |
32869 | 112 id = fntAddNewFont(fname); |
113 | |
114 if (id < 0) | |
115 return id; | |
116 | |
33082 | 117 av_strlcpy(buf, path, sizeof(buf)); |
118 av_strlcat(buf, fname, sizeof(buf)); | |
119 av_strlcat(buf, ".fnt", sizeof(buf)); | |
34578 | 120 file = fopen(buf, "rt"); |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
121 |
34578 | 122 if (!file) { |
33739 | 123 nfree(Fonts[id]); |
32869 | 124 return -3; |
125 } | |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
126 |
34578 | 127 while (fgetstr(buf, sizeof(buf), file)) { |
33082 | 128 strswap(buf, '\t', ' '); |
129 trim(buf); | |
130 decomment(buf); | |
32869 | 131 |
33082 | 132 if (!*buf) |
32869 | 133 continue; |
134 | |
33082 | 135 n = (strncmp(buf, "\"=", 2) == 0 ? 1 : 0); |
136 cutItem(buf, item, '=', n); | |
137 cutItem(buf, param, '=', n + 1); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
138 |
33082 | 139 if (item[0] == '"') { |
140 if (!item[1]) | |
141 item[0] = '='; | |
142 else if (item[1] == '"') | |
143 item[1] = 0; | |
32869 | 144 else |
33082 | 145 cutItem(item, item, '"', 1); |
32869 | 146 |
33082 | 147 if (item[0] & 0x80) { |
32869 | 148 for (i = 0; i < EXTRA_CHRS; i++) { |
149 if (!Fonts[id]->nonASCIIidx[i][0]) { | |
33082 | 150 strncpy(Fonts[id]->nonASCIIidx[i], item, UTF8LENGTH); |
32869 | 151 break; |
152 } | |
153 } | |
154 | |
155 if (i == EXTRA_CHRS) | |
156 continue; | |
157 | |
158 i += ASCII_CHRS; | |
159 } else | |
33082 | 160 i = item[0]; |
32869 | 161 |
33082 | 162 cutItem(param, buf, ',', 0); |
163 Fonts[id]->Fnt[i].x = atoi(buf); | |
32869 | 164 |
33082 | 165 cutItem(param, buf, ',', 1); |
166 Fonts[id]->Fnt[i].y = atoi(buf); | |
32869 | 167 |
33082 | 168 cutItem(param, buf, ',', 2); |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
169 Fonts[id]->Fnt[i].w = atoi(buf); |
32869 | 170 |
33082 | 171 cutItem(param, buf, ',', 3); |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
172 Fonts[id]->Fnt[i].h = atoi(buf); |
32869 | 173 |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
174 mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[font] char: '%s' params: %d,%d %dx%d\n", item, Fonts[id]->Fnt[i].x, Fonts[id]->Fnt[i].y, Fonts[id]->Fnt[i].w, Fonts[id]->Fnt[i].h); |
33082 | 175 } else if (!strcmp(item, "image")) { |
176 av_strlcpy(buf, path, sizeof(buf)); | |
177 av_strlcat(buf, param, sizeof(buf)); | |
32869 | 178 |
33985 | 179 mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[font] image file: %s\n", buf); |
32869 | 180 |
33969 | 181 if (skinImageRead(buf, &Fonts[id]->Bitmap) != 0) { |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
182 bpFree(&Fonts[id]->Bitmap); |
33739 | 183 nfree(Fonts[id]); |
34578 | 184 fclose(file); |
32869 | 185 return -4; |
186 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
187 } |
23077 | 188 } |
189 | |
34578 | 190 fclose(file); |
33053 | 191 |
32869 | 192 return 0; |
23077 | 193 } |
194 | |
33973 | 195 /** |
196 * @brief Find the ID of a font by its name. | |
197 * | |
198 * @param name name of the font | |
199 * | |
200 * @return an identification >= 0 (ok) or -1 (not found) | |
201 */ | |
32869 | 202 int fntFindID(char *name) |
23077 | 203 { |
32869 | 204 int i; |
205 | |
206 for (i = 0; i < MAX_FONTS; i++) | |
207 if (Fonts[i]) | |
208 if (!strcmp(name, Fonts[i]->name)) | |
209 return i; | |
210 | |
211 return -1; | |
23077 | 212 } |
213 | |
33973 | 214 /** |
215 * @brief Get the #bmpFont::Fnt index of the character @a *str points to. | |
216 * | |
217 * Move pointer @a *str to the character according to @a direction | |
218 * afterwards. | |
219 * | |
220 * @param id font ID | |
221 * @param str pointer to the string | |
222 * @param uft8 flag indicating whether @a str contains UTF-8 characters | |
223 * @param direction +1 (forward) or -1 (backward) | |
224 * | |
225 * @return index >= 0 (ok) or -1 (not found) | |
226 */ | |
32869 | 227 static int fntGetCharIndex(int id, unsigned char **str, gboolean utf8, int direction) |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
228 { |
32869 | 229 unsigned char *p, uchar[6] = ""; // glib implements 31-bit UTF-8 |
230 int i, c = -1; | |
231 | |
232 if (**str & 0x80) { | |
233 if (utf8) { | |
234 p = *str; | |
235 *str = g_utf8_next_char(*str); | |
236 strncpy(uchar, p, *str - p); | |
237 | |
238 if (direction < 0) | |
239 *str = g_utf8_prev_char(p); | |
240 } else { | |
241 uchar[0] = **str; | |
242 *str += direction; | |
243 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
244 |
32869 | 245 for (i = 0; (i < EXTRA_CHRS) && Fonts[id]->nonASCIIidx[i][0]; i++) { |
246 if (strncmp(Fonts[id]->nonASCIIidx[i], uchar, UTF8LENGTH) == 0) | |
247 return i + ASCII_CHRS; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
248 |
32869 | 249 if (!utf8 && |
250 (Fonts[id]->nonASCIIidx[i][0] == (*uchar >> 6 | 0xc0) && | |
251 Fonts[id]->nonASCIIidx[i][1] == ((*uchar & 0x3f) | 0x80) && | |
252 Fonts[id]->nonASCIIidx[i][2] == 0)) | |
253 c = i + ASCII_CHRS; | |
254 } | |
255 } else { | |
256 c = **str; | |
257 | |
258 if (utf8 && (direction < 0)) | |
259 *str = g_utf8_prev_char(*str); | |
260 else | |
261 *str += direction; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
262 } |
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
263 |
32869 | 264 return c; |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
265 } |
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
266 |
33973 | 267 /** |
268 * @brief Get the rendering width of a text. | |
269 * | |
270 * @param id font ID | |
271 * @param str string to be examined | |
272 * | |
273 * @return width of the rendered string (in pixels) | |
274 */ | |
32869 | 275 int fntTextWidth(int id, char *str) |
23077 | 276 { |
32869 | 277 int size = 0, c; |
278 gboolean utf8; | |
279 unsigned char *p; | |
280 | |
281 utf8 = g_utf8_validate(str, -1, NULL); | |
282 p = str; | |
23077 | 283 |
32869 | 284 while (*p) { |
285 c = fntGetCharIndex(id, &p, utf8, 1); | |
286 | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
287 if (c == -1 || Fonts[id]->Fnt[c].w == -1) |
32869 | 288 c = ' '; |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
289 |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
290 if (Fonts[id]->Fnt[c].w != -1) |
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
291 size += Fonts[id]->Fnt[c].w; |
32869 | 292 } |
293 | |
294 return size; | |
23077 | 295 } |
296 | |
33973 | 297 /** |
298 * @brief Get the rendering height of a text. | |
299 * | |
300 * @param id font ID | |
301 * @param str string to be examined | |
302 * | |
303 * @return height of the rendered string (in pixels) | |
304 */ | |
32869 | 305 static int fntTextHeight(int id, char *str) |
23077 | 306 { |
32869 | 307 int max = 0, c, h; |
308 gboolean utf8; | |
309 unsigned char *p; | |
23077 | 310 |
32869 | 311 utf8 = g_utf8_validate(str, -1, NULL); |
312 p = str; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
313 |
32869 | 314 while (*p) { |
315 c = fntGetCharIndex(id, &p, utf8, 1); | |
316 | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
317 if (c == -1 || Fonts[id]->Fnt[c].w == -1) |
32869 | 318 c = ' '; |
319 | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
320 h = Fonts[id]->Fnt[c].h; |
32869 | 321 |
322 if (h > max) | |
323 max = h; | |
324 } | |
325 | |
326 return max; | |
23077 | 327 } |
328 | |
33973 | 329 /** |
330 * @brief Render a text on an item. | |
331 * | |
332 * @param item item the text shall be placed on | |
333 * @param px x position for the text in case it is wider than the item width | |
334 * @param txt text to be rendered | |
335 * | |
336 * @return image containing the rendered text | |
337 */ | |
35688 | 338 guiImage *fntTextRender(guiItem *item, int px, char *txt) |
23077 | 339 { |
32869 | 340 unsigned char *u; |
341 unsigned int i; | |
342 int c, dx, tw, th, fbw, iw, id, ofs; | |
343 int x, y, fh, fw, fyc, yc; | |
344 uint32_t *ibuf; | |
345 uint32_t *obuf; | |
346 gboolean utf8; | |
23077 | 347 |
32869 | 348 id = item->fontid; |
349 tw = fntTextWidth(id, txt); | |
23077 | 350 |
32869 | 351 if (!tw) |
352 return NULL; | |
23077 | 353 |
32869 | 354 iw = item->width; |
355 fbw = Fonts[id]->Bitmap.Width; | |
356 th = fntTextHeight(id, txt); | |
357 | |
358 if (item->height != th) | |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
359 bpFree(&item->Bitmap); |
23077 | 360 |
32869 | 361 if (!item->Bitmap.Image) { |
362 item->Bitmap.Height = item->height = th; | |
363 item->Bitmap.Width = item->width = iw; | |
364 item->Bitmap.ImageSize = item->height * iw * 4; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
365 |
32869 | 366 if (!item->Bitmap.ImageSize) |
367 return NULL; | |
368 | |
33555 | 369 item->Bitmap.Bpp = 32; |
32869 | 370 item->Bitmap.Image = malloc(item->Bitmap.ImageSize); |
371 | |
372 if (!item->Bitmap.Image) | |
373 return NULL; | |
23077 | 374 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
375 |
32869 | 376 obuf = (uint32_t *)item->Bitmap.Image; |
377 ibuf = (uint32_t *)Fonts[id]->Bitmap.Image; | |
23077 | 378 |
32869 | 379 for (i = 0; i < item->Bitmap.ImageSize / 4; i++) |
33731
81f71d910333
Cosmetic: Change prefix for symbolic constants from GMP to GUI.
ib
parents:
33728
diff
changeset
|
380 obuf[i] = GUI_TRANSPARENT; |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
381 |
32869 | 382 if (tw <= iw) { |
383 switch (item->align) { | |
384 default: | |
385 case fntAlignLeft: | |
386 dx = 0; | |
387 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
388 |
32869 | 389 case fntAlignCenter: |
390 dx = (iw - tw) / 2; | |
391 break; | |
32792
31ce0bd110d5
Only replace non-existing font character by space if space itself exists.
ib
parents:
32791
diff
changeset
|
392 |
32869 | 393 case fntAlignRight: |
394 dx = iw - tw; | |
395 break; | |
396 } | |
397 } else | |
398 dx = px; | |
399 | |
400 ofs = dx; | |
401 | |
402 utf8 = g_utf8_validate(txt, -1, NULL); | |
403 u = txt; | |
404 | |
405 while (*u) { | |
406 c = fntGetCharIndex(id, &u, utf8, 1); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
407 |
32869 | 408 if (c != -1) |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
409 fw = Fonts[id]->Fnt[c].w; |
32869 | 410 |
411 if (c == -1 || fw == -1) { | |
412 c = ' '; | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
413 fw = Fonts[id]->Fnt[c].w; |
32869 | 414 } |
415 | |
416 if (fw == -1) | |
417 continue; | |
418 | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
419 fh = Fonts[id]->Fnt[c].h; |
32869 | 420 fyc = Fonts[id]->Fnt[c].y * fbw + Fonts[id]->Fnt[c].x; |
421 yc = dx; | |
23077 | 422 |
32869 | 423 if (dx >= 0) { |
424 for (y = 0; y < fh; y++) { | |
425 for (x = 0; x < fw; x++) | |
426 if (dx + x >= 0 && dx + x < iw) | |
427 obuf[yc + x] = ibuf[fyc + x]; | |
428 | |
429 fyc += fbw; | |
430 yc += iw; | |
431 } | |
432 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
433 |
32869 | 434 dx += fw; |
435 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
436 |
32869 | 437 if (ofs > 0 && tw > item->width) { |
438 dx = ofs; | |
439 u = txt + strlen(txt); | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
440 |
32869 | 441 while (u > (unsigned char *)txt) { |
442 c = fntGetCharIndex(id, &u, utf8, -1); | |
23077 | 443 |
32869 | 444 if (c != -1) |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
445 fw = Fonts[id]->Fnt[c].w; |
32792
31ce0bd110d5
Only replace non-existing font character by space if space itself exists.
ib
parents:
32791
diff
changeset
|
446 |
32869 | 447 if (c == -1 || fw == -1) { |
448 c = ' '; | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
449 fw = Fonts[id]->Fnt[c].w; |
32869 | 450 } |
451 | |
452 if (fw == -1) | |
453 continue; | |
454 | |
36982
896b8c73943e
Cosmetic: Rename fntChar members for width and height.
ib
parents:
36032
diff
changeset
|
455 fh = Fonts[id]->Fnt[c].h; |
32869 | 456 fyc = Fonts[id]->Fnt[c].y * fbw + Fonts[id]->Fnt[c].x; |
457 | |
458 dx -= fw; | |
459 yc = dx; | |
23077 | 460 |
32869 | 461 if (dx >= 0) { |
462 for (y = 0; y < fh; y++) { | |
463 for (x = fw - 1; x >= 0; x--) | |
464 if (dx + x >= 0 && dx + x < iw) | |
465 obuf[yc + x] = ibuf[fyc + x]; | |
466 | |
467 fyc += fbw; | |
468 yc += iw; | |
469 } | |
470 } | |
471 } | |
23077 | 472 } |
473 | |
32869 | 474 return &item->Bitmap; |
23077 | 475 } |