/* 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-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
/* 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"
#include "frame.h"
#include "character.h"
#include "font.h"
+#include "termchar.h"
-/* This header is not included from GNUstep's (0.16.0) AppKit.h. */
+/* TODO: Drop once we can assume gnustep-gui 0.17.1. */
#ifdef NS_IMPL_GNUSTEP
#import <AppKit/NSFontDescriptor.h>
#endif
extern Lisp_Object Qnormal, Qbold, Qitalic, Qcondensed, Qexpanded;
static Lisp_Object Qapple, Qroman, Qmedium;
extern Lisp_Object Qappend;
-extern int ns_antialias_text, ns_use_qd_smoothing;
extern float ns_antialias_threshold;
extern int ns_tmp_flags;
extern struct nsfont_info *ns_tmp_font;
return nil;
else
{
- char *tmp = strdup (SDATA (SYMBOL_NAME (tem)));
+ char *tmp = xstrdup (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;
/* Converts NSFont descriptor to FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, etc.. */
static Lisp_Object
-ns_descriptor_to_entity (NSFontDescriptor *desc, Lisp_Object extra, char *style)
+ns_descriptor_to_entity (NSFontDescriptor *desc,
+ Lisp_Object extra,
+ const 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 = xstrdup ([family UTF8String]);
ns_escape_name (escapedFamily);
ASET (font_entity, FONT_TYPE_INDEX, Qns);
/* Default font entity. */
static Lisp_Object
-ns_fallback_entity ()
+ns_fallback_entity (void)
{
return ns_descriptor_to_entity ([[NSFont userFixedPitchFontOfSize: 0]
fontDescriptor], Qnil, NULL);
return w;
}
#endif
- w = [sfont widthOfString: cstr];
+ {
+ NSDictionary *attrsDictionary =
+ [NSDictionary dictionaryWithObject: sfont forKey: NSFontAttributeName];
+ w = [cstr sizeWithAttributes: attrsDictionary].width;
+ }
return max (w, 2.0);
}
}
-/* 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);
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 @"";
}
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 ? Fcons (ns_fallback_entity (), list) : Qnil;
-
cFamilies = ns_get_covering_families (ns_get_req_script (font_spec), 0.90);
fdesc = ns_spec_to_descriptor (font_spec);
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);
+ NULL);
+ if (isMatch)
+ return tem;
+ list = Fcons (tem, list);
if (fabs (ns_attribute_fvalue (desc, NSFontSlantTrait)) > 0.05)
foundItal = YES;
}
}
/* Return something if was a match and nothing found. */
- if (isMatch && XINT (Flength (list)) == 0)
- list = Fcons (ns_fallback_entity (), Qnil);
+ 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;
}
/* 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;
}
synthItal = !NILP (tem) && !strncmp ("synthItal", SDATA (SYMBOL_NAME (tem)),
9);
family = ns_get_family (font_entity);
+ 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)
xmalloc (0x100 * sizeof (struct font_metrics *));
if (!font_info->glyphs || !font_info->metrics)
return Qnil;
- bzero (font_info->glyphs, 0x100 * sizeof (unsigned short *));
- bzero (font_info->metrics, 0x100 * sizeof (struct font_metrics *));
+ memset (font_info->glyphs, 0, 0x100 * sizeof (unsigned short *));
+ memset (font_info->metrics, 0, 0x100 * sizeof (struct font_metrics *));
BLOCK_INPUT;
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
[font_info->nsfont retain];
/* set up ns_font (defined in nsgui.h) */
- font_info->name = (char *)xmalloc (strlen (fontName) + 1);
- bcopy (fontName, font_info->name, strlen (fontName) + 1);
+ font_info->name = (char *)xmalloc (strlen (fontName)+1);
+ strcpy (font_info->name, fontName);
font_info->bold = [fontMgr traitsOfFont: nsfont] & NSBoldFontMask;
font_info->ital =
synthItal || ([fontMgr traitsOfFont: nsfont] & NSItalicFontMask);
brect = [sfont boundingRectForFont];
full_height = brect.size.height;
- min_height = [sfont ascender] - [sfont descender];
+ min_height = [sfont ascender] - adjusted_descender;
hd = full_height - min_height;
/* standard height, similar to Carbon. Emacs.app: was 0.5 by default. */
/* max bounds */
font_info->max_bounds.ascent =
lrint (hshrink * [sfont ascender] + expand * hd/2);
+ /* 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* adjusted_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);
#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(adjusted_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);
int totalWidth = 0;
int i;
- bzero (metrics, sizeof (struct font_metrics));
+ memset (metrics, 0, sizeof (struct font_metrics));
for (i =0; i<nglyphs; i++)
{
face = s->face;
break;
case NS_DUMPGLYPH_MOUSEFACE:
- face = FACE_FROM_ID (s->f,
- FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id);
+ face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id);
if (!face)
face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
break;
br.size.width -= 2*correction;
}
-#if 0
if (!s->face->stipple)
-#endif
[(NS_FACE_BACKGROUND (face) != 0
? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
: FRAME_BACKGROUND_COLOR (s->f)) set];
-#if 0 /* This is tiling, not stippling. */
else
{
struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f);
[[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
}
-#endif
NSRectFill (br);
}
DPSstroke (context);
DPSgrestore (context);
- return to-from;
}
#else /* NS_IMPL_COCOA */
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);
}
CGContextRestoreGState (gcontext);
- return;
}
#endif /* NS_IMPL_COCOA */
-
+ return to-from;
}
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
sfont = [font_info->nsfont screenFont];
font_info->metrics[block] = xmalloc (0x100 * sizeof (struct font_metrics));
- bzero (font_info->metrics[block], 0x100 * sizeof (struct font_metrics));
+ memset (font_info->metrics[block], 0, 0x100 * sizeof (struct font_metrics));
if (!(font_info->metrics[block]))
abort ();
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;
}
/* NSGlyphStorage protocol */
-- (unsigned int)layoutOptions
+- (NSUInteger)layoutOptions
{
return 0;
}
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++)
maxGlyph = len;
}
-- (void)setIntAttribute: (int)attributeTag value: (int)val
- forGlyphAtIndex: (unsigned)glyphIndex
+- (void)setIntAttribute: (NSInteger)attributeTag value: (NSInteger)val
+ forGlyphAtIndex: (NSUInteger)glyphIndex
{
return;
}
void
-syms_of_nsfont ()
+syms_of_nsfont (void)
{
nsfont_driver.type = Qns;
register_font_driver (&nsfont_driver, NULL);
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