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