aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2011-01-26 13:10:04 -0500
committerChong Yidong2011-01-26 13:10:04 -0500
commit6608a7d8fb941119faeb8873df0f56eea0ac1764 (patch)
treebd0ec795e234761deec190592842a0c7824802d9
parente4dbdb099213f183db9b46fa93f998319dfb64cd (diff)
downloademacs-6608a7d8fb941119faeb8873df0f56eea0ac1764.tar.gz
emacs-6608a7d8fb941119faeb8873df0f56eea0ac1764.zip
* src/font.c (font_parse_fcname): Rewrite GTK font name parser.
* test/font-parse-testsuite.el (test-font-parse-data): New file.
-rw-r--r--src/ChangeLog4
-rw-r--r--src/font.c134
-rw-r--r--test/ChangeLog4
-rw-r--r--test/font-parse-testsuite.el135
4 files changed, 197 insertions, 80 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 76f81d61354..2041b5bb45c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
12011-01-26 Chong Yidong <cyd@stupidchicken.com>
2
3 * font.c (font_parse_fcname): Rewrite GTK font name parser.
4
12011-01-25 Stefan Monnier <monnier@iro.umontreal.ca> 52011-01-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 6
3 * xdisp.c (handle_fontified_prop): Be careful with font-lock changing 7 * xdisp.c (handle_fontified_prop): Be careful with font-lock changing
diff --git a/src/font.c b/src/font.c
index eb217c6f60f..52b239569bd 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1448,109 +1448,83 @@ font_parse_fcname (char *name, Lisp_Object font)
1448 /* Either a fontconfig-style name with no size and property 1448 /* Either a fontconfig-style name with no size and property
1449 data, or a GTK-style name. */ 1449 data, or a GTK-style name. */
1450 Lisp_Object prop; 1450 Lisp_Object prop;
1451 int word_len, prop_found = 0; 1451 Lisp_Object weight = Qnil, slant = Qnil;
1452 Lisp_Object width = Qnil, size = Qnil;
1453 char *word_start;
1454 int word_len;
1455 int size_found = 0;
1456
1457 /* Scan backwards from the end, looking for a size. */
1458 for (p = name + len - 1; p >= name; p--)
1459 if (!isdigit (*p))
1460 break;
1461
1462 if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
1463 /* Found a font size. */
1464 size = make_float (strtod (p + 1, NULL));
1465 else
1466 p = name + len;
1452 1467
1453 for (p = name; *p; p = *q ? q + 1 : q) 1468 /* Now P points to the termination of the string, sans size.
1469 Scan backwards, looking for font properties. */
1470 for (; p > name; p = q)
1454 { 1471 {
1455 if (isdigit (*p)) 1472 for (q = p - 1; q >= name; q--)
1456 { 1473 {
1457 int size_found = 1; 1474 if (q > name && *(q-1) == '\\')
1458 1475 --q; /* Skip quoting backslashes. */
1459 for (q = p + 1; *q && *q != ' '; q++) 1476 else if (*q == ' ')
1460 if (! isdigit (*q) && *q != '.') 1477 break;
1461 {
1462 size_found = 0;
1463 break;
1464 }
1465 if (size_found)
1466 {
1467 double point_size = strtod (p, &q);
1468 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
1469 continue;
1470 }
1471 } 1478 }
1472 1479
1473 for (q = p + 1; *q && *q != ' '; q++) 1480 word_start = q + 1;
1474 if (*q == '\\' && q[1]) 1481 word_len = p - word_start;
1475 q++;
1476 word_len = q - p;
1477 1482
1478#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0) 1483#define PROP_MATCH(STR,N) \
1484 ((word_len == N) && memcmp (word_start, STR, N) == 0)
1485#define PROP_SAVE(VAR,STR,N) \
1486 (VAR = NILP (VAR) ? font_intern_prop (STR, N, 1) : VAR)
1479 1487
1480 if (PROP_MATCH ("Ultra-Light", 11)) 1488 if (PROP_MATCH ("Ultra-Light", 11))
1481 { 1489 PROP_SAVE (weight, "ultra-light", 11);
1482 prop_found = 1;
1483 prop = font_intern_prop ("ultra-light", 11, 1);
1484 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1485 }
1486 else if (PROP_MATCH ("Light", 5)) 1490 else if (PROP_MATCH ("Light", 5))
1487 { 1491 PROP_SAVE (weight, "light", 5);
1488 prop_found = 1;
1489 prop = font_intern_prop ("light", 5, 1);
1490 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1491 }
1492 else if (PROP_MATCH ("Book", 4)) 1492 else if (PROP_MATCH ("Book", 4))
1493 { 1493 PROP_SAVE (weight, "book", 4);
1494 prop_found = 1;
1495 prop = font_intern_prop ("book", 4, 1);
1496 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1497 }
1498 else if (PROP_MATCH ("Medium", 6)) 1494 else if (PROP_MATCH ("Medium", 6))
1499 { 1495 PROP_SAVE (weight, "medium", 6);
1500 prop_found = 1;
1501 prop = font_intern_prop ("medium", 6, 1);
1502 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1503 }
1504 else if (PROP_MATCH ("Semi-Bold", 9)) 1496 else if (PROP_MATCH ("Semi-Bold", 9))
1505 { 1497 PROP_SAVE (weight, "semi-bold", 9);
1506 prop_found = 1;
1507 prop = font_intern_prop ("semi-bold", 9, 1);
1508 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1509 }
1510 else if (PROP_MATCH ("Bold", 4)) 1498 else if (PROP_MATCH ("Bold", 4))
1511 { 1499 PROP_SAVE (weight, "bold", 4);
1512 prop_found = 1;
1513 prop = font_intern_prop ("bold", 4, 1);
1514 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
1515 }
1516 else if (PROP_MATCH ("Italic", 6)) 1500 else if (PROP_MATCH ("Italic", 6))
1517 { 1501 PROP_SAVE (slant, "italic", 6);
1518 prop_found = 1;
1519 prop = font_intern_prop ("italic", 4, 1);
1520 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1521 }
1522 else if (PROP_MATCH ("Oblique", 7)) 1502 else if (PROP_MATCH ("Oblique", 7))
1523 { 1503 PROP_SAVE (slant, "oblique", 7);
1524 prop_found = 1;
1525 prop = font_intern_prop ("oblique", 7, 1);
1526 FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
1527 }
1528 else if (PROP_MATCH ("Semi-Condensed", 14)) 1504 else if (PROP_MATCH ("Semi-Condensed", 14))
1529 { 1505 PROP_SAVE (width, "semi-condensed", 14);
1530 prop_found = 1;
1531 prop = font_intern_prop ("semi-condensed", 14, 1);
1532 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
1533 }
1534 else if (PROP_MATCH ("Condensed", 9)) 1506 else if (PROP_MATCH ("Condensed", 9))
1507 PROP_SAVE (width, "condensed", 9);
1508 /* An unknown word must be part of the font name. */
1509 else
1535 { 1510 {
1536 prop_found = 1; 1511 family_end = p;
1537 prop = font_intern_prop ("condensed", 9, 1); 1512 break;
1538 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
1539 } 1513 }
1540 else {
1541 if (prop_found)
1542 return -1; /* Unknown property in GTK-style font name. */
1543 family_end = q;
1544 }
1545 } 1514 }
1546#undef PROP_MATCH 1515#undef PROP_MATCH
1547 1516
1548 if (family_end) 1517 if (family_end)
1549 { 1518 ASET (font, FONT_FAMILY_INDEX,
1550 Lisp_Object family; 1519 font_intern_prop (name, family_end - name, 1));
1551 family = font_intern_prop (name, family_end - name, 1); 1520 if (!NILP (size))
1552 ASET (font, FONT_FAMILY_INDEX, family); 1521 ASET (font, FONT_SIZE_INDEX, size);
1553 } 1522 if (!NILP (weight))
1523 FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
1524 if (!NILP (slant))
1525 FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
1526 if (!NILP (width))
1527 FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
1554 } 1528 }
1555 1529
1556 return 0; 1530 return 0;
diff --git a/test/ChangeLog b/test/ChangeLog
index 7b0de7e9e1e..b03e372b8b9 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,7 @@
12011-01-26 Chong Yidong <cyd@stupidchicken.com>
2
3 * font-parse-testsuite.el (test-font-parse-data): New file.
4
12011-01-13 Stefan Monnier <monnier@iro.umontreal.ca> 52011-01-13 Stefan Monnier <monnier@iro.umontreal.ca>
2 6
3 * indent/prolog.prolog: Add tokenizing tests. 7 * indent/prolog.prolog: Add tokenizing tests.
diff --git a/test/font-parse-testsuite.el b/test/font-parse-testsuite.el
new file mode 100644
index 00000000000..02923159e83
--- /dev/null
+++ b/test/font-parse-testsuite.el
@@ -0,0 +1,135 @@
1;;; redisplay-testsuite.el --- Test suite for redisplay.
2
3;; Copyright (C) 2011 Free Software Foundation, Inc.
4
5;; Author: Chong Yidong <cyd@stupidchicken.com>
6;; Keywords: internal
7;; Human-Keywords: internal
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software: you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24;;; Commentary:
25
26;; Type M-x test-font-parse RET to generate the test buffer.
27
28;; TODO: Convert to ERT format.
29
30;;; Code:
31
32(defvar test-font-parse-data
33 '((" " " " nil nil nil nil)
34 ("Monospace" "Monospace" nil nil nil nil)
35 ("Foo1" "Foo1" nil nil nil nil)
36 ("12" "nil" 12.0 nil nil nil)
37 ("12 " "12 " nil nil nil nil)
38 ;; Fontconfig format
39 ("Foo:" "Foo" nil nil nil nil)
40 ("Foo-8" "Foo" 8.0 nil nil nil)
41 ("Foo-18:" "Foo" 18.0 nil nil nil)
42 ("Foo-18:light" "Foo" 18.0 light nil nil)
43 ("Foo 10:weight=bold" "Foo 10" nil bold nil nil)
44 ("Foo-12:weight=bold" "Foo" 12.0 bold nil nil)
45 ("Foo 8-20:slant=oblique" "Foo 8" 20.0 nil oblique nil)
46 ("Foo:light:roman" "Foo" nil light roman nil)
47 ("Foo:italic:roman" "Foo" nil nil roman nil)
48 ("Foo 12:light:oblique" "Foo 12" nil light oblique nil)
49 ("Foo-12:demibold:oblique" "Foo" 12.0 demibold oblique nil)
50 ("Foo:black:proportional" "Foo" nil black nil 0)
51 ("Foo-10:black:proportional" "Foo" 10.0 black nil 0)
52 ("Foo:weight=normal" "Foo" nil normal nil nil)
53 ("Foo:weight=bold" "Foo" nil bold nil nil)
54 ("Foo:weight=bold:slant=italic" "Foo" nil bold italic)
55 ("Foo:weight=bold:slant=italic:mono" "Foo" nil bold italic 100)
56 ("Foo-10:demibold:slant=normal" "Foo" 10.0 demibold normal nil)
57 ("Foo 11-16:oblique:weight=bold" "Foo 11" 16.0 bold oblique nil)
58 ("Foo:oblique:randomprop=randomtag:weight=bold"
59 "Foo" nil bold oblique nil)
60 ("Foo:randomprop=randomtag:bar=baz" "Foo" nil nil nil nil)
61 ("Foo Book Light:bar=baz" "Foo Book Light" nil nil nil nil)
62 ("Foo Book Light 10:bar=baz" "Foo Book Light 10" nil nil nil nil)
63 ("Foo Book Light-10:bar=baz" "Foo Book Light" 10.0 nil nil nil)
64 ;; GTK format
65 ("Oblique" "nil" nil nil oblique nil)
66 ("Bold 17" "nil" 17.0 bold nil nil)
67 ("17 Bold" "17" nil bold nil nil)
68 ("Book Oblique 2" "nil" 2.0 book oblique nil)
69 ("Bar 7" "Bar" 7.0 nil nil nil)
70 ("Bar Ultra-Light" "Bar" nil ultra-light nil nil)
71 ("Bar Light 8" "Bar" 8.0 light nil nil)
72 ("Bar Book Medium 9" "Bar" 9.0 medium nil nil)
73 ("Bar Semi-Bold Italic 10" "Bar" 10.0 semi-bold italic nil)
74 ("Bar Semi-Condensed Bold Italic 11" "Bar" 11.0 bold italic nil)
75 ("Foo 10 11" "Foo 10" 11.0 nil nil nil)
76 ("Foo 1985 Book" "Foo 1985" nil book nil nil)
77 ("Foo 1985 A Book" "Foo 1985 A" nil book nil nil)
78 ("Foo A Book 12 A" "Foo A Book 12 A" nil nil nil nil)
79 ("Foo 1985 Book 12 Oblique" "Foo 1985 Book 12" nil nil oblique nil)
80 ("Foo 1985 Book 12 Italic 10" "Foo 1985 Book 12" 10.0 nil italic nil)
81 ("Foo Book Bar 6 Italic" "Foo Book Bar 6" nil nil italic nil)
82 ("Foo Book Bar Bold" "Foo Book Bar" nil bold nil nil))
83 "List of font names parse data.
84Each element should have the form
85 (NAME FAMILY SIZE WEIGHT SLANT SPACING)
86where NAME is the name to parse, and the remainder are the
87expected font properties from parsing NAME.")
88
89(defun test-font-parse ()
90 "Test font name parsing."
91 (interactive)
92 (switch-to-buffer (generate-new-buffer "*Font Pase Test*"))
93 (setq show-trailing-whitespace nil)
94 (let ((pass-face '((t :foreground "green")))
95 (fail-face '((t :foreground "red"))))
96 (dolist (test test-font-parse-data)
97 (let* ((name (nth 0 test))
98 (fs (font-spec :name name))
99 (family (symbol-name (font-get fs :family)))
100 (size (font-get fs :size))
101 (weight (font-get fs :weight))
102 (slant (font-get fs :slant))
103 (spacing (font-get fs :spacing)))
104 (insert name)
105 (if (> (current-column) 20)
106 (insert "\n"))
107 (indent-to-column 21)
108 (insert (propertize family
109 'face (if (equal family (nth 1 test))
110 pass-face
111 fail-face)))
112 (indent-to-column 40)
113 (insert (propertize (format "%s" size)
114 'face (if (equal size (nth 2 test))
115 pass-face
116 fail-face)))
117 (indent-to-column 48)
118 (insert (propertize (format "%s" weight)
119 'face (if (eq weight (nth 3 test))
120 pass-face
121 fail-face)))
122 (indent-to-column 60)
123 (insert (propertize (format "%s" slant)
124 'face (if (eq slant (nth 4 test))
125 pass-face
126 fail-face)))
127 (indent-to-column 69)
128 (insert (propertize (format "%s" spacing)
129 'face (if (eq spacing (nth 5 test))
130 pass-face
131 fail-face)))
132 (insert "\n"))))
133 (goto-char (point-min)))
134
135;;; font-parse-testsuite.el ends here.