Mercurial > emacs
comparison src/font.c @ 95790:a486132d892c
(font_parse_fcname): Accept GTK-style font names too.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Tue, 10 Jun 2008 20:01:06 +0000 |
parents | b490fda95b13 |
children | 27e773c9952b |
comparison
equal
deleted
inserted
replaced
95789:2d4b2068b7ec | 95790:a486132d892c |
---|---|
1321 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX], | 1321 f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX], |
1322 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX], | 1322 f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX], |
1323 f[XLFD_REGISTRY_INDEX]); | 1323 f[XLFD_REGISTRY_INDEX]); |
1324 } | 1324 } |
1325 | 1325 |
1326 /* Parse NAME (null terminated) as Fonconfig's name format and store | 1326 /* Parse NAME (null terminated) and store information in FONT |
1327 information in FONT (font-spec or font-entity). If NAME is | 1327 (font-spec or font-entity). NAME is supplied in either the |
1328 successfully parsed, return 0. Otherwise return -1. */ | 1328 Fontconfig or GTK font name format. If NAME is successfully |
1329 parsed, return 0. Otherwise return -1. | |
1330 | |
1331 The fontconfig format is | |
1332 | |
1333 FAMILY[-SIZE][:PROP1[=VAL1][:PROP2[=VAL2]...]] | |
1334 | |
1335 The GTK format is | |
1336 | |
1337 FAMILY [PROPS...] [SIZE] | |
1338 | |
1339 This function tries to guess which format it is. */ | |
1329 | 1340 |
1330 int | 1341 int |
1331 font_parse_fcname (name, font) | 1342 font_parse_fcname (name, font) |
1332 char *name; | 1343 char *name; |
1333 Lisp_Object font; | 1344 Lisp_Object font; |
1334 { | 1345 { |
1335 char *p0, *p1; | 1346 char *p, *q; |
1347 char *size_beg = NULL, *size_end = NULL; | |
1348 char *props_beg = NULL, *family_end = NULL; | |
1336 int len = strlen (name); | 1349 int len = strlen (name); |
1337 char *copy; | |
1338 | 1350 |
1339 if (len == 0) | 1351 if (len == 0) |
1340 return -1; | 1352 return -1; |
1341 /* It is assured that (name[0] && name[0] != '-'). */ | 1353 |
1342 if (name[0] == ':') | 1354 for (p = name; *p; p++) |
1343 p0 = name; | 1355 { |
1356 if (*p == '\\' && p[1]) | |
1357 p++; | |
1358 else if (*p == ':') | |
1359 { | |
1360 family_end = p; | |
1361 props_beg = p + 1; | |
1362 break; | |
1363 } | |
1364 else if (*p == '-') | |
1365 { | |
1366 int size_found = 1; | |
1367 for (q = p + 1; *q && *q != ':'; q++) | |
1368 if (! isdigit(*q)) | |
1369 { | |
1370 size_found = 0; | |
1371 break; | |
1372 } | |
1373 if (size_found) | |
1374 { | |
1375 family_end = p; | |
1376 size_beg = p + 1; | |
1377 size_end = q; | |
1378 break; | |
1379 } | |
1380 } | |
1381 } | |
1382 | |
1383 if (family_end) | |
1384 { | |
1385 /* A fontconfig name with size and/or property data. */ | |
1386 if (family_end > name) | |
1387 { | |
1388 Lisp_Object family; | |
1389 family = font_intern_prop (name, family_end - name, 1); | |
1390 ASET (font, FONT_FAMILY_INDEX, family); | |
1391 } | |
1392 if (size_beg) | |
1393 { | |
1394 double point_size = strtod (size_beg, &size_end); | |
1395 ASET (font, FONT_SIZE_INDEX, make_float (point_size)); | |
1396 if (*size_end == ':' && size_end[1]) | |
1397 props_beg = size_end + 1; | |
1398 } | |
1399 if (props_beg) | |
1400 { | |
1401 /* Now parse ":KEY=VAL" patterns. Store known keys and values in | |
1402 extra, copy unknown ones to COPY. It is stored in extra slot by | |
1403 the key QCfc_unknown_spec. */ | |
1404 char *copy; | |
1405 | |
1406 name = copy = alloca (name + len - props_beg); | |
1407 if (! copy) | |
1408 return -1; | |
1409 | |
1410 p = props_beg; | |
1411 while (*p) | |
1412 { | |
1413 Lisp_Object val; | |
1414 int word_len, prop; | |
1415 | |
1416 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0) | |
1417 | |
1418 for (q = p + 1; *q && *q != '=' && *q != ':'; q++); | |
1419 word_len = q - p; | |
1420 if (*q != '=') | |
1421 { | |
1422 /* Must be an enumerated value. */ | |
1423 val = font_intern_prop (p, q - p, 1); | |
1424 if (PROP_MATCH ("light", 5) | |
1425 || PROP_MATCH ("medium", 6) | |
1426 || PROP_MATCH ("demibold", 8) | |
1427 || PROP_MATCH ("bold", 4) | |
1428 || PROP_MATCH ("black", 5)) | |
1429 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val); | |
1430 else if (PROP_MATCH ("roman", 5) | |
1431 || PROP_MATCH ("italic", 6) | |
1432 || PROP_MATCH ("oblique", 7)) | |
1433 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val); | |
1434 else if (PROP_MATCH ("charcell", 8)) | |
1435 ASET (font, FONT_SPACING_INDEX, | |
1436 make_number (FONT_SPACING_CHARCELL)); | |
1437 else if (PROP_MATCH ("mono", 4)) | |
1438 ASET (font, FONT_SPACING_INDEX, | |
1439 make_number (FONT_SPACING_MONO)); | |
1440 else if (PROP_MATCH ("proportional", 12)) | |
1441 ASET (font, FONT_SPACING_INDEX, | |
1442 make_number (FONT_SPACING_PROPORTIONAL)); | |
1443 else | |
1444 { | |
1445 /* Unknown key */ | |
1446 bcopy (p, copy, word_len); | |
1447 copy += word_len; | |
1448 } | |
1449 } | |
1450 else /* KEY=VAL pairs */ | |
1451 { | |
1452 Lisp_Object key; | |
1453 char *keyhead = p; | |
1454 | |
1455 if (PROP_MATCH ("pixelsize=", 10)) | |
1456 prop = FONT_SIZE_INDEX; | |
1457 else | |
1458 { | |
1459 key = font_intern_prop (p, q - p, 1); | |
1460 prop = get_font_prop_index (key); | |
1461 } | |
1462 p = q + 1; | |
1463 for (q = p; *q && *q != ':'; q++); | |
1464 | |
1465 val = font_intern_prop (p, word_len, 0); | |
1466 if (! NILP (val)) | |
1467 { | |
1468 if (prop >= FONT_FOUNDRY_INDEX | |
1469 && prop < FONT_EXTRA_INDEX) | |
1470 ASET (font, prop, | |
1471 font_prop_validate (prop, Qnil, val)); | |
1472 else if (prop >= 0) | |
1473 Ffont_put (font, key, val); | |
1474 else | |
1475 bcopy (keyhead, copy, q - keyhead); | |
1476 copy += q - keyhead; | |
1477 } | |
1478 } | |
1479 p = *q ? q + 1 : q; | |
1480 #undef PROP_MATCH | |
1481 } | |
1482 if (name != copy) | |
1483 font_put_extra (font, QCfc_unknown_spec, | |
1484 make_unibyte_string (name, copy - name)); | |
1485 } | |
1486 } | |
1344 else | 1487 else |
1345 { | 1488 { |
1346 Lisp_Object family; | 1489 /* Either a fontconfig-style name with no size and property |
1347 double point_size; | 1490 data, or a GTK-style name. */ |
1348 | 1491 Lisp_Object prop; |
1349 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++) | 1492 int word_len, prop_found = 0; |
1350 if (*p0 == '\\' && p0[1]) | 1493 |
1351 p0++; | 1494 for (p = name; *p; p = *q ? q + 1 : q) |
1352 family = font_intern_prop (name, p0 - name, 1); | 1495 { |
1353 if (*p0 == '-') | 1496 if (isdigit (*p)) |
1354 { | |
1355 if (! isdigit (p0[1])) | |
1356 return -1; | |
1357 point_size = strtod (p0 + 1, &p1); | |
1358 if (*p1 && *p1 != ':') | |
1359 return -1; | |
1360 ASET (font, FONT_SIZE_INDEX, make_float (point_size)); | |
1361 p0 = p1; | |
1362 } | |
1363 ASET (font, FONT_FAMILY_INDEX, family); | |
1364 } | |
1365 | |
1366 len -= p0 - name; | |
1367 copy = alloca (len + 1); | |
1368 if (! copy) | |
1369 return -1; | |
1370 name = copy; | |
1371 | |
1372 /* Now parse ":KEY=VAL" patterns. Store known keys and values in | |
1373 extra, copy unknown ones to COPY. It is stored in extra slot by | |
1374 the key QCfc_unknown_spec. */ | |
1375 while (*p0) | |
1376 { | |
1377 Lisp_Object key, val; | |
1378 int prop; | |
1379 | |
1380 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++); | |
1381 if (*p1 != '=') | |
1382 { | |
1383 /* Must be an enumerated value. */ | |
1384 val = font_intern_prop (p0 + 1, p1 - p0 - 1, 1); | |
1385 if (memcmp (p0 + 1, "light", 5) == 0 | |
1386 || memcmp (p0 + 1, "medium", 6) == 0 | |
1387 || memcmp (p0 + 1, "demibold", 8) == 0 | |
1388 || memcmp (p0 + 1, "bold", 4) == 0 | |
1389 || memcmp (p0 + 1, "black", 5) == 0) | |
1390 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, val); | |
1391 else if (memcmp (p0 + 1, "roman", 5) == 0 | |
1392 || memcmp (p0 + 1, "italic", 6) == 0 | |
1393 || memcmp (p0 + 1, "oblique", 7) == 0) | |
1394 FONT_SET_STYLE (font, FONT_SLANT_INDEX, val); | |
1395 else if (memcmp (p0 + 1, "charcell", 8) == 0 | |
1396 || memcmp (p0 + 1, "mono", 4) == 0 | |
1397 || memcmp (p0 + 1, "proportional", 12) == 0) | |
1398 { | 1497 { |
1399 int spacing = (p0[1] == 'c' ? FONT_SPACING_CHARCELL | 1498 char *r; |
1400 : p0[1] == 'm' ? FONT_SPACING_MONO | 1499 int size_found = 1; |
1401 : FONT_SPACING_PROPORTIONAL); | 1500 for (q = p + 1; *q && *q != ' '; q++) |
1402 ASET (font, FONT_SPACING_INDEX, make_number (spacing)); | 1501 if (! isdigit (*q)) |
1502 { | |
1503 size_found = 0; | |
1504 break; | |
1505 } | |
1506 if (size_found) | |
1507 { | |
1508 double point_size = strtod (p, &q); | |
1509 ASET (font, FONT_SIZE_INDEX, make_float (point_size)); | |
1510 continue; | |
1511 } | |
1403 } | 1512 } |
1404 else | 1513 |
1514 for (q = p + 1; *q && *q != ' '; q++) | |
1515 if (*q == '\\' && q[1]) | |
1516 q++; | |
1517 word_len = q - p; | |
1518 | |
1519 #define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0) | |
1520 | |
1521 if (PROP_MATCH ("Ultra-Light", 11)) | |
1405 { | 1522 { |
1406 /* unknown key */ | 1523 prop_found = 1; |
1407 bcopy (p0, copy, p1 - p0); | 1524 prop = font_intern_prop ("ultra-light", 11, 1); |
1408 copy += p1 - p0; | 1525 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop); |
1409 } | 1526 } |
1410 } | 1527 else if (PROP_MATCH ("Light", 5)) |
1411 else | |
1412 { | |
1413 char *keyhead = p0; | |
1414 | |
1415 if (memcmp (p0 + 1, "pixelsize=", 10) == 0) | |
1416 prop = FONT_SIZE_INDEX; | |
1417 else | |
1418 { | 1528 { |
1419 key = font_intern_prop (p0, p1 - p0, 1); | 1529 prop_found = 1; |
1420 prop = get_font_prop_index (key); | 1530 prop = font_intern_prop ("light", 5, 1); |
1531 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop); | |
1421 } | 1532 } |
1422 p0 = p1 + 1; | 1533 else if (PROP_MATCH ("Semi-Bold", 9)) |
1423 for (p1 = p0; *p1 && *p1 != ':'; p1++); | |
1424 val = font_intern_prop (p0, p1 - p0, 0); | |
1425 if (! NILP (val)) | |
1426 { | 1534 { |
1427 if (prop >= FONT_FOUNDRY_INDEX && prop < FONT_EXTRA_INDEX) | 1535 prop_found = 1; |
1428 ASET (font, prop, font_prop_validate (prop, Qnil, val)); | 1536 prop = font_intern_prop ("semi-bold", 9, 1); |
1429 else if (prop >= 0) | 1537 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop); |
1430 Ffont_put (font, key, val); | |
1431 else | |
1432 bcopy (keyhead, copy, p1 - keyhead); | |
1433 copy += p1 - keyhead; | |
1434 } | 1538 } |
1435 } | 1539 else if (PROP_MATCH ("Bold", 4)) |
1436 p0 = p1; | 1540 { |
1437 } | 1541 prop_found = 1; |
1438 if (name != copy) | 1542 prop = font_intern_prop ("bold", 4, 1); |
1439 font_put_extra (font, QCfc_unknown_spec, | 1543 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop); |
1440 make_unibyte_string (name, copy - name)); | 1544 } |
1441 | 1545 else if (PROP_MATCH ("Italic", 6)) |
1546 { | |
1547 prop_found = 1; | |
1548 prop = font_intern_prop ("italic", 4, 1); | |
1549 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop); | |
1550 } | |
1551 else if (PROP_MATCH ("Oblique", 7)) | |
1552 { | |
1553 prop_found = 1; | |
1554 prop = font_intern_prop ("oblique", 7, 1); | |
1555 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop); | |
1556 } | |
1557 else { | |
1558 if (prop_found) | |
1559 return -1; /* Unknown property in GTK-style font name. */ | |
1560 family_end = q; | |
1561 } | |
1562 } | |
1563 #undef PROP_MATCH | |
1564 | |
1565 if (family_end) | |
1566 { | |
1567 Lisp_Object family; | |
1568 family = font_intern_prop (name, family_end - name, 1); | |
1569 ASET (font, FONT_FAMILY_INDEX, family); | |
1570 } | |
1571 } | |
1572 | |
1442 return 0; | 1573 return 0; |
1443 } | 1574 } |
1444 | 1575 |
1445 /* Store fontconfig's font name of FONT (font-spec or font-entity) in | 1576 /* Store fontconfig's font name of FONT (font-spec or font-entity) in |
1446 NAME (NBYTES length), and return the name length. If | 1577 NAME (NBYTES length), and return the name length. If |