Mercurial > mplayer.hg
annotate gui/skin/font.c @ 33582:d9a4365d1006
gui: Rename TRANSPARENT #define to MP_TRANSPARENT.
TRANSPARENT is defined in windows.h and clashes for the Win32 GUI.
author | diego |
---|---|
date | Sun, 19 Jun 2011 17:33:11 +0000 |
parents | c5a19bbeac2b |
children | 34e85af9e80f |
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 |
32851 | 19 #include <gtk/gtk.h> |
33123
9566100d88a1
Replace inttypes.h by stdint.h and remove inttypes.h where unneeded.
ib
parents:
33082
diff
changeset
|
20 #include <stdint.h> |
23077 | 21 #include <stdlib.h> |
22 #include <string.h> | |
23 | |
24 #include "font.h" | |
32869 | 25 #include "gui/interface.h" |
33046 | 26 #include "gui/util/cut.h" |
33048 | 27 #include "gui/util/string.h" |
32869 | 28 #include "skin.h" |
29 | |
30 #include "libavutil/avstring.h" | |
26382
b2f4abcf20ed
Make include paths consistent; do not use ../ in them.
diego
parents:
26365
diff
changeset
|
31 #include "mp_msg.h" |
32869 | 32 |
33269 | 33 #define MAX_FONTS 25 |
34 | |
35 #define fntAlignLeft 0 | |
36 #define fntAlignCenter 1 | |
37 #define fntAlignRight 2 | |
38 | |
32869 | 39 static bmpFont *Fonts[MAX_FONTS]; |
23077 | 40 |
32869 | 41 static int fntAddNewFont(char *name) |
42 { | |
43 int id, i; | |
23077 | 44 |
32869 | 45 for (id = 0; id < MAX_FONTS; id++) |
46 if (!Fonts[id]) | |
47 break; | |
23077 | 48 |
32869 | 49 if (id == MAX_FONTS) |
50 return -2; | |
23077 | 51 |
32869 | 52 Fonts[id] = calloc(1, sizeof(*Fonts[id])); |
23077 | 53 |
32869 | 54 if (!Fonts[id]) |
55 return -1; | |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
56 |
32869 | 57 av_strlcpy(Fonts[id]->name, name, MAX_FONT_NAME); |
23077 | 58 |
32869 | 59 for (i = 0; i < ASCII_CHRS + EXTRA_CHRS; i++) { |
60 Fonts[id]->Fnt[i].x = -1; | |
61 Fonts[id]->Fnt[i].y = -1; | |
62 Fonts[id]->Fnt[i].sx = -1; | |
63 Fonts[id]->Fnt[i].sy = -1; | |
64 } | |
23077 | 65 |
32869 | 66 return id; |
23077 | 67 } |
68 | |
32869 | 69 void fntFreeFont(void) |
23077 | 70 { |
32869 | 71 int i; |
72 | |
73 for (i = 0; i < MAX_FONTS; i++) { | |
74 if (Fonts[i]) { | |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
75 bpFree(&Fonts[i]->Bitmap); |
32869 | 76 gfree((void **)&Fonts[i]); |
77 } | |
23077 | 78 } |
79 } | |
80 | |
32869 | 81 int fntRead(char *path, char *fname) |
23077 | 82 { |
32869 | 83 FILE *f; |
33082 | 84 unsigned char buf[512]; |
85 unsigned char item[32]; | |
32869 | 86 unsigned char param[256]; |
87 int id, n, i; | |
32817 | 88 |
32869 | 89 id = fntAddNewFont(fname); |
90 | |
91 if (id < 0) | |
92 return id; | |
93 | |
33082 | 94 av_strlcpy(buf, path, sizeof(buf)); |
95 av_strlcat(buf, fname, sizeof(buf)); | |
96 av_strlcat(buf, ".fnt", sizeof(buf)); | |
97 f = fopen(buf, "rt"); | |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
98 |
32869 | 99 if (!f) { |
100 gfree((void **)&Fonts[id]); | |
101 return -3; | |
102 } | |
32839
2dd39155f320
Cosmetic: Make conditions more readable by having assignments outside.
ib
parents:
32838
diff
changeset
|
103 |
33082 | 104 while (fgets(buf, sizeof(buf), f)) { |
105 buf[strcspn(buf, "\n\r")] = 0; // remove any kind of newline, if any | |
106 strswap(buf, '\t', ' '); | |
107 trim(buf); | |
108 decomment(buf); | |
32869 | 109 |
33082 | 110 if (!*buf) |
32869 | 111 continue; |
112 | |
33082 | 113 n = (strncmp(buf, "\"=", 2) == 0 ? 1 : 0); |
114 cutItem(buf, item, '=', n); | |
115 cutItem(buf, param, '=', n + 1); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
116 |
33082 | 117 if (item[0] == '"') { |
118 if (!item[1]) | |
119 item[0] = '='; | |
120 else if (item[1] == '"') | |
121 item[1] = 0; | |
32869 | 122 else |
33082 | 123 cutItem(item, item, '"', 1); |
32869 | 124 |
33082 | 125 if (item[0] & 0x80) { |
32869 | 126 for (i = 0; i < EXTRA_CHRS; i++) { |
127 if (!Fonts[id]->nonASCIIidx[i][0]) { | |
33082 | 128 strncpy(Fonts[id]->nonASCIIidx[i], item, UTF8LENGTH); |
32869 | 129 break; |
130 } | |
131 } | |
132 | |
133 if (i == EXTRA_CHRS) | |
134 continue; | |
135 | |
136 i += ASCII_CHRS; | |
137 } else | |
33082 | 138 i = item[0]; |
32869 | 139 |
33082 | 140 cutItem(param, buf, ',', 0); |
141 Fonts[id]->Fnt[i].x = atoi(buf); | |
32869 | 142 |
33082 | 143 cutItem(param, buf, ',', 1); |
144 Fonts[id]->Fnt[i].y = atoi(buf); | |
32869 | 145 |
33082 | 146 cutItem(param, buf, ',', 2); |
147 Fonts[id]->Fnt[i].sx = atoi(buf); | |
32869 | 148 |
33082 | 149 cutItem(param, buf, ',', 3); |
150 Fonts[id]->Fnt[i].sy = atoi(buf); | |
32869 | 151 |
33082 | 152 mp_dbg(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].sx, Fonts[id]->Fnt[i].sy); |
153 } else if (!strcmp(item, "image")) { | |
154 av_strlcpy(buf, path, sizeof(buf)); | |
155 av_strlcat(buf, param, sizeof(buf)); | |
32869 | 156 |
33082 | 157 mp_dbg(MSGT_GPLAYER, MSGL_DBG2, "[font] image file: %s\n", buf); |
32869 | 158 |
33082 | 159 if (skinBPRead(buf, &Fonts[id]->Bitmap) != 0) { |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
160 bpFree(&Fonts[id]->Bitmap); |
32869 | 161 gfree((void **)&Fonts[id]); |
162 fclose(f); | |
163 return -4; | |
164 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
165 } |
23077 | 166 } |
167 | |
32869 | 168 fclose(f); |
33053 | 169 |
32869 | 170 return 0; |
23077 | 171 } |
172 | |
32869 | 173 int fntFindID(char *name) |
23077 | 174 { |
32869 | 175 int i; |
176 | |
177 for (i = 0; i < MAX_FONTS; i++) | |
178 if (Fonts[i]) | |
179 if (!strcmp(name, Fonts[i]->name)) | |
180 return i; | |
181 | |
182 return -1; | |
23077 | 183 } |
184 | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
185 // get Fnt index of character (utf8 or normal one) *str points to, |
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
186 // then move pointer to next/previous character |
32869 | 187 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
|
188 { |
32869 | 189 unsigned char *p, uchar[6] = ""; // glib implements 31-bit UTF-8 |
190 int i, c = -1; | |
191 | |
192 if (**str & 0x80) { | |
193 if (utf8) { | |
194 p = *str; | |
195 *str = g_utf8_next_char(*str); | |
196 strncpy(uchar, p, *str - p); | |
197 | |
198 if (direction < 0) | |
199 *str = g_utf8_prev_char(p); | |
200 } else { | |
201 uchar[0] = **str; | |
202 *str += direction; | |
203 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
204 |
32869 | 205 for (i = 0; (i < EXTRA_CHRS) && Fonts[id]->nonASCIIidx[i][0]; i++) { |
206 if (strncmp(Fonts[id]->nonASCIIidx[i], uchar, UTF8LENGTH) == 0) | |
207 return i + ASCII_CHRS; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
208 |
32869 | 209 if (!utf8 && |
210 (Fonts[id]->nonASCIIidx[i][0] == (*uchar >> 6 | 0xc0) && | |
211 Fonts[id]->nonASCIIidx[i][1] == ((*uchar & 0x3f) | 0x80) && | |
212 Fonts[id]->nonASCIIidx[i][2] == 0)) | |
213 c = i + ASCII_CHRS; | |
214 } | |
215 } else { | |
216 c = **str; | |
217 | |
218 if (utf8 && (direction < 0)) | |
219 *str = g_utf8_prev_char(*str); | |
220 else | |
221 *str += direction; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
222 } |
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
223 |
32869 | 224 return c; |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
225 } |
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
226 |
32869 | 227 int fntTextWidth(int id, char *str) |
23077 | 228 { |
32869 | 229 int size = 0, c; |
230 gboolean utf8; | |
231 unsigned char *p; | |
232 | |
233 utf8 = g_utf8_validate(str, -1, NULL); | |
234 p = str; | |
23077 | 235 |
32869 | 236 while (*p) { |
237 c = fntGetCharIndex(id, &p, utf8, 1); | |
238 | |
239 if (c == -1 || Fonts[id]->Fnt[c].sx == -1) | |
240 c = ' '; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
241 |
32869 | 242 if (Fonts[id]->Fnt[c].sx != -1) |
243 size += Fonts[id]->Fnt[c].sx; | |
244 } | |
245 | |
246 return size; | |
23077 | 247 } |
248 | |
32869 | 249 static int fntTextHeight(int id, char *str) |
23077 | 250 { |
32869 | 251 int max = 0, c, h; |
252 gboolean utf8; | |
253 unsigned char *p; | |
23077 | 254 |
32869 | 255 utf8 = g_utf8_validate(str, -1, NULL); |
256 p = str; | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
257 |
32869 | 258 while (*p) { |
259 c = fntGetCharIndex(id, &p, utf8, 1); | |
260 | |
261 if (c == -1 || Fonts[id]->Fnt[c].sx == -1) | |
262 c = ' '; | |
263 | |
264 h = Fonts[id]->Fnt[c].sy; | |
265 | |
266 if (h > max) | |
267 max = h; | |
268 } | |
269 | |
270 return max; | |
23077 | 271 } |
272 | |
33555 | 273 guiImage *fntRender(wItem *item, int px, char *txt) |
23077 | 274 { |
32869 | 275 unsigned char *u; |
276 unsigned int i; | |
277 int c, dx, tw, th, fbw, iw, id, ofs; | |
278 int x, y, fh, fw, fyc, yc; | |
279 uint32_t *ibuf; | |
280 uint32_t *obuf; | |
281 gboolean utf8; | |
23077 | 282 |
32869 | 283 id = item->fontid; |
284 tw = fntTextWidth(id, txt); | |
23077 | 285 |
32869 | 286 if (!tw) |
287 return NULL; | |
23077 | 288 |
32869 | 289 iw = item->width; |
290 fbw = Fonts[id]->Bitmap.Width; | |
291 th = fntTextHeight(id, txt); | |
292 | |
293 if (item->height != th) | |
32917
9949f3a123cf
Add new function bpFree() to free txSamples (bitmaps).
ib
parents:
32869
diff
changeset
|
294 bpFree(&item->Bitmap); |
23077 | 295 |
32869 | 296 if (!item->Bitmap.Image) { |
297 item->Bitmap.Height = item->height = th; | |
298 item->Bitmap.Width = item->width = iw; | |
299 item->Bitmap.ImageSize = item->height * iw * 4; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
300 |
32869 | 301 if (!item->Bitmap.ImageSize) |
302 return NULL; | |
303 | |
33555 | 304 item->Bitmap.Bpp = 32; |
32869 | 305 item->Bitmap.Image = malloc(item->Bitmap.ImageSize); |
306 | |
307 if (!item->Bitmap.Image) | |
308 return NULL; | |
23077 | 309 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
310 |
32869 | 311 obuf = (uint32_t *)item->Bitmap.Image; |
312 ibuf = (uint32_t *)Fonts[id]->Bitmap.Image; | |
23077 | 313 |
32869 | 314 for (i = 0; i < item->Bitmap.ImageSize / 4; i++) |
33582 | 315 obuf[i] = MP_TRANSPARENT; |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
316 |
32869 | 317 if (tw <= iw) { |
318 switch (item->align) { | |
319 default: | |
320 case fntAlignLeft: | |
321 dx = 0; | |
322 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
323 |
32869 | 324 case fntAlignCenter: |
325 dx = (iw - tw) / 2; | |
326 break; | |
32792
31ce0bd110d5
Only replace non-existing font character by space if space itself exists.
ib
parents:
32791
diff
changeset
|
327 |
32869 | 328 case fntAlignRight: |
329 dx = iw - tw; | |
330 break; | |
331 } | |
332 } else | |
333 dx = px; | |
334 | |
335 ofs = dx; | |
336 | |
337 utf8 = g_utf8_validate(txt, -1, NULL); | |
338 u = txt; | |
339 | |
340 while (*u) { | |
341 c = fntGetCharIndex(id, &u, utf8, 1); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
342 |
32869 | 343 if (c != -1) |
344 fw = Fonts[id]->Fnt[c].sx; | |
345 | |
346 if (c == -1 || fw == -1) { | |
347 c = ' '; | |
348 fw = Fonts[id]->Fnt[c].sx; | |
349 } | |
350 | |
351 if (fw == -1) | |
352 continue; | |
353 | |
354 fh = Fonts[id]->Fnt[c].sy; | |
355 fyc = Fonts[id]->Fnt[c].y * fbw + Fonts[id]->Fnt[c].x; | |
356 yc = dx; | |
23077 | 357 |
32869 | 358 if (dx >= 0) { |
359 for (y = 0; y < fh; y++) { | |
360 for (x = 0; x < fw; x++) | |
361 if (dx + x >= 0 && dx + x < iw) | |
362 obuf[yc + x] = ibuf[fyc + x]; | |
363 | |
364 fyc += fbw; | |
365 yc += iw; | |
366 } | |
367 } | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
368 |
32869 | 369 dx += fw; |
370 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26458
diff
changeset
|
371 |
32869 | 372 if (ofs > 0 && tw > item->width) { |
373 dx = ofs; | |
374 u = txt + strlen(txt); | |
32734
cc58a1e919d9
Allow character in the font description file to be in UTF-8.
ib
parents:
32712
diff
changeset
|
375 |
32869 | 376 while (u > (unsigned char *)txt) { |
377 c = fntGetCharIndex(id, &u, utf8, -1); | |
23077 | 378 |
32869 | 379 if (c != -1) |
380 fw = Fonts[id]->Fnt[c].sx; | |
32792
31ce0bd110d5
Only replace non-existing font character by space if space itself exists.
ib
parents:
32791
diff
changeset
|
381 |
32869 | 382 if (c == -1 || fw == -1) { |
383 c = ' '; | |
384 fw = Fonts[id]->Fnt[c].sx; | |
385 } | |
386 | |
387 if (fw == -1) | |
388 continue; | |
389 | |
390 fh = Fonts[id]->Fnt[c].sy; | |
391 fyc = Fonts[id]->Fnt[c].y * fbw + Fonts[id]->Fnt[c].x; | |
392 | |
393 dx -= fw; | |
394 yc = dx; | |
23077 | 395 |
32869 | 396 if (dx >= 0) { |
397 for (y = 0; y < fh; y++) { | |
398 for (x = fw - 1; x >= 0; x--) | |
399 if (dx + x >= 0 && dx + x < iw) | |
400 obuf[yc + x] = ibuf[fyc + x]; | |
401 | |
402 fyc += fbw; | |
403 yc += iw; | |
404 } | |
405 } | |
406 } | |
23077 | 407 } |
408 | |
32869 | 409 return &item->Bitmap; |
23077 | 410 } |