* nsmenu.m (free_frame_tool_bar, update_frame_tool_bar): Add
[bpt/emacs.git] / src / nsfont.m
index 7241af3..db2399a 100644 (file)
@@ -1,6 +1,6 @@
 /* Font back-end driver for the NeXT/Open/GNUstep and MacOSX window system.
    See font.h
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,7 +22,8 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
 
 /* This should be the first include, as it may set up #defines affecting
    interpretation of even the system includes. */
-#include "config.h"
+#include <config.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "dispextern.h"
@@ -37,13 +38,19 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
 #include "character.h"
 #include "font.h"
 
+/* TODO: Drop once we can assume gnustep-gui 0.17.1. */
+#ifdef NS_IMPL_GNUSTEP
+#import <AppKit/NSFontDescriptor.h>
+#endif
+
 #define NSFONT_TRACE 0
 
 extern Lisp_Object Qns;
 extern Lisp_Object Qnormal, Qbold, Qitalic, Qcondensed, Qexpanded;
+static Lisp_Object Vns_reg_to_script;
 static Lisp_Object Qapple, Qroman, Qmedium;
 extern Lisp_Object Qappend;
-extern int ns_antialias_text, ns_use_qd_smoothing;
+extern Lisp_Object ns_antialias_text;
 extern float ns_antialias_threshold;
 extern int ns_tmp_flags;
 extern struct nsfont_info *ns_tmp_font;
@@ -97,8 +104,6 @@ ns_get_family (Lisp_Object font_spec)
       char *tmp = strdup (SDATA (SYMBOL_NAME (tem)));
       NSString *family;
       ns_unescape_name (tmp);
-      /* For names hard-coded into emacs, like 'helvetica' for splash. */
-      tmp[0] = toupper (tmp[0]);
       family = [NSString stringWithUTF8String: tmp];
       free (tmp);
       return family;
@@ -119,15 +124,6 @@ ns_attribute_fvalue (NSFontDescriptor *fdesc, NSString *trait)
 }
 
 
-/* Return whether font has attribute set to non-standard value. */
-static BOOL
-ns_has_attribute (NSFontDescriptor *fdesc, NSString *trait)
-{
-    float v = ns_attribute_fvalue (fdesc, trait);
-    return v < -0.05 || v > 0.05;
-}
-
-
 /* Converts FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, plus family and script/lang
    to NSFont descriptor.  Information under extra only needed for matching. */
 #define STYLE_REF 100
@@ -170,9 +166,16 @@ ns_descriptor_to_entity (NSFontDescriptor *desc, Lisp_Object extra, char *style)
     Lisp_Object font_entity = font_make_entity ();
     /*   NSString *psName = [desc postscriptName]; */
     NSString *family = [desc objectForKey: NSFontFamilyAttribute];
-    char *escapedFamily = strdup ([family UTF8String]);
     unsigned int traits = [desc symbolicTraits];
+    char *escapedFamily;
+
+    /* Shouldn't happen, but on Tiger fallback desc gets name but no family. */
+    if (family == nil)
+      family = [desc objectForKey: NSFontNameAttribute];
+    if (family == nil)
+      family = [[NSFont userFixedPitchFontOfSize: 0] familyName];
 
+    escapedFamily = strdup ([family UTF8String]);
     ns_escape_name (escapedFamily);
 
     ASET (font_entity, FONT_TYPE_INDEX, Qns);
@@ -242,7 +245,11 @@ ns_char_width (NSFont *sfont, int c)
            return w;
       }
 #endif
-    w = [sfont widthOfString: cstr];
+    {
+      NSDictionary *attrsDictionary =
+        [NSDictionary dictionaryWithObject: sfont forKey: NSFontAttributeName];
+      w = [cstr sizeWithAttributes: attrsDictionary].width;
+    }
     return max (w, 2.0);
 }
 
@@ -300,17 +307,35 @@ static NSString
 }
 
 
-/* Searches the :script, :lang, and :otf extra-bundle properties of the spec
-   for something that can be mapped to a unicode script.  Empty string returned
-   if no script spec found.
-   TODO: Eventually registry / encoding should be checked and mapped, but for
-   now the font backend will try script/lang/otf if registry fails, so it is
-   not needed. */
+/* Convert a font registry, such as  */
+static NSString
+*ns_registry_to_script (char *reg)
+{
+    Lisp_Object script, r, rts = Vns_reg_to_script;
+    while CONSP (rts)
+      {
+        r = XCAR (XCAR (rts));
+        if (!strncmp(SDATA(r), reg, strlen(SDATA(r))))
+          {
+            script = XCDR (XCAR (rts));
+            return [NSString stringWithUTF8String: SDATA (SYMBOL_NAME (script))];
+          }
+        rts = XCDR (rts);
+      }
+    return  @"";
+}
+
+
+/* Searches the :script, :lang, and :otf extra-bundle properties of the spec,
+   plus registry regular property, for something that can be mapped to a
+   unicode script.  Empty string returned if no script spec found. */
 static NSString
 *ns_get_req_script (Lisp_Object font_spec)
 {
+    Lisp_Object reg = AREF (font_spec, FONT_REGISTRY_INDEX);
     Lisp_Object extra = AREF (font_spec, FONT_EXTRA_INDEX);
 
+    /* The extra-bundle properties have priority. */
     for ( ; CONSP (extra); extra = XCDR (extra))
       {
        Lisp_Object tmp = XCAR (extra);
@@ -326,6 +351,20 @@ static NSString
                return ns_otf_to_script (val);
          }
       }
+
+    /* If we get here, check the charset portion of the registry. */
+    if (! NILP (reg))
+      {
+        /* XXX: iso10646 is passed in for non-ascii latin-1 characters
+           (which causes box rendering if we don't treat it like iso8858-1)
+           but also for ascii (which causes unnecessary font substitution). */
+#if 0
+        if (EQ (reg, Qiso10646_1))
+          reg = Qiso8859_1;
+#endif
+        return ns_registry_to_script (SDATA (SYMBOL_NAME (reg)));
+      }
+
     return @"";
 }
 
@@ -465,11 +504,6 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch)
        debug_print (font_spec);
       }
 
-    /* If has non-unicode registry, give up. */
-    tem = AREF (font_spec, FONT_REGISTRY_INDEX);
-    if (! NILP (tem) && !EQ (tem, Qiso10646_1) && !EQ (tem, Qunicode_bmp))
-       return isMatch ? ns_fallback_entity () : Qnil;
-
     cFamilies = ns_get_covering_families (ns_get_req_script (font_spec), 0.90);
 
     fdesc = ns_spec_to_descriptor (font_spec);
@@ -487,10 +521,13 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch)
        if (![cFamilies containsObject:
                 [desc objectForKey: NSFontFamilyAttribute]])
            continue;
-       list = Fcons (ns_descriptor_to_entity (desc,
+        tem = ns_descriptor_to_entity (desc,
                                         AREF (font_spec, FONT_EXTRA_INDEX),
-                                        NULL), list);
-       if (ns_has_attribute (desc, NSFontSlantTrait))
+                                       NULL);
+        if (isMatch)
+          return tem;
+       list = Fcons (tem, list);
+       if (fabs (ns_attribute_fvalue (desc, NSFontSlantTrait)) > 0.05)
            foundItal = YES;
       }
 
@@ -506,8 +543,13 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch)
                                         "synthItal"), list);
       }
 
+    /* Return something if was a match and nothing found. */
+    if (isMatch)
+      return ns_fallback_entity ();
+
     if (NSFONT_TRACE)
-       fprintf (stderr, "    Returning %d entities.\n", XINT (Flength (list)));
+       fprintf (stderr, "    Returning %ld entities.\n",
+                 (long) XINT (Flength (list)));
 
     return list;
 }
@@ -613,8 +655,8 @@ nsfont_list_family (Lisp_Object frame)
   /* FIXME: escape the name? */
 
   if (NSFONT_TRACE)
-    fprintf (stderr, "nsfont: list families returning %d entries\n",
-            XINT (Flength (list)));
+    fprintf (stderr, "nsfont: list families returning %ld entries\n",
+            (long) XINT (Flength (list)));
 
   return list;
 }
@@ -666,9 +708,13 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
   synthItal = !NILP (tem) && !strncmp ("synthItal", SDATA (SYMBOL_NAME (tem)),
                                        9);
   family = ns_get_family (font_entity);
-  if (ns_has_attribute (fontDesc, NSFontWeightTrait))
+  if (family == nil)
+    family = [[NSFont userFixedPitchFontOfSize: 0] familyName];
+  /* Should be > 0.23 as some font descriptors (e.g. Terminus) set to that
+     when setting family in ns_spec_to_descriptor(). */
+  if (ns_attribute_fvalue (fontDesc, NSFontWeightTrait) > 0.50)
       traits |= NSBoldFontMask;
-  if (ns_has_attribute (fontDesc, NSFontSlantTrait))
+  if (fabs (ns_attribute_fvalue (fontDesc, NSFontSlantTrait) > 0.05))
       traits |= NSItalicFontMask;
 
   /* see http://cocoadev.com/forums/comments.php?DiscussionID=74 */
@@ -798,8 +844,10 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
     /* max bounds */
     font_info->max_bounds.ascent =
       lrint (hshrink * [sfont ascender] + expand * hd/2);
+    /* [sfont descender] is usually negative.  Use floor to avoid
+       clipping descenders. */
     font_info->max_bounds.descent =
-      -lrint (hshrink* [sfont descender] - expand*hd/2);
+      -lrint (floor(hshrink* [sfont descender] - expand*hd/2));
     font_info->height =
       font_info->max_bounds.ascent + font_info->max_bounds.descent;
     font_info->max_bounds.width = lrint (font_info->width);
@@ -834,9 +882,9 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
 #endif
 
     /* set up metrics portion of font struct */
-    font->ascent = [sfont ascender];
-    font->descent = -[sfont descender];
-    font->min_width = [sfont widthOfString: @"|"]; /* FIXME */
+    font->ascent = lrint([sfont ascender]);
+    font->descent = -lrint(floor([sfont descender]));
+    font->min_width = ns_char_width(sfont, '|');
     font->space_width = lrint (ns_char_width (sfont, ' '));
     font->average_width = lrint (font_info->width);
     font->max_width = lrint (font_info->max_bounds.width);
@@ -1183,12 +1231,10 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
 
     CGContextSetFont (gcontext, font->cgfont);
     CGContextSetFontSize (gcontext, font->size);
-    if (ns_antialias_text == Qnil || font->size <= ns_antialias_threshold)
+    if (NILP (ns_antialias_text) || font->size <= ns_antialias_threshold)
       CGContextSetShouldAntialias (gcontext, 0);
     else
       CGContextSetShouldAntialias (gcontext, 1);
-    if (EQ (ns_use_qd_smoothing, Qt))
-      CGContextSetFontRenderingMode (gcontext, 2); /* 0 is Cocoa, 2 is QD */
 
     CGContextSetTextMatrix (gcontext, fliptf);
 
@@ -1294,7 +1340,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block)
     NSGlyphGenerator *glyphGenerator = [NSGlyphGenerator sharedGlyphGenerator];
     /*NSCharacterSet *coveredChars = [nsfont coveredCharacterSet]; */
     unsigned int numGlyphs = [font_info->nsfont numberOfGlyphs];
-    unsigned int gInd =0, cInd =0;
+    NSUInteger gInd =0, cInd =0;
 
     [glyphStorage setString: allChars font: font_info->nsfont];
     [glyphGenerator generateGlyphsForGlyphStorage: glyphStorage
@@ -1359,16 +1405,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
       float w, lb, rb;
       NSRect r = [sfont boundingRectForGlyph: g];
 
-#ifdef NS_IMPL_GNUSTEP
-      {
-        /* lord help us */
-        NSString *s = [NSString stringWithFormat: @"%c", g];
-        w = [sfont widthOfString: s];
-      }
-#else
-      w = [sfont advancementForGlyph: g].width;
-#endif
-      w = max (w, 2.0);
+      w = max ([sfont advancementForGlyph: g].width, 2.0);
       metrics->width = lrint (w);
 
       lb = r.origin.x;
@@ -1425,7 +1462,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
 }
 
 /* NSGlyphStorage protocol */
-- (unsigned int)layoutOptions
+- (NSUInteger)layoutOptions
 {
   return 0;
 }
@@ -1435,9 +1472,9 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
   return attrStr;
 }
 
-- (void)insertGlyphs: (const NSGlyph *)glyphs length: (unsigned int)length
-        forStartingGlyphAtIndex: (unsigned int)glyphIndex
-        characterIndex: (unsigned int)charIndex
+- (void)insertGlyphs: (const NSGlyph *)glyphs length: (NSUInteger)length
+        forStartingGlyphAtIndex: (NSUInteger)glyphIndex
+        characterIndex: (NSUInteger)charIndex
 {
   len = glyphIndex+length;
   for (i =glyphIndex; i<len; i++)
@@ -1446,8 +1483,8 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block)
     maxGlyph = len;
 }
 
-- (void)setIntAttribute: (int)attributeTag value: (int)val
-        forGlyphAtIndex: (unsigned)glyphIndex
+- (void)setIntAttribute: (NSInteger)attributeTag value: (NSInteger)val
+        forGlyphAtIndex: (NSUInteger)glyphIndex
 {
   return;
 }
@@ -1480,6 +1517,8 @@ syms_of_nsfont ()
   DEFSYM (Qapple, "apple");
   DEFSYM (Qroman, "roman");
   DEFSYM (Qmedium, "medium");
+  DEFVAR_LISP ("ns-reg-to-script", &Vns_reg_to_script,
+               doc: /* Internal use: maps font registry to unicode script. */);
 }
 
 // arch-tag: d6c3c6f0-62de-4978-8b1e-b7966fe02cae