X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4e2f36cfedaac888d4867482f3e83fa5ba635d19..4520b858c1d64bf61db1ae7b00b1b84e0cc645bd:/src/nsfont.m diff --git a/src/nsfont.m b/src/nsfont.m index 33bbe37ab6..115986774d 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, 2007, 2008, 2009, 2010 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" @@ -37,7 +38,7 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu) #include "character.h" #include "font.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 @@ -46,9 +47,10 @@ 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 int ns_antialias_text, ns_use_qd_smoothing; +extern Lisp_Object ns_antialias_text; extern float ns_antialias_threshold; extern int ns_tmp_flags; extern struct nsfont_info *ns_tmp_font; @@ -102,8 +104,6 @@ ns_get_family (Lisp_Object font_spec) char *tmp = strdup (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 +161,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 = strdup ([family UTF8String]); ns_escape_name (escapedFamily); ASET (font_entity, FONT_TYPE_INDEX, Qns); @@ -216,7 +225,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 +247,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 +309,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 +353,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 +506,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 +523,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 +545,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 +657,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 +710,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 +778,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; @@ -768,8 +818,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); @@ -796,8 +846,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); + /* [sfont 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* [sfont 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 +884,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([sfont 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 +974,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->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); } @@ -1185,12 +1233,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); @@ -1296,7 +1342,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 +1397,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 +1407,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 +1464,7 @@ ns_glyph_metrics (struct nsfont_info *font_info, unsigned char block) } /* NSGlyphStorage protocol */ -- (unsigned int)layoutOptions +- (NSUInteger)layoutOptions { return 0; } @@ -1437,9 +1474,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