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