aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2008-06-10 20:01:06 +0000
committerChong Yidong2008-06-10 20:01:06 +0000
commit8c102d5bfee908d9f09506377bed7ab61ef0cda0 (patch)
tree8734fc79dd5f21cdd52fabf3ea812c22bd8830cd
parent0abdd19768c8a2c058a79aab773fd908a26c0754 (diff)
downloademacs-8c102d5bfee908d9f09506377bed7ab61ef0cda0.tar.gz
emacs-8c102d5bfee908d9f09506377bed7ab61ef0cda0.zip
(font_parse_fcname): Accept GTK-style font names too.
-rw-r--r--src/font.c303
1 files changed, 217 insertions, 86 deletions
diff --git a/src/font.c b/src/font.c
index 04de0cfdf03..72ef2d3b58d 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1323,122 +1323,253 @@ font_unparse_xlfd (font, pixel_size, name, nbytes)
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
1330int 1341int
1331font_parse_fcname (name, font) 1342font_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;
1344 else
1345 { 1355 {
1346 Lisp_Object family; 1356 if (*p == '\\' && p[1])
1347 double point_size; 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 }
1348 1382
1349 for (p0 = name + 1; *p0 && (*p0 != '-' && *p0 != ':'); p0++) 1383 if (family_end)
1350 if (*p0 == '\\' && p0[1]) 1384 {
1351 p0++; 1385 /* A fontconfig name with size and/or property data. */
1352 family = font_intern_prop (name, p0 - name, 1); 1386 if (family_end > name)
1353 if (*p0 == '-')
1354 { 1387 {
1355 if (! isdigit (p0[1])) 1388 Lisp_Object family;
1356 return -1; 1389 family = font_intern_prop (name, family_end - name, 1);
1357 point_size = strtod (p0 + 1, &p1); 1390 ASET (font, FONT_FAMILY_INDEX, family);
1358 if (*p1 && *p1 != ':') 1391 }
1359 return -1; 1392 if (size_beg)
1393 {
1394 double point_size = strtod (size_beg, &size_end);
1360 ASET (font, FONT_SIZE_INDEX, make_float (point_size)); 1395 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1361 p0 = p1; 1396 if (*size_end == ':' && size_end[1])
1397 props_beg = size_end + 1;
1362 } 1398 }
1363 ASET (font, FONT_FAMILY_INDEX, family); 1399 if (props_beg)
1364 } 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;
1365 1405
1366 len -= p0 - name; 1406 name = copy = alloca (name + len - props_beg);
1367 copy = alloca (len + 1); 1407 if (! copy)
1368 if (! copy) 1408 return -1;
1369 return -1; 1409
1370 name = copy; 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++);
1371 1464
1372 /* Now parse ":KEY=VAL" patterns. Store known keys and values in 1465 val = font_intern_prop (p, word_len, 0);
1373 extra, copy unknown ones to COPY. It is stored in extra slot by 1466 if (! NILP (val))
1374 the key QCfc_unknown_spec. */ 1467 {
1375 while (*p0) 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 }
1487 else
1376 { 1488 {
1377 Lisp_Object key, val; 1489 /* Either a fontconfig-style name with no size and property
1378 int prop; 1490 data, or a GTK-style name. */
1491 Lisp_Object prop;
1492 int word_len, prop_found = 0;
1379 1493
1380 for (p1 = p0 + 1; *p1 && *p1 != '=' && *p1 != ':'; p1++); 1494 for (p = name; *p; p = *q ? q + 1 : q)
1381 if (*p1 != '=')
1382 { 1495 {
1383 /* Must be an enumerated value. */ 1496 if (isdigit (*p))
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); 1538 }
1431 else 1539 else if (PROP_MATCH ("Bold", 4))
1432 bcopy (keyhead, copy, p1 - keyhead); 1540 {
1433 copy += p1 - keyhead; 1541 prop_found = 1;
1542 prop = font_intern_prop ("bold", 4, 1);
1543 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1544 }
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);
1434 } 1556 }
1557 else {
1558 if (prop_found)
1559 return -1; /* Unknown property in GTK-style font name. */
1560 family_end = q;
1561 }
1435 } 1562 }
1436 p0 = p1; 1563#undef PROP_MATCH
1437 }
1438 if (name != copy)
1439 font_put_extra (font, QCfc_unknown_spec,
1440 make_unibyte_string (name, copy - name));
1441 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