/* Font back-end driver for the NeXT/Open/GNUstep and MacOSX window system.
See font.h
- Copyright (C) 2006-2011 Free Software Foundation, Inc.
+ Copyright (C) 2006-2012 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 <setjmp.h>
#include "lisp.h"
#include "dispextern.h"
return nil;
else
{
- char *tmp = xstrdup (SDATA (SYMBOL_NAME (tem)));
+ char *tmp = xstrdup (SSDATA (SYMBOL_NAME (tem)));
NSString *family;
ns_unescape_name (tmp);
family = [NSString stringWithUTF8String: tmp];
/* 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
-static NSFontDescriptor
-*ns_spec_to_descriptor(Lisp_Object font_spec)
+static NSFontDescriptor *
+ns_spec_to_descriptor (Lisp_Object font_spec)
{
NSFontDescriptor *fdesc;
NSMutableDictionary *fdAttrs = [NSMutableDictionary new];
fdesc = [NSFontDescriptor fontDescriptorWithFontAttributes: fdAttrs];
if (family != nil)
+ {
fdesc = [fdesc fontDescriptorWithFamily: family];
+ }
+
+ [fdAttrs release];
+ [tdict release];
return fdesc;
}
}
-/* Utility: get width of a char c in screen font sfont */
+/* Utility: get width of a char c in screen font SFONT */
static float
ns_char_width (NSFont *sfont, int c)
{
- float w;
- NSString *cstr = [NSString stringWithFormat: @"%c", c];
+ float w = -1.0;
+ NSString *cstr = [NSString stringWithFormat: @"%c", c];
+
#ifdef NS_IMPL_COCOA
- NSGlyph glyph = [sfont glyphWithName: cstr];
- if (glyph)
- {
- float w = [sfont advancementForGlyph: glyph].width;
- if (w >= 1.5)
- return w;
- }
+ NSGlyph glyph = [sfont glyphWithName: cstr];
+ if (glyph)
+ w = [sfont advancementForGlyph: glyph].width;
#endif
+
+ if (w < 0.0)
{
NSDictionary *attrsDictionary =
[NSDictionary dictionaryWithObject: sfont forKey: NSFontAttributeName];
w = [cstr sizeWithAttributes: attrsDictionary].width;
}
- return max (w, 2.0);
+
+ return max (w, 1.0);
+}
+
+/* Return average width over ASCII printable characters for SFONT. */
+
+static NSString *ascii_printable;
+
+static int
+ns_ascii_average_width (NSFont *sfont)
+{
+ float w = -1.0;
+
+ if (!ascii_printable)
+ {
+ char chars[96];
+ int ch;
+ for (ch = 0; ch < 95; ch++)
+ chars[ch] = ' ' + ch;
+ chars[95] = '\0';
+
+ ascii_printable = [[NSString alloc] initWithFormat: @"%s", chars];
+ }
+
+#ifdef NS_IMPL_COCOA
+ NSGlyph glyph = [sfont glyphWithName: ascii_printable];
+ if (glyph)
+ w = [sfont advancementForGlyph: glyph].width;
+#endif
+
+ if (w < 0.0)
+ {
+ NSDictionary *attrsDictionary =
+ [NSDictionary dictionaryWithObject: sfont forKey: NSFontAttributeName];
+ w = [ascii_printable sizeWithAttributes: attrsDictionary].width;
+ }
+
+ return lrint (w / 95.0);
}
/* 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
const unsigned short *bytes2 = [[set2 bitmapRepresentation] bytes];
int i, off = 0, tot = 0;
+ /* Work around what appears to be a GNUstep bug.
+ See <http://bugs.gnu.org/11853>. */
+ if (! (bytes1 && bytes2))
+ return NO;
+
for (i=0; i<4096; i++, bytes1++, bytes2++)
if (*bytes2)
{
static NSString
*ns_lang_to_script (Lisp_Object lang)
{
- if (!strcmp (SDATA (SYMBOL_NAME (lang)), "ja"))
+ if (!strcmp (SSDATA (SYMBOL_NAME (lang)), "ja"))
return @"han";
/* NOTE: ja given for any hanzi that's also a kanji, but Chinese fonts
have more characters. */
- else if (!strcmp (SDATA (SYMBOL_NAME (lang)), "zh"))
+ else if (!strcmp (SSDATA (SYMBOL_NAME (lang)), "zh"))
return @"han";
- else if (!strcmp (SDATA (SYMBOL_NAME (lang)), "ko"))
+ else if (!strcmp (SSDATA (SYMBOL_NAME (lang)), "ko"))
return @"hangul";
else
return @"";
/* 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: SSDATA (SYMBOL_NAME (XCDR ((script))))]
: @"";
}
while CONSP (rts)
{
r = XCAR (XCAR (rts));
- if (!strncmp(SDATA(r), reg, strlen(SDATA(r))))
+ if (!strncmp(SSDATA(r), reg, strlen(SSDATA(r))))
{
script = XCDR (XCAR (rts));
- return [NSString stringWithUTF8String: SDATA (SYMBOL_NAME (script))];
+ return [NSString stringWithUTF8String: SSDATA (SYMBOL_NAME (script))];
}
rts = XCDR (rts);
}
/* 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)
{
Lisp_Object key = XCAR (tmp), val = XCDR (tmp);
if (EQ (key, QCscript) && SYMBOLP (val))
return [NSString stringWithUTF8String:
- SDATA (SYMBOL_NAME (val))];
+ SSDATA (SYMBOL_NAME (val))];
if (EQ (key, QClang) && SYMBOLP (val))
return ns_lang_to_script (val);
if (EQ (key, QCotf) && CONSP (val) && SYMBOLP (XCAR (val)))
if (EQ (reg, Qiso10646_1))
reg = Qiso8859_1;
#endif
- return ns_registry_to_script (SDATA (SYMBOL_NAME (reg)));
+ return ns_registry_to_script (SSDATA (SYMBOL_NAME (reg)));
}
return @"";
}
-/* 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)
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)
{
while (1)
{
NSEnumerator *allFamiliesEnum = [allFamilies objectEnumerator];
- while (family = [allFamiliesEnum nextObject])
+ while ((family = [allFamiliesEnum nextObject]))
{
NSCharacterSet *fset = [[fontMgr fontWithFamily: family
traits: 0 weight: 5 size: 12.0] coveredCharacterSet];
if ([families count] > 0 || pct < 0.05)
break;
}
+ [charset release];
}
#ifdef NS_IMPL_COCOA
if ([families count] == 0)
NSLog(@"Got desc %@ and found %d matching fonts from it: ", fdesc,
[matchingDescs count]);
- for (dEnum = [matchingDescs objectEnumerator]; desc = [dEnum nextObject]; )
+ for (dEnum = [matchingDescs objectEnumerator]; (desc = [dEnum nextObject]);)
{
if (![cFamilies containsObject:
[desc objectForKey: NSFontFamilyAttribute]])
family = [fdesc objectForKey: NSFontFamilyAttribute];
if (family != nil && !foundItal && XINT (Flength (list)) > 0)
{
- NSFontDescriptor *sDesc = [[[NSFontDescriptor new]
- fontDescriptorWithSymbolicTraits: NSFontItalicTrait]
- fontDescriptorWithFamily: family];
+ NSFontDescriptor *s1 = [NSFontDescriptor new];
+ NSFontDescriptor *sDesc
+ = [[s1 fontDescriptorWithSymbolicTraits: NSFontItalicTrait]
+ fontDescriptorWithFamily: family];
list = Fcons (ns_descriptor_to_entity (sDesc,
AREF (font_spec, FONT_EXTRA_INDEX),
"synthItal"), list);
+ [s1 release];
}
/* Return something if was a match and nothing found. */
static int nsfont_text_extents (struct font *font, unsigned int *code,
int nglyphs, struct font_metrics *metrics);
static int nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
- int with_background);
+ bool with_background);
struct font_driver nsfont_driver =
{
}
-/* Return a font entity most closely maching with FONT_SPEC on
+/* Return a font entity most closely matching with FONT_SPEC on
FRAME. The closeness is determined by the font backend, thus
`face-font-selection-order' is ignored here.
Properties to be considered are same as for list(). */
[[[NSFontManager sharedFontManager] availableFontFamilies]
objectEnumerator];
NSString *family;
- while (family = [families nextObject])
+ while ((family = [families nextObject]))
list = Fcons (intern ([family UTF8String]), list);
/* FIXME: escape the name? */
Lisp_Object tem;
NSRect brect;
Lisp_Object font_object;
- int i;
int fixLeopardBug;
static NSMutableDictionary *fontCache = nil;
NSNumber *cached;
}
tem = AREF (font_entity, FONT_ADSTYLE_INDEX);
- synthItal = !NILP (tem) && !strncmp ("synthItal", SDATA (SYMBOL_NAME (tem)),
+ synthItal = !NILP (tem) && !strncmp ("synthItal", SSDATA (SYMBOL_NAME (tem)),
9);
family = ns_get_family (font_entity);
if (family == nil)
if (!font)
return Qnil; /* FIXME: other terms do, but return Qnil causes segfault */
- font_info->glyphs = (unsigned short **)
- xmalloc (0x100 * sizeof (unsigned short *));
- font_info->metrics = (struct font_metrics **)
- xmalloc (0x100 * sizeof (struct font_metrics *));
- if (!font_info->glyphs || !font_info->metrics)
- return Qnil;
- memset (font_info->glyphs, 0, 0x100 * sizeof (unsigned short *));
- memset (font_info->metrics, 0, 0x100 * sizeof (struct font_metrics *));
+ font_info->glyphs = xzalloc (0x100 * sizeof *font_info->glyphs);
+ font_info->metrics = xzalloc (0x100 * sizeof *font_info->metrics);
- BLOCK_INPUT;
+ block_input ();
/* for metrics */
sfont = [nsfont screenFont];
font = (struct font *) font_info;
font->pixel_size = [sfont pointSize];
font->driver = &nsfont_driver;
- font->encoding_type = FONT_ENCODING_NOT_DECIDED;
font->encoding_charset = -1;
font->repertory_charset = -1;
font->default_ascent = 0;
{
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
[font_info->nsfont retain];
/* set up ns_font (defined in nsgui.h) */
- font_info->name = (char *)xmalloc (strlen (fontName)+1);
- strcpy (font_info->name, fontName);
+ font_info->name = xstrdup (fontName);
font_info->bold = [fontMgr traitsOfFont: nsfont] & NSBoldFontMask;
font_info->ital =
synthItal || ([fontMgr traitsOfFont: nsfont] & NSItalicFontMask);
/* set up metrics portion of font struct */
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);
+ font->min_width = font->space_width; /* Approximate. */
+ font->average_width = ns_ascii_average_width (sfont);
+
font->height = lrint (font_info->height);
font->underline_position = lrint (font_info->underpos);
font->underline_thickness = lrint (font_info->underwidth);
font->props[FONT_FULLNAME_INDEX] =
make_unibyte_string (font_info->name, strlen (font_info->name));
}
- UNBLOCK_INPUT;
+ unblock_input ();
return font_object;
}
/* Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
- position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
- is nonzero, fill the background in advance. It is assured that
- WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars). */
+ position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
+ fill the background in advance. It is assured that WITH_BACKGROUND
+ is false when (FROM > 0 || TO < S->nchars). */
static int
nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
- int with_background)
+ bool with_background)
/* NOTE: focus and clip must be set
also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */
{
NS to render the string, it will come out differently from the individual
character widths added up because of layout processing. */
{
- XCharStruct *cs;
int cwidth, twidth = 0;
int hi, lo;
/* FIXME: composition: no vertical displacement is considered. */
fprintf (stderr, "%p\tFinding glyphs for glyphs in block %d\n",
font_info, block);
- BLOCK_INPUT;
+ block_input ();
#ifdef NS_IMPL_COCOA
if (firstTime)
font_info->glyphs[block] = xmalloc (0x100 * sizeof (unsigned short));
if (!unichars || !(font_info->glyphs[block]))
- abort ();
+ emacs_abort ();
- /* create a string containing all unicode characters in this block */
- for (idx = block<<8, i =0; i<0x100; idx++, i++)
+ /* 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;
else
NSGlyphGenerator *glyphGenerator = [NSGlyphGenerator sharedGlyphGenerator];
/*NSCharacterSet *coveredChars = [nsfont coveredCharacterSet]; */
unsigned int numGlyphs = [font_info->nsfont numberOfGlyphs];
- NSUInteger gInd =0, cInd =0;
+ NSUInteger gInd = 0, cInd = 0;
[glyphStorage setString: allChars font: font_info->nsfont];
[glyphGenerator generateGlyphsForGlyphStorage: glyphStorage
glyphIndex: &gInd characterIndex: &cInd];
#endif
glyphs = font_info->glyphs[block];
- for (i =0; i<0x100; i++, glyphs++)
+ for (i = 0; i < 0x100; i++, glyphs++)
{
#ifdef NS_IMPL_GNUSTEP
g = unichars[i];
#endif
}
- UNBLOCK_INPUT;
+ unblock_input ();
xfree (unichars);
}
numGlyphs = 0x10000;
#endif
- BLOCK_INPUT;
+ block_input ();
sfont = [font_info->nsfont screenFont];
- font_info->metrics[block] = xmalloc (0x100 * sizeof (struct font_metrics));
- memset (font_info->metrics[block], 0, 0x100 * sizeof (struct font_metrics));
+ font_info->metrics[block] = xzalloc (0x100 * sizeof (struct font_metrics));
if (!(font_info->metrics[block]))
- abort ();
+ emacs_abort ();
metrics = font_info->metrics[block];
for (g = block<<8, i =0; i<0x100 && g < numGlyphs; g++, i++, metrics++)
metrics->ascent = r.size.height - metrics->descent;
/*-lrint (hshrink* [sfont descender] - expand * hd/2); */
}
- UNBLOCK_INPUT;
+ unblock_input ();
}
maxChar = 0;
maxGlyph = 0;
dict = [NSMutableDictionary new];
- cglyphs = (CGGlyph *)xmalloc (c * sizeof (CGGlyph));
+ cglyphs = xmalloc (c * sizeof (CGGlyph));
return self;
}
- (void) setString: (NSString *)str font: (NSFont *)font
{
[dict setObject: font forKey: NSFontAttributeName];
+ if (attrStr != nil)
+ [attrStr release];
attrStr = [[NSAttributedString alloc] initWithString: str attributes: dict];
maxChar = [str length];
maxGlyph = 0;
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. */);
+ doc: /* Internal use: maps font registry to Unicode script. */);
+
+ ascii_printable = NULL;
}