X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8825930890470898883be9841d6a0aa3d6ff6623..0877d0dc24ee792b9b14592869ea1aa0934aee58:/src/nsfont.m diff --git a/src/nsfont.m b/src/nsfont.m index 556102b6f4..c0bea2e225 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -1,6 +1,6 @@ /* Font back-end driver for the NeXT/Open/GNUstep and MacOSX window system. See font.h - Copyright (C) 2006-2012 Free Software Foundation, Inc. + Copyright (C) 2006-2013 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -23,7 +23,6 @@ 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 -#include #include "lisp.h" #include "dispextern.h" @@ -47,13 +46,15 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu) #define NSFONT_TRACE 0 extern Lisp_Object Qns; -extern Lisp_Object Qnormal, Qbold, Qitalic, Qcondensed, Qexpanded; +extern Lisp_Object Qnormal, Qbold, Qitalic; static Lisp_Object Qapple, Qroman, Qmedium; +static Lisp_Object Qcondensed, Qexpanded; extern Lisp_Object Qappend; extern float ns_antialias_threshold; extern int ns_tmp_flags; extern struct nsfont_info *ns_tmp_font; + /* font glyph and metrics caching functions, implemented at end */ static void ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block); @@ -100,7 +101,7 @@ ns_get_family (Lisp_Object font_spec) 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]; @@ -152,7 +153,7 @@ ns_spec_to_descriptor (Lisp_Object font_spec) [fdAttrs setObject: tdict forKey: NSFontTraitsAttribute]; fdesc = [NSFontDescriptor fontDescriptorWithFontAttributes: fdAttrs]; - if (family != nil) + if (family != nil) { fdesc = [fdesc fontDescriptorWithFamily: family]; } @@ -201,8 +202,8 @@ ns_descriptor_to_entity (NSFontDescriptor *desc, make_number (100 + 100 * ns_attribute_fvalue (desc, NSFontSlantTrait)));*/ FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX, - traits & NSFontCondensedTrait ? Qcondensed : - traits & NSFontExpandedTrait ? Qexpanded : Qnormal); + traits & NSFontCondensedTrait ? Qcondensed : + traits & NSFontExpandedTrait ? Qexpanded : Qnormal); /* FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX, make_number (100 + 100 * ns_attribute_fvalue (desc, NSFontWidthTrait)));*/ @@ -236,27 +237,63 @@ ns_fallback_entity (void) } -/* 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); } @@ -271,6 +308,11 @@ ns_charset_covers(NSCharacterSet *set1, NSCharacterSet *set2, float pct) const unsigned short *bytes2 = [[set2 bitmapRepresentation] bytes]; int i, off = 0, tot = 0; + /* Work around what appears to be a GNUstep bug. + See . */ + if (! (bytes1 && bytes2)) + return NO; + for (i=0; i<4096; i++, bytes1++, bytes2++) if (*bytes2) { @@ -288,13 +330,13 @@ ns_charset_covers(NSCharacterSet *set1, NSCharacterSet *set2, float pct) 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 @""; @@ -308,7 +350,7 @@ static NSString { 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))))] : @""; } @@ -321,10 +363,10 @@ static NSString 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); } @@ -350,7 +392,7 @@ static NSString 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))) @@ -368,7 +410,7 @@ static NSString 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 @""; @@ -459,7 +501,7 @@ static NSSet 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]; @@ -518,12 +560,16 @@ ns_findfonts (Lisp_Object font_spec, BOOL isMatch) if (isMatch) [fkeys removeObject: NSFontFamilyAttribute]; - matchingDescs = [fdesc matchingFontDescriptorsWithMandatoryKeys: fkeys]; + if ([fkeys count] > 0) + matchingDescs = [fdesc matchingFontDescriptorsWithMandatoryKeys: fkeys]; + else + matchingDescs = [NSMutableArray array]; + if (NSFONT_TRACE) 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]]) @@ -584,7 +630,7 @@ static unsigned int nsfont_encode_char (struct font *font, int c); 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 = { @@ -659,7 +705,7 @@ nsfont_list_family (Lisp_Object frame) [[[NSFontManager sharedFontManager] availableFontFamilies] objectEnumerator]; NSString *family; - while (family = [families nextObject]) + while ((family = [families nextObject])) list = Fcons (intern ([family UTF8String]), list); /* FIXME: escape the name? */ @@ -687,18 +733,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) Lisp_Object tem; NSRect brect; Lisp_Object font_object; - int i; int fixLeopardBug; - static NSMutableDictionary *fontCache = nil; - NSNumber *cached; - - /* 2008/03/08: The same font may end up being requested for different - entities, due to small differences in numeric values or other issues, - or for different copies of the same entity. Therefore we cache to - avoid creating multiple struct font objects (with metrics cache, etc.) - for the same NSFont object. */ - if (fontCache == nil) - fontCache = [[NSMutableDictionary alloc] init]; if (NSFONT_TRACE) { @@ -714,7 +749,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) } 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) @@ -754,44 +789,26 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) if (NSFONT_TRACE) NSLog (@"%@\n", nsfont); - /* Check the cache */ - cached = [fontCache objectForKey: nsfont]; - if (cached != nil && !synthItal) - { - if (NSFONT_TRACE) - fprintf(stderr, "*** nsfont_open CACHE HIT!\n"); - /* FIXME: Cast from (unsigned long) to Lisp_Object. */ - XHASH (font_object) = [cached unsignedLongValue]; - return font_object; - } - else - { - font_object = font_make_object (VECSIZE (struct nsfont_info), - font_entity, pixel_size); - if (!synthItal) - [fontCache setObject: [NSNumber numberWithUnsignedLong: - (unsigned long) XHASH (font_object)] - forKey: nsfont]; - } - + font_object = font_make_object (VECSIZE (struct nsfont_info), + font_entity, pixel_size); font_info = (struct nsfont_info *) XFONT_OBJECT (font_object); font = (struct font *) font_info; 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 */ +#ifdef NS_IMPL_COCOA + sfont = [nsfont screenFontWithRenderingMode: + NSFontAntialiasedIntegerAdvancementsRenderingMode]; +#else sfont = [nsfont screenFont]; +#endif + if (sfont == nil) sfont = nsfont; @@ -799,7 +816,6 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) 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; @@ -813,7 +829,6 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) { 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 @@ -831,8 +846,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) [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); @@ -889,10 +903,11 @@ 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(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); @@ -901,7 +916,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) font->props[FONT_FULLNAME_INDEX] = make_unibyte_string (font_info->name, strlen (font_info->name)); } - UNBLOCK_INPUT; + unblock_input (); return font_object; } @@ -1009,12 +1024,12 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, /* 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 */ { @@ -1062,7 +1077,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, 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. */ @@ -1226,6 +1240,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, else CGContextSetShouldAntialias (gcontext, 1); + CGContextSetShouldSmoothFonts (gcontext, NO); CGContextSetTextMatrix (gcontext, fliptf); if (bgCol != nil) @@ -1286,7 +1301,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block) fprintf (stderr, "%p\tFinding glyphs for glyphs in block %d\n", font_info, block); - BLOCK_INPUT; + block_input (); #ifdef NS_IMPL_COCOA if (firstTime) @@ -1298,7 +1313,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block) 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++) @@ -1343,7 +1358,7 @@ ns_uni_to_glyphs (struct nsfont_info *font_info, unsigned char block) #endif } - UNBLOCK_INPUT; + unblock_input (); xfree (unichars); } @@ -1368,13 +1383,17 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) numGlyphs = 0x10000; #endif - BLOCK_INPUT; - sfont = [font_info->nsfont screenFont]; + block_input (); +#ifdef NS_IMPL_COCOA + sfont = [font_info->nsfont screenFontWithRenderingMode: + NSFontAntialiasedIntegerAdvancementsRenderingMode]; +#else + sfont = [font_info->nsfont screenFont]; +#endif - 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++) @@ -1398,7 +1417,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) metrics->ascent = r.size.height - metrics->descent; /*-lrint (hshrink* [sfont descender] - expand * hd/2); */ } - UNBLOCK_INPUT; + unblock_input (); } @@ -1417,7 +1436,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) maxChar = 0; maxGlyph = 0; dict = [NSMutableDictionary new]; - cglyphs = (CGGlyph *)xmalloc (c * sizeof (CGGlyph)); + cglyphs = xmalloc (c * sizeof (CGGlyph)); return self; } @@ -1493,9 +1512,13 @@ syms_of_nsfont (void) { nsfont_driver.type = Qns; register_font_driver (&nsfont_driver, NULL); + DEFSYM (Qcondensed, "condensed"); + DEFSYM (Qexpanded, "expanded"); 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. */); + + ascii_printable = NULL; }