X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4e2f36cfedaac888d4867482f3e83fa5ba635d19..6ca3801d0e75ee56f27aa3c8aaf97fbf1e56a380:/src/nsfont.m diff --git a/src/nsfont.m b/src/nsfont.m index 33bbe37ab6..48d4022355 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, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2006-2011 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 +#include #include "lisp.h" #include "dispextern.h" @@ -36,8 +37,9 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu) #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 #endif @@ -48,7 +50,6 @@ extern Lisp_Object Qns; 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; @@ -99,11 +100,9 @@ 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); - /* For names hard-coded into emacs, like 'helvetica' for splash. */ - tmp[0] = toupper (tmp[0]); family = [NSString stringWithUTF8String: tmp]; free (tmp); return family; @@ -161,14 +160,23 @@ static NSFontDescriptor /* 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); @@ -216,7 +224,7 @@ ns_descriptor_to_entity (NSFontDescriptor *desc, Lisp_Object extra, char *style) /* Default font entity. */ static Lisp_Object -ns_fallback_entity () +ns_fallback_entity (void) { return ns_descriptor_to_entity ([[NSFont userFixedPitchFontOfSize: 0] fontDescriptor], Qnil, NULL); @@ -238,7 +246,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); } @@ -296,17 +308,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); @@ -322,6 +352,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 @""; } @@ -461,11 +505,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); @@ -483,9 +522,12 @@ 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); + NULL); + if (isMatch) + return tem; + list = Fcons (tem, list); if (fabs (ns_attribute_fvalue (desc, NSFontSlantTrait)) > 0.05) foundItal = YES; } @@ -502,8 +544,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; } @@ -609,8 +656,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; } @@ -662,6 +709,8 @@ 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 (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) @@ -728,8 +777,8 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) 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; @@ -760,6 +809,14 @@ 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 + * -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 @@ -768,8 +825,8 @@ 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); - 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); @@ -781,7 +838,7 @@ nsfont_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size) 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. */ @@ -796,8 +853,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); + /* 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); @@ -832,9 +891,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(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); @@ -922,7 +981,7 @@ nsfont_text_extents (struct font *font, unsigned int *code, int nglyphs, int totalWidth = 0; int i; - bzero (metrics, sizeof (struct font_metrics)); + memset (metrics, 0, sizeof (struct font_metrics)); for (i =0; iface; 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; @@ -1093,19 +1151,15 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, 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); } @@ -1163,7 +1217,6 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, DPSstroke (context); DPSgrestore (context); - return to-from; } #else /* NS_IMPL_COCOA */ @@ -1185,12 +1238,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); @@ -1234,10 +1285,9 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y, } CGContextRestoreGState (gcontext); - return; } #endif /* NS_IMPL_COCOA */ - + return to-from; } @@ -1296,7 +1346,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 @@ -1351,7 +1401,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) 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 (); @@ -1361,16 +1411,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; @@ -1427,7 +1468,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) } /* NSGlyphStorage protocol */ -- (unsigned int)layoutOptions +- (NSUInteger)layoutOptions { return 0; } @@ -1437,9 +1478,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