Merge from trunk.
[bpt/emacs.git] / src / nsfont.m
index 546c47d..7dfb995 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, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2006-2011 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -48,10 +48,8 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
 
 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 Lisp_Object ns_antialias_text;
 extern float ns_antialias_threshold;
 extern int ns_tmp_flags;
 extern struct nsfont_info *ns_tmp_font;
@@ -102,11 +100,11 @@ ns_get_family (Lisp_Object font_spec)
       return nil;
   else
     {
-      char *tmp = strdup (SDATA (SYMBOL_NAME (tem)));
+      char *tmp = xstrdup (SDATA (SYMBOL_NAME (tem)));
       NSString *family;
       ns_unescape_name (tmp);
       family = [NSString stringWithUTF8String: tmp];
-      free (tmp);
+      xfree (tmp);
       return family;
     }
 }
@@ -178,7 +176,7 @@ ns_descriptor_to_entity (NSFontDescriptor *desc,
     if (family == nil)
       family = [[NSFont userFixedPitchFontOfSize: 0] familyName];
 
-    escapedFamily = strdup ([family UTF8String]);
+    escapedFamily = xstrdup ([family UTF8String]);
     ns_escape_name (escapedFamily);
 
     ASET (font_entity, FONT_TYPE_INDEX, Qns);
@@ -219,7 +217,7 @@ ns_descriptor_to_entity (NSFontDescriptor *desc,
        debug_print (font_entity);
       }
 
-    free (escapedFamily);
+    xfree (escapedFamily);
     return font_entity;
 }
 
@@ -258,7 +256,7 @@ ns_char_width (NSFont *sfont, int c)
 
 
 /* Return whether set1 covers set2 to a reasonable extent given by pct.
-   We check, out of each 16 unicode char range containing chars in set2,
+   We check, out of each 16 Unicode char range containing chars in set2,
    whether at least one character is present in set1.
    This must be true for pct of the pairs to consider it covering. */
 static BOOL
@@ -299,13 +297,13 @@ static NSString
 
 
 /* Convert OTF 4-letter script code to emacs script name.  (Why can't
-   everyone just use some standard unicode names for these?) */
+   everyone just use some standard Unicode names for these?) */
 static NSString
 *ns_otf_to_script (Lisp_Object otf)
 {
     Lisp_Object script = assq_no_quit (XCAR (otf), Votf_script_alist);
     return CONSP (script)
-       ? [NSString stringWithUTF8String: SDATA (SYMBOL_NAME XCDR ((script)))]
+       ? [NSString stringWithUTF8String: SDATA (SYMBOL_NAME (XCDR ((script))))]
        : @"";
 }
 
@@ -331,7 +329,7 @@ static NSString
 
 /* 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. */
+   Unicode script.  Empty string returned if no script spec found. */
 static NSString
 *ns_get_req_script (Lisp_Object font_spec)
 {
@@ -387,7 +385,7 @@ accumulate_script_ranges (Lisp_Object arg, Lisp_Object range, Lisp_Object val)
 }
 
 
-/* Use the unicode range information in Vchar_script_table to convert a script
+/* Use the Unicode range information in Vchar_script_table to convert a script
    name into an NSCharacterSet. */
 static NSCharacterSet
 *ns_script_to_charset (NSString *scriptName)
@@ -428,7 +426,7 @@ static NSCharacterSet
    If none are found, we reduce the percentage and try again, until 5%.
    This provides a font with at least some characters if such can be found.
    We don't use isSupersetOfSet: because (a) it doesn't work on Tiger, and
-   (b) need approximate match as fonts covering full unicode ranges are rare. */
+   (b) need approximate match as fonts covering full Unicode ranges are rare. */
 static NSSet
 *ns_get_covering_families (NSString *script, float pct)
 {
@@ -551,8 +549,8 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch)
       return ns_fallback_entity ();
 
     if (NSFONT_TRACE)
-       fprintf (stderr, "    Returning %ld entities.\n",
-                 (long) XINT (Flength (list)));
+       fprintf (stderr, "    Returning %"pI"d entities.\n",
+                 XINT (Flength (list)));
 
     return list;
 }
@@ -658,8 +656,8 @@ nsfont_list_family (Lisp_Object frame)
   /* FIXME: escape the name? */
 
   if (NSFONT_TRACE)
-    fprintf (stderr, "nsfont: list families returning %ld entries\n",
-            (long) XINT (Flength (list)));
+    fprintf (stderr, "nsfont: list families returning %"pI"d entries\n",
+            XINT (Flength (list)));
 
   return list;
 }
@@ -806,11 +804,17 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
   font->props[FONT_FILE_INDEX] = Qnil;
 
   {
-    double expand, hshrink;
-    float full_height, min_height, hd;
     const char *fontName = [[nsfont fontName] UTF8String];
     int len = strlen (fontName);
 
+    /* The values specified by fonts are not always exact. For
+     * example, a 6x8 font could specify that the descender is
+     * -2.00000405... (represented by 0xc000000220000000).  Without
+     * adjustment, the code below would round the descender to -3,
+     * resulting in a font that would be one pixel higher than
+     * intended. */
+    CGFloat adjusted_descender = [sfont descender] + 0.0001;
+
 #ifdef NS_IMPL_GNUSTEP
     font_info->nsfont = sfont;
 #else
@@ -831,26 +835,16 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
       [sfont maximumAdvancement].width : ns_char_width (sfont, '0');
 
     brect =  [sfont boundingRectForFont];
-    full_height = brect.size.height;
-    min_height = [sfont ascender] - [sfont descender];
-    hd = full_height - min_height;
-
-    /* standard height, similar to Carbon. Emacs.app: was 0.5 by default. */
-    expand = 0.0;
-    hshrink = 1.0;
 
-    font_info->underpos = 2; /*[sfont underlinePosition] is often clipped out */
+    font_info->underpos = [sfont underlinePosition];
     font_info->underwidth = [sfont underlineThickness];
     font_info->size = font->pixel_size;
-    font_info->voffset = lrint (hshrink * [sfont ascender] + expand * hd / 2);
 
     /* max bounds */
-    font_info->max_bounds.ascent =
-      lrint (hshrink * [sfont ascender] + expand * hd/2);
-    /* [sfont descender] is usually negative.  Use floor to avoid
+    font_info->max_bounds.ascent = lrint ([sfont ascender]);
+    /* Descender is usually negative.  Use floor to avoid
        clipping descenders. */
-    font_info->max_bounds.descent =
-      -lrint (floor(hshrink* [sfont descender] - expand*hd/2));
+    font_info->max_bounds.descent = -lrint (floor(adjusted_descender));
     font_info->height =
       font_info->max_bounds.ascent + font_info->max_bounds.descent;
     font_info->max_bounds.width = lrint (font_info->width);
@@ -886,7 +880,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
 
     /* set up metrics portion of font struct */
     font->ascent = lrint([sfont ascender]);
-    font->descent = -lrint(floor([sfont descender]));
+    font->descent = -lrint(floor(adjusted_descender));
     font->min_width = ns_char_width(sfont, '|');
     font->space_width = lrint (ns_char_width (sfont, ' '));
     font->average_width = lrint (font_info->width);
@@ -1159,7 +1153,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
 
 
   /* set up for character rendering */
-  r.origin.y += font->voffset + (s->height - font->height)/2;
+  r.origin.y = s->ybase;
 
   col = (NS_FACE_FOREGROUND (face) != 0
          ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f)
@@ -1190,20 +1184,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
 /*[context GSSetTextDrawingMode: GSTextFill]; /// not implemented yet */
       }
 
-    /* do underline */
-    if (face->underline_p)
-      {
-        if (face->underline_color != 0)
-          [ns_lookup_indexed_color (face->underline_color, s->f) set];
-        else
-          [col set];
-        DPSmoveto (context, r.origin.x, r.origin.y + font->underpos);
-        DPSlineto (context, r.origin.x+r.size.width, r.origin.y+font->underpos);
-        if (face->underline_color != 0)
-          [col set];
-      }
-    else
-      [col set];
+    [col set];
 
     /* draw with DPSxshow () */
     DPSmoveto (context, r.origin.x, r.origin.y);
@@ -1249,23 +1230,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
         CGContextSetTextDrawingMode (gcontext, kCGTextFill);
       }
 
-    if (face->underline_p)
-      {
-        if (face->underline_color != 0)
-          [ns_lookup_indexed_color (face->underline_color, s->f) set];
-        else
-          [col set];
-        CGContextBeginPath (gcontext);
-        CGContextMoveToPoint (gcontext,
-                              r.origin.x, r.origin.y + font->underpos);
-        CGContextAddLineToPoint (gcontext, r.origin.x + r.size.width,
-                                r.origin.y + font->underpos);
-        CGContextStrokePath (gcontext);
-        if (face->underline_color != 0)
-          [col set];
-      }
-    else
-      [col set];
+    [col set];
 
     CGContextSetTextPosition (gcontext, r.origin.x, r.origin.y);
     CGContextShowGlyphsWithAdvances (gcontext, s->char2b + s->cmp_from,
@@ -1281,6 +1246,10 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
     CGContextRestoreGState (gcontext);
   }
 #endif  /* NS_IMPL_COCOA */
+
+  /* Draw underline, overline, strike-through. */
+  ns_draw_text_decoration (s, face, col, r.size.width, r.origin.x);
+
   return to-from;
 }
 
@@ -1323,7 +1292,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block)
   if (!unichars || !(font_info->glyphs[block]))
     abort ();
 
-  /* create a string containing all unicode characters in this block */
+  /* create a string containing all Unicode characters in this block */
   for (idx = block<<8, i =0; i<0x100; idx++, i++)
     if (idx < 0xD800 || idx > 0xDFFF)
       unichars[i] = idx;
@@ -1517,8 +1486,6 @@ syms_of_nsfont (void)
   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. */);
+  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