emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r102981: * src/font.c (font_parse_fcn


From: Chong Yidong
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r102981: * src/font.c (font_parse_fcname): Rewrite GTK font name parser.
Date: Wed, 26 Jan 2011 13:10:04 -0500
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 102981
committer: Chong Yidong <address@hidden>
branch nick: trunk
timestamp: Wed 2011-01-26 13:10:04 -0500
message:
  * src/font.c (font_parse_fcname): Rewrite GTK font name parser.
  
  * test/font-parse-testsuite.el (test-font-parse-data): New file.
added:
  test/font-parse-testsuite.el
modified:
  src/ChangeLog
  src/font.c
  test/ChangeLog
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-01-25 04:08:28 +0000
+++ b/src/ChangeLog     2011-01-26 18:10:04 +0000
@@ -1,3 +1,7 @@
+2011-01-26  Chong Yidong  <address@hidden>
+
+       * font.c (font_parse_fcname): Rewrite GTK font name parser.
+
 2011-01-25  Stefan Monnier  <address@hidden>
 
        * xdisp.c (handle_fontified_prop): Be careful with font-lock changing

=== modified file 'src/font.c'
--- a/src/font.c        2011-01-26 08:36:39 +0000
+++ b/src/font.c        2011-01-26 18:10:04 +0000
@@ -1448,109 +1448,83 @@
       /* Either a fontconfig-style name with no size and property
         data, or a GTK-style name.  */
       Lisp_Object prop;
-      int word_len, prop_found = 0;
-
-      for (p = name; *p; p = *q ? q + 1 : q)
+      Lisp_Object weight = Qnil, slant = Qnil;
+      Lisp_Object width  = Qnil, size  = Qnil;
+      char *word_start;
+      int word_len;
+      int size_found = 0;
+
+      /* Scan backwards from the end, looking for a size.  */
+      for (p = name + len - 1; p >= name; p--)
+       if (!isdigit (*p))
+         break;
+
+      if ((p < name + len - 1) && ((p + 1 == name) || *p == ' '))
+       /* Found a font size.  */
+       size = make_float (strtod (p + 1, NULL));
+      else
+       p = name + len;
+
+      /* Now P points to the termination of the string, sans size.
+        Scan backwards, looking for font properties.  */
+      for (; p > name; p = q)
        {
-         if (isdigit (*p))
+         for (q = p - 1; q >= name; q--)
            {
-             int size_found = 1;
-
-             for (q = p + 1; *q && *q != ' '; q++)
-               if (! isdigit (*q) && *q != '.')
-                 {
-                   size_found = 0;
-                   break;
-                 }
-             if (size_found)
-               {
-                 double point_size = strtod (p, &q);
-                 ASET (font, FONT_SIZE_INDEX, make_float (point_size));
-                 continue;
-               }
+             if (q > name && *(q-1) == '\\')
+               --q;   /* Skip quoting backslashes.  */
+             else if (*q == ' ')
+               break;
            }
 
-         for (q = p + 1; *q && *q != ' '; q++)
-           if (*q == '\\' && q[1])
-             q++;
-         word_len = q - p;
+         word_start = q + 1;
+         word_len = p - word_start;
 
-#define PROP_MATCH(STR,N) ((word_len == N) && memcmp (p, STR, N) == 0)
+#define PROP_MATCH(STR,N) \
+         ((word_len == N) && memcmp (word_start, STR, N) == 0)
+#define PROP_SAVE(VAR,STR,N)                   \
+         (VAR = NILP (VAR) ? font_intern_prop (STR, N, 1) : VAR)
 
          if (PROP_MATCH ("Ultra-Light", 11))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("ultra-light", 11, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "ultra-light", 11);
          else if (PROP_MATCH ("Light", 5))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("light", 5, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "light", 5);
          else if (PROP_MATCH ("Book", 4))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("book", 4, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "book", 4);
          else if (PROP_MATCH ("Medium", 6))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("medium", 6, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "medium", 6);
          else if (PROP_MATCH ("Semi-Bold", 9))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("semi-bold", 9, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "semi-bold", 9);
          else if (PROP_MATCH ("Bold", 4))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("bold", 4, 1);
-             FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, prop);
-           }
+           PROP_SAVE (weight, "bold", 4);
          else if (PROP_MATCH ("Italic", 6))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("italic", 4, 1);
-             FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
-           }
+           PROP_SAVE (slant, "italic", 6);
          else if (PROP_MATCH ("Oblique", 7))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("oblique", 7, 1);
-             FONT_SET_STYLE (font, FONT_SLANT_INDEX, prop);
-           }
+           PROP_SAVE (slant, "oblique", 7);
          else if (PROP_MATCH ("Semi-Condensed", 14))
-           {
-             prop_found = 1;
-             prop = font_intern_prop ("semi-condensed", 14, 1);
-             FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
-           }
+           PROP_SAVE (width, "semi-condensed", 14);
          else if (PROP_MATCH ("Condensed", 9))
+           PROP_SAVE (width, "condensed", 9);
+         /* An unknown word must be part of the font name.  */
+         else
            {
-             prop_found = 1;
-             prop = font_intern_prop ("condensed", 9, 1);
-             FONT_SET_STYLE (font, FONT_WIDTH_INDEX, prop);
+             family_end = p;
+             break;
            }
-         else {
-           if (prop_found)
-             return -1; /* Unknown property in GTK-style font name.  */
-           family_end = q;
-         }
        }
 #undef PROP_MATCH
 
       if (family_end)
-       {
-         Lisp_Object family;
-         family = font_intern_prop (name, family_end - name, 1);
-         ASET (font, FONT_FAMILY_INDEX, family);
-       }
+       ASET (font, FONT_FAMILY_INDEX,
+             font_intern_prop (name, family_end - name, 1));
+      if (!NILP (size))
+       ASET (font, FONT_SIZE_INDEX, size);
+      if (!NILP (weight))
+       FONT_SET_STYLE (font, FONT_WEIGHT_INDEX, weight);
+      if (!NILP (slant))
+       FONT_SET_STYLE (font, FONT_SLANT_INDEX, slant);
+      if (!NILP (width))
+       FONT_SET_STYLE (font, FONT_WIDTH_INDEX, width);
     }
 
   return 0;

=== modified file 'test/ChangeLog'
--- a/test/ChangeLog    2011-01-25 04:08:28 +0000
+++ b/test/ChangeLog    2011-01-26 18:10:04 +0000
@@ -1,3 +1,7 @@
+2011-01-26  Chong Yidong  <address@hidden>
+
+       * font-parse-testsuite.el (test-font-parse-data): New file.
+
 2011-01-13  Stefan Monnier  <address@hidden>
 
        * indent/prolog.prolog: Add tokenizing tests.

=== added file 'test/font-parse-testsuite.el'
--- a/test/font-parse-testsuite.el      1970-01-01 00:00:00 +0000
+++ b/test/font-parse-testsuite.el      2011-01-26 18:10:04 +0000
@@ -0,0 +1,135 @@
+;;; redisplay-testsuite.el --- Test suite for redisplay.
+
+;; Copyright (C) 2011 Free Software Foundation, Inc.
+
+;; Author: Chong Yidong <address@hidden>
+;; Keywords:       internal
+;; Human-Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Type M-x test-font-parse RET to generate the test buffer.
+
+;; TODO: Convert to ERT format.
+
+;;; Code:
+
+(defvar test-font-parse-data
+  '((" " " " nil nil nil nil)
+    ("Monospace" "Monospace" nil nil nil nil)
+    ("Foo1" "Foo1" nil nil nil nil)
+    ("12" "nil" 12.0 nil nil nil)
+    ("12 " "12 " nil nil nil nil)
+    ;; Fontconfig format
+    ("Foo:" "Foo" nil nil nil nil)
+    ("Foo-8" "Foo" 8.0 nil nil nil)
+    ("Foo-18:" "Foo" 18.0 nil nil nil)
+    ("Foo-18:light" "Foo" 18.0 light nil nil)
+    ("Foo 10:weight=bold" "Foo 10" nil bold nil nil)
+    ("Foo-12:weight=bold" "Foo" 12.0 bold nil nil)
+    ("Foo 8-20:slant=oblique" "Foo 8" 20.0 nil oblique nil)
+    ("Foo:light:roman" "Foo" nil light roman nil)
+    ("Foo:italic:roman" "Foo" nil nil roman nil)
+    ("Foo 12:light:oblique" "Foo 12" nil light oblique nil)
+    ("Foo-12:demibold:oblique" "Foo" 12.0 demibold oblique nil)
+    ("Foo:black:proportional" "Foo" nil black nil 0)
+    ("Foo-10:black:proportional" "Foo" 10.0 black nil 0)
+    ("Foo:weight=normal" "Foo" nil normal nil nil)
+    ("Foo:weight=bold" "Foo" nil bold nil nil)
+    ("Foo:weight=bold:slant=italic" "Foo" nil bold italic)
+    ("Foo:weight=bold:slant=italic:mono" "Foo" nil bold italic 100)
+    ("Foo-10:demibold:slant=normal" "Foo" 10.0 demibold normal nil)
+    ("Foo 11-16:oblique:weight=bold" "Foo 11" 16.0 bold oblique nil)
+    ("Foo:oblique:randomprop=randomtag:weight=bold"
+     "Foo" nil bold oblique nil)
+    ("Foo:randomprop=randomtag:bar=baz" "Foo" nil nil nil nil)
+    ("Foo Book Light:bar=baz" "Foo Book Light" nil nil nil nil)
+    ("Foo Book Light 10:bar=baz" "Foo Book Light 10" nil nil nil nil)
+    ("Foo Book Light-10:bar=baz" "Foo Book Light" 10.0 nil nil nil)
+    ;; GTK format
+    ("Oblique" "nil" nil nil oblique nil)
+    ("Bold 17" "nil" 17.0 bold nil nil)
+    ("17 Bold" "17" nil bold nil nil)
+    ("Book Oblique 2" "nil" 2.0 book oblique nil)
+    ("Bar 7" "Bar" 7.0 nil nil nil)
+    ("Bar Ultra-Light" "Bar" nil ultra-light nil nil)
+    ("Bar Light 8" "Bar" 8.0 light nil nil)
+    ("Bar Book Medium 9" "Bar" 9.0 medium nil nil)
+    ("Bar Semi-Bold Italic 10" "Bar" 10.0 semi-bold italic nil)
+    ("Bar Semi-Condensed Bold Italic 11" "Bar" 11.0 bold italic nil)
+    ("Foo 10 11" "Foo 10" 11.0 nil nil nil)
+    ("Foo 1985 Book" "Foo 1985" nil book nil nil)
+    ("Foo 1985 A Book" "Foo 1985 A" nil book nil nil)
+    ("Foo A Book 12 A" "Foo A Book 12 A" nil nil nil nil)
+    ("Foo 1985 Book 12 Oblique" "Foo 1985 Book 12" nil nil oblique nil)
+    ("Foo 1985 Book 12 Italic 10" "Foo 1985 Book 12" 10.0 nil italic nil)
+    ("Foo Book Bar 6 Italic" "Foo Book Bar 6" nil nil italic nil)
+    ("Foo Book Bar Bold" "Foo Book Bar" nil bold nil nil))
+  "List of font names parse data.
+Each element should have the form
+   (NAME FAMILY SIZE WEIGHT SLANT SPACING)
+where NAME is the name to parse, and the remainder are the
+expected font properties from parsing NAME.")
+
+(defun test-font-parse ()
+  "Test font name parsing."
+  (interactive)
+  (switch-to-buffer (generate-new-buffer "*Font Pase Test*"))
+  (setq show-trailing-whitespace nil)
+  (let ((pass-face '((t :foreground "green")))
+       (fail-face '((t :foreground "red"))))
+    (dolist (test test-font-parse-data)
+      (let* ((name (nth 0 test))
+            (fs (font-spec :name name))
+            (family  (symbol-name (font-get fs :family)))
+            (size    (font-get fs :size))
+            (weight  (font-get fs :weight))
+            (slant   (font-get fs :slant))
+            (spacing (font-get fs :spacing)))
+       (insert name)
+       (if (> (current-column) 20)
+           (insert "\n"))
+       (indent-to-column 21)
+       (insert (propertize family
+                           'face (if (equal family (nth 1 test))
+                                     pass-face
+                                   fail-face)))
+       (indent-to-column 40)
+       (insert (propertize (format "%s" size)
+                           'face (if (equal size (nth 2 test))
+                                     pass-face
+                                   fail-face)))
+       (indent-to-column 48)
+       (insert (propertize (format "%s" weight)
+                           'face (if (eq weight (nth 3 test))
+                                     pass-face
+                                   fail-face)))
+       (indent-to-column 60)
+       (insert (propertize (format "%s" slant)
+                           'face (if (eq slant (nth 4 test))
+                                     pass-face
+                                   fail-face)))
+       (indent-to-column 69)
+       (insert (propertize (format "%s" spacing)
+                           'face (if (eq spacing (nth 5 test))
+                                     pass-face
+                                   fail-face)))
+       (insert "\n"))))
+  (goto-char (point-min)))
+
+;;; font-parse-testsuite.el ends here.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]