1 /* Font back-end driver for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 2006-2013 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
20 Author: Adrian Robert (arobert@cogsci.ucsd.edu)
23 /* This should be the first include, as it may set up #defines affecting
24 interpretation of even the system includes. */
28 #include "dispextern.h"
29 #include "composite.h"
30 #include "blockinput.h"
36 #include "character.h"
40 /* TODO: Drop once we can assume gnustep-gui 0.17.1. */
41 #ifdef NS_IMPL_GNUSTEP
42 #import
<AppKit
/NSFontDescriptor.h
>
45 #define NSFONT_TRACE
0
46 #define LCD_SMOOTHING_MARGIN
2
48 extern Lisp_Object Qns
;
49 extern Lisp_Object Qnormal
, Qbold
, Qitalic
;
50 static Lisp_Object Qapple
, Qroman
, Qmedium
;
51 static Lisp_Object Qcondensed
, Qexpanded
;
52 extern Lisp_Object Qappend
;
53 extern float ns_antialias_threshold
;
54 extern int ns_tmp_flags
;
55 extern
struct nsfont_info
*ns_tmp_font
;
58 /* font glyph and metrics caching functions, implemented at end */
59 static void ns_uni_to_glyphs
(struct nsfont_info
*font_info
,
61 static void ns_glyph_metrics
(struct nsfont_info
*font_info
,
65 /* ==========================================================================
69 ========================================================================== */
72 /* Replace spaces w/another character so emacs core font parsing routines
75 ns_escape_name
(char *name
)
83 /* Reconstruct spaces in a font family name passed through emacs. */
85 ns_unescape_name
(char *name
)
93 /* Extract family name from a font spec. */
95 ns_get_family
(Lisp_Object font_spec
)
97 Lisp_Object tem
= AREF
(font_spec
, FONT_FAMILY_INDEX
);
102 char *tmp
= xstrdup
(SSDATA
(SYMBOL_NAME
(tem
)));
104 ns_unescape_name
(tmp
);
105 family
= [NSString stringWithUTF8String
: tmp
];
112 /* Return 0 if attr not set, else value (which might also be 0).
113 On Leopard 0 gets returned even on descriptors where the attribute
114 was never set, so there's no way to distinguish between unspecified
115 and set to not have. Callers should assume 0 means unspecified. */
117 ns_attribute_fvalue
(NSFontDescriptor
*fdesc
, NSString
*trait
)
119 NSDictionary
*tdict
= [fdesc objectForKey
: NSFontTraitsAttribute
];
120 NSNumber
*val
= [tdict objectForKey
: trait
];
121 return val
== nil ?
0.0F
: [val floatValue
];
125 /* Converts FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, plus family and script/lang
126 to NSFont descriptor. Information under extra only needed for matching. */
127 #define STYLE_REF
100
128 static NSFontDescriptor
*
129 ns_spec_to_descriptor
(Lisp_Object font_spec
)
131 NSFontDescriptor
*fdesc
;
132 NSMutableDictionary
*fdAttrs
= [NSMutableDictionary new
];
133 NSMutableDictionary
*tdict
= [NSMutableDictionary new
];
134 NSString
*family
= ns_get_family
(font_spec
);
137 /* add each attr in font_spec to fdAttrs.. */
138 n
= min (FONT_WEIGHT_NUMERIC
(font_spec
), 200);
139 if (n
!= -1 && n
!= STYLE_REF
)
140 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0F
) / 100.0F
]
141 forKey
: NSFontWeightTrait
];
142 n
= min (FONT_SLANT_NUMERIC
(font_spec
), 200);
143 if (n
!= -1 && n
!= STYLE_REF
)
144 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0F
) / 100.0F
]
145 forKey
: NSFontSlantTrait
];
146 n
= min (FONT_WIDTH_NUMERIC
(font_spec
), 200);
147 if (n
> -1 && (n
> STYLE_REF
+ 10 || n
< STYLE_REF
- 10))
148 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0F
) / 100.0F
]
149 forKey
: NSFontWidthTrait
];
150 if ([tdict count
] > 0)
151 [fdAttrs setObject
: tdict forKey
: NSFontTraitsAttribute
];
153 fdesc
= [[[NSFontDescriptor fontDescriptorWithFontAttributes
: fdAttrs
]
154 retain
] autorelease
];
158 NSFontDescriptor
*fdesc2
= [fdesc fontDescriptorWithFamily
: family
];
159 fdesc
= [[fdesc2 retain
] autorelease
];
168 /* Converts NSFont descriptor to FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, etc.. */
170 ns_descriptor_to_entity
(NSFontDescriptor
*desc
,
174 Lisp_Object font_entity
= font_make_entity
();
175 /* NSString *psName = [desc postscriptName]; */
176 NSString
*family
= [desc objectForKey
: NSFontFamilyAttribute
];
177 unsigned int traits
= [desc symbolicTraits
];
180 /* Shouldn't happen, but on Tiger fallback desc gets name but no family. */
182 family
= [desc objectForKey
: NSFontNameAttribute
];
184 family
= [[NSFont userFixedPitchFontOfSize
: 0] familyName
];
186 escapedFamily
= xstrdup
([family UTF8String
]);
187 ns_escape_name
(escapedFamily
);
189 ASET
(font_entity
, FONT_TYPE_INDEX
, Qns
);
190 ASET
(font_entity
, FONT_FOUNDRY_INDEX
, Qapple
);
191 ASET
(font_entity
, FONT_FAMILY_INDEX
, intern
(escapedFamily
));
192 ASET
(font_entity
, FONT_ADSTYLE_INDEX
, style ? intern
(style
) : Qnil
);
193 ASET
(font_entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
195 FONT_SET_STYLE
(font_entity
, FONT_WEIGHT_INDEX
,
196 traits
& NSFontBoldTrait ? Qbold
: Qmedium
);
197 /* FONT_SET_STYLE (font_entity, FONT_WEIGHT_INDEX,
198 make_number (100 + 100
199 * ns_attribute_fvalue (desc, NSFontWeightTrait)));*/
200 FONT_SET_STYLE
(font_entity
, FONT_SLANT_INDEX
,
201 traits
& NSFontItalicTrait ? Qitalic
: Qnormal
);
202 /* FONT_SET_STYLE (font_entity, FONT_SLANT_INDEX,
203 make_number (100 + 100
204 * ns_attribute_fvalue (desc, NSFontSlantTrait)));*/
205 FONT_SET_STYLE
(font_entity
, FONT_WIDTH_INDEX
,
206 traits
& NSFontCondensedTrait ? Qcondensed
:
207 traits
& NSFontExpandedTrait ? Qexpanded
: Qnormal
);
208 /* FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX,
209 make_number (100 + 100
210 * ns_attribute_fvalue (desc, NSFontWidthTrait)));*/
212 ASET
(font_entity
, FONT_SIZE_INDEX
, make_number
(0));
213 ASET
(font_entity
, FONT_AVGWIDTH_INDEX
, make_number
(0));
214 ASET
(font_entity
, FONT_SPACING_INDEX
,
215 make_number
([desc symbolicTraits
] & NSFontMonoSpaceTrait
216 ? FONT_SPACING_MONO
: FONT_SPACING_PROPORTIONAL
));
218 ASET
(font_entity
, FONT_EXTRA_INDEX
, extra
);
219 ASET
(font_entity
, FONT_OBJLIST_INDEX
, Qnil
);
223 fprintf (stderr
, "created font_entity
:\n "
);
224 debug_print
(font_entity
);
227 xfree
(escapedFamily
);
232 /* Default font entity. */
234 ns_fallback_entity
(void
)
236 return ns_descriptor_to_entity
([[NSFont userFixedPitchFontOfSize
: 0]
237 fontDescriptor
], Qnil
, NULL);
241 /* Utility: get width of a char c in screen font SFONT */
243 ns_char_width
(NSFont
*sfont
, int c
)
246 NSString
*cstr
= [NSString stringWithFormat
: @"
%c", c];
249 NSGlyph glyph
= [sfont glyphWithName
: cstr
];
251 w
= [sfont advancementForGlyph
: glyph
].width
;
256 NSDictionary
*attrsDictionary
=
257 [NSDictionary dictionaryWithObject
: sfont forKey
: NSFontAttributeName
];
258 w
= [cstr sizeWithAttributes
: attrsDictionary
].width
;
264 /* Return average width over ASCII printable characters for SFONT. */
266 static NSString
*ascii_printable
;
269 ns_ascii_average_width
(NSFont
*sfont
)
273 if (!ascii_printable
)
277 for (ch
= 0; ch
< 95; ch
++)
278 chars
[ch
] = ' ' + ch
;
281 ascii_printable
= [[NSString alloc
] initWithFormat
: @"
%s", chars];
285 NSGlyph glyph
= [sfont glyphWithName
: ascii_printable
];
287 w
= [sfont advancementForGlyph
: glyph
].width
;
290 if (w
< (CGFloat
) 0.0)
292 NSDictionary
*attrsDictionary
=
293 [NSDictionary dictionaryWithObject
: sfont forKey
: NSFontAttributeName
];
294 w
= [ascii_printable sizeWithAttributes
: attrsDictionary
].width
;
297 return lrint
(w
/ (CGFloat
) 95.0);
301 /* Return whether set1 covers set2 to a reasonable extent given by pct.
302 We check, out of each 16 Unicode char range containing chars in set2,
303 whether at least one character is present in set1.
304 This must be true for pct of the pairs to consider it covering. */
306 ns_charset_covers
(NSCharacterSet
*set1
, NSCharacterSet
*set2
, float pct
)
308 const unsigned short
*bytes1
= [[set1 bitmapRepresentation
] bytes
];
309 const unsigned short
*bytes2
= [[set2 bitmapRepresentation
] bytes
];
310 int i
, off
= 0, tot
= 0;
312 /* Work around what appears to be a GNUstep bug.
313 See <http://bugs.gnu.org/11853>. */
314 if (! (bytes1
&& bytes2
))
317 for (i
=0; i
<4096; i
++, bytes1
++, bytes2
++)
321 if (*bytes1
== 0) // *bytes1
& *bytes2
!= *bytes2
324 //fprintf(stderr
, "off
= %d\ttot = %d\n", off,tot);
325 return (float
)off
/ tot
< 1.0F
- pct
;
329 /* Convert :lang property to a script. Use of :lang property by font backend
330 seems to be limited for now (2009/05) to ja, zh, and ko. */
332 *ns_lang_to_script
(Lisp_Object lang
)
334 if (!strcmp (SSDATA
(SYMBOL_NAME
(lang
)), "ja"
))
336 /* NOTE: ja given for any hanzi that's also a kanji, but Chinese fonts
337 have more characters. */
338 else if (!strcmp (SSDATA
(SYMBOL_NAME
(lang
)), "zh"
))
340 else if (!strcmp (SSDATA
(SYMBOL_NAME
(lang
)), "ko"
))
347 /* Convert OTF 4-letter script code to emacs script name. (Why can't
348 everyone just use some standard Unicode names for these?) */
350 *ns_otf_to_script
(Lisp_Object otf
)
352 Lisp_Object
script = assq_no_quit
(XCAR
(otf
), Votf_script_alist
);
353 return CONSP
(script)
354 ?
[NSString stringWithUTF8String
: SSDATA
(SYMBOL_NAME
(XCDR
((script))))]
359 /* Convert a font registry, such as */
361 *ns_registry_to_script
(char *reg
)
363 Lisp_Object
script, r
, rts
= Vns_reg_to_script
;
366 r
= XCAR
(XCAR
(rts
));
367 if (!strncmp
(SSDATA
(r
), reg
, SBYTES
(r
)))
369 script = XCDR
(XCAR
(rts
));
370 return [NSString stringWithUTF8String
: SSDATA
(SYMBOL_NAME
(script))];
378 /* Searches the :script, :lang, and :otf extra-bundle properties of the spec,
379 plus registry regular property, for something that can be mapped to a
380 Unicode script. Empty string returned if no script spec found. */
382 *ns_get_req_script
(Lisp_Object font_spec
)
384 Lisp_Object reg
= AREF
(font_spec
, FONT_REGISTRY_INDEX
);
385 Lisp_Object extra
= AREF
(font_spec
, FONT_EXTRA_INDEX
);
387 /* The extra-bundle properties have priority. */
388 for ( ; CONSP
(extra
); extra
= XCDR
(extra
))
390 Lisp_Object tmp
= XCAR
(extra
);
393 Lisp_Object key
= XCAR
(tmp
), val
= XCDR
(tmp
);
394 if (EQ
(key
, QCscript
) && SYMBOLP
(val
))
395 return [NSString stringWithUTF8String
:
396 SSDATA
(SYMBOL_NAME
(val
))];
397 if (EQ
(key
, QClang
) && SYMBOLP
(val
))
398 return ns_lang_to_script
(val
);
399 if (EQ
(key
, QCotf
) && CONSP
(val
) && SYMBOLP
(XCAR
(val
)))
400 return ns_otf_to_script
(val
);
404 /* If we get here, check the charset portion of the registry. */
407 /* XXX: iso10646 is passed in for non-ascii latin-1 characters
408 (which causes box rendering if we don't treat it like iso8858-1)
409 but also for ascii (which causes unnecessary font substitution). */
411 if (EQ
(reg
, Qiso10646_1
))
414 return ns_registry_to_script
(SSDATA
(SYMBOL_NAME
(reg
)));
421 /* This small function is static in fontset.c. If it can be made public for
422 all ports, remove this, but otherwise it doesn't seem worth the ifdefs. */
424 accumulate_script_ranges
(Lisp_Object arg
, Lisp_Object range
, Lisp_Object val
)
426 if (EQ
(XCAR
(arg
), val
))
429 XSETCDR
(arg
, Fcons
(Fcons
(XCAR
(range
), XCDR
(range
)), XCDR
(arg
)));
431 XSETCDR
(arg
, Fcons
(Fcons
(range
, range
), XCDR
(arg
)));
436 /* Use the Unicode range information in Vchar_script_table to convert a script
437 name into an NSCharacterSet. */
438 static NSCharacterSet
439 *ns_script_to_charset
(NSString
*scriptName
)
441 NSMutableCharacterSet
*charset
= [NSMutableCharacterSet new
];
442 Lisp_Object
script = intern
([scriptName UTF8String
]);
443 Lisp_Object script_list
= XCHAR_TABLE
(Vchar_script_table
)->extras
[0];
445 if (! NILP
(Fmemq
(script, script_list
)))
447 Lisp_Object ranges
, range_list
;
449 ranges
= list1
(script);
450 map_char_table
(accumulate_script_ranges
, Qnil
, Vchar_script_table
,
452 range_list
= Fnreverse
(XCDR
(ranges
));
453 if (! NILP
(range_list
))
455 for (; CONSP
(range_list
); range_list
= XCDR
(range_list
))
457 int start
= XINT
(XCAR
(XCAR
(range_list
)));
458 int
end = XINT
(XCDR
(XCAR
(range_list
)));
460 debug_print
(XCAR
(range_list
));
462 [charset addCharactersInRange
:
463 NSMakeRange
(start
, end-start
)];
471 /* Return an array of font families containing characters for the given
472 script, for the given coverage criterion, including at least LastResort.
473 Results are cached by script for faster access.
474 If none are found, we reduce the percentage and try again, until 5%.
475 This provides a font with at least some characters if such can be found.
476 We don't use isSupersetOfSet: because (a) it doesn't work on Tiger, and
477 (b) need approximate match as fonts covering full Unicode ranges are rare. */
479 *ns_get_covering_families
(NSString
*script, float pct
)
481 static NSMutableDictionary
*scriptToFamilies
= nil
;
482 NSMutableSet
*families
;
485 NSLog
(@"Request covering families
for script: '%@'"
, script);
487 if (scriptToFamilies
== nil
)
488 scriptToFamilies
= [[NSMutableDictionary alloc
] init
];
490 if ((families
= [scriptToFamilies objectForKey
: script]) == nil
)
492 NSFontManager
*fontMgr
= [NSFontManager sharedFontManager
];
493 NSArray
*allFamilies
= [fontMgr availableFontFamilies
];
495 if ([script length] == 0)
496 families
= [NSMutableSet setWithArray
: allFamilies
];
499 NSCharacterSet
*charset
= ns_script_to_charset
(script);
501 families
= [NSMutableSet setWithCapacity
: 10];
504 NSEnumerator
*allFamiliesEnum
= [allFamilies objectEnumerator
];
505 while ((family
= [allFamiliesEnum nextObject
]))
507 NSCharacterSet
*fset
= [[fontMgr fontWithFamily
: family
508 traits
: 0 weight
: 5 size: 12.0] coveredCharacterSet
];
509 /* Some fonts on OS X, maybe many on GNUstep, return nil. */
511 fset
= [NSCharacterSet characterSetWithRange
:
512 NSMakeRange
(0, 127)];
513 if (ns_charset_covers
(fset
, charset
, pct
))
514 [families addObject
: family
];
517 if ([families count
] > 0 || pct
< 0.05F
)
523 if ([families count
] == 0)
524 [families addObject
: @"LastResort"
];
526 [scriptToFamilies setObject
: families forKey
: script];
530 NSLog
(@" returning
%d families", [families count]);
535 /* Implementation for list() and match(). List() can return nil, match()
536 must return something. Strategy is to drop family name from attribute
537 matching set for match. */
539 ns_findfonts
(Lisp_Object font_spec
, BOOL isMatch
)
541 Lisp_Object tem
, list
= Qnil
;
542 NSFontDescriptor
*fdesc
, *desc
;
544 NSArray
*matchingDescs
;
553 fprintf (stderr
, "nsfont
: %s for fontspec:\n ",
554 (isMatch ? "match"
: "list"
));
555 debug_print
(font_spec
);
558 cFamilies
= ns_get_covering_families
(ns_get_req_script
(font_spec
), 0.90);
560 fdesc
= ns_spec_to_descriptor
(font_spec
);
561 fkeys
= [NSMutableSet setWithArray
: [[fdesc fontAttributes
] allKeys
]];
563 [fkeys removeObject
: NSFontFamilyAttribute
];
565 matchingDescs
= [fdesc matchingFontDescriptorsWithMandatoryKeys
: fkeys
];
568 NSLog
(@"Got desc
%@ and found %d matching fonts from it: ", fdesc,
569 [matchingDescs count
]);
571 for (dEnum
= [matchingDescs objectEnumerator
]; (desc
= [dEnum nextObject
]);)
573 if (![cFamilies containsObject
:
574 [desc objectForKey
: NSFontFamilyAttribute
]])
576 tem
= ns_descriptor_to_entity
(desc
,
577 AREF
(font_spec
, FONT_EXTRA_INDEX
),
581 list
= Fcons
(tem
, list
);
582 if (fabs
(ns_attribute_fvalue
(desc
, NSFontSlantTrait
)) > 0.05)
586 /* Add synthItal member if needed. */
587 family
= [fdesc objectForKey
: NSFontFamilyAttribute
];
588 if (family
!= nil
&& !foundItal
&& XINT
(Flength
(list
)) > 0)
590 NSFontDescriptor
*s1
= [NSFontDescriptor new
];
591 NSFontDescriptor
*sDesc
592 = [[s1 fontDescriptorWithSymbolicTraits
: NSFontItalicTrait
]
593 fontDescriptorWithFamily
: family
];
594 list
= Fcons
(ns_descriptor_to_entity
(sDesc
,
595 AREF
(font_spec
, FONT_EXTRA_INDEX
),
602 /* Return something if was a match and nothing found. */
604 return ns_fallback_entity
();
607 fprintf (stderr
, " Returning
%"pI"d entities.\n",
608 XINT
(Flength
(list
)));
615 /* ==========================================================================
617 Font driver implementation
619 ========================================================================== */
622 static Lisp_Object nsfont_get_cache
(struct frame
*frame
);
623 static Lisp_Object nsfont_list
(struct frame
*, Lisp_Object
);
624 static Lisp_Object nsfont_match
(struct frame
*, Lisp_Object
);
625 static Lisp_Object nsfont_list_family
(struct frame
*);
626 static Lisp_Object nsfont_open
(struct frame
*f
, Lisp_Object font_entity
,
628 static void nsfont_close
(struct frame
*f
, struct font
*font
);
629 static int nsfont_has_char
(Lisp_Object entity
, int c
);
630 static unsigned int nsfont_encode_char
(struct font
*font
, int c
);
631 static int nsfont_text_extents
(struct font
*font
, unsigned int
*code
,
632 int nglyphs
, struct font_metrics
*metrics
);
633 static int nsfont_draw
(struct glyph_string
*s
, int from
, int to
, int x
, int y
,
634 bool with_background
);
636 struct font_driver nsfont_driver
=
639 1, /* case sensitive */
644 NULL, /*free_entity */
647 NULL, /* prepare_face */
648 NULL, /* done_face */
653 /* excluded: get_bitmap, free_bitmap, get_outline, free_outline,
654 anchor_point, otf_capability, otf_driver,
655 start_for_frame, end_for_frame, shape */
659 /* Return a cache of font-entities on FRAME. The cache must be a
660 cons whose cdr part is the actual cache area. */
662 nsfont_get_cache
(struct frame
*frame
)
664 Display_Info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(frame
);
665 return (dpyinfo
->name_list_element
);
669 /* List fonts exactly matching with FONT_SPEC on FRAME. The value is a
670 **list** of font-entities. This and match () are sole APIs that allocate
671 font-entities. Properties to be considered (2009/05/19) are:
672 regular: foundry, family, adstyle, registry
673 extended: script, lang, otf
674 "Extended" properties are not part of the vector but get stored as
675 lisp properties under FONT_EXTRA_INDEX.
677 The returned entities should have type set (to 'ns), plus the following:
678 foundry, family, adstyle, registry,
679 weight, slant, width, size (0 if scalable),
680 dpi, spacing, avgwidth (0 if scalable) */
682 nsfont_list
(struct frame
*f
, Lisp_Object font_spec
)
684 return ns_findfonts
(font_spec
, NO
);
688 /* Return a font entity most closely matching with FONT_SPEC on
689 FRAME. The closeness is determined by the font backend, thus
690 `face-font-selection-order' is ignored here.
691 Properties to be considered are same as for list(). */
693 nsfont_match
(struct frame
*f
, Lisp_Object font_spec
)
695 return ns_findfonts
(font_spec
, YES
);
699 /* List available families. The value is a list of family names
702 nsfont_list_family
(struct frame
*f
)
704 Lisp_Object list
= Qnil
;
705 NSEnumerator
*families
;
709 families
= [[[NSFontManager sharedFontManager
] availableFontFamilies
]
711 while ((family
= [families nextObject
]))
712 list
= Fcons
(intern
([family UTF8String
]), list
);
713 /* FIXME: escape the name? */
716 fprintf (stderr
, "nsfont
: list families returning
%"pI"d entries\n",
717 XINT
(Flength
(list
)));
724 /* Open a font specified by FONT_ENTITY on frame F. If the font is
725 scalable, open it with PIXEL_SIZE. */
727 nsfont_open
(struct frame
*f
, Lisp_Object font_entity
, int pixel_size
)
730 unsigned int traits
= 0;
731 struct nsfont_info
*font_info
;
733 NSFontDescriptor
*fontDesc
= ns_spec_to_descriptor
(font_entity
);
734 NSFontManager
*fontMgr
= [NSFontManager sharedFontManager
];
736 NSFont
*nsfont
, *sfont
;
739 Lisp_Object font_object
;
746 fprintf (stderr
, "nsfont
: open
size %d of fontentity:\n ", pixel_size);
747 debug_print
(font_entity
);
752 /* try to get it out of frame params */
753 Lisp_Object tem
= get_frame_param
(f
, Qfontsize
);
754 pixel_size
= NILP
(tem
) ?
0 : XFASTINT
(tem
);
757 tem
= AREF
(font_entity
, FONT_ADSTYLE_INDEX
);
758 synthItal
= !NILP
(tem
) && !strncmp
("synthItal"
, SSDATA
(SYMBOL_NAME
(tem
)),
760 family
= ns_get_family
(font_entity
);
762 family
= [[NSFont userFixedPitchFontOfSize
: 0] familyName
];
763 /* Should be > 0.23 as some font descriptors (e.g. Terminus) set to that
764 when setting family in ns_spec_to_descriptor(). */
765 if (ns_attribute_fvalue
(fontDesc
, NSFontWeightTrait
) > 0.50F
)
766 traits |
= NSBoldFontMask
;
767 if (fabs
(ns_attribute_fvalue
(fontDesc
, NSFontSlantTrait
) > 0.05F
))
768 traits |
= NSItalicFontMask
;
770 /* see http://cocoadev.com/forums/comments.php?DiscussionID=74 */
771 fixLeopardBug
= traits
& NSBoldFontMask ?
10 : 5;
772 nsfont
= [fontMgr fontWithFamily
: family
773 traits
: traits weight
: fixLeopardBug
775 /* if didn't find, try synthetic italic */
776 if (nsfont
== nil
&& synthItal
)
778 nsfont
= [fontMgr fontWithFamily
: family
779 traits
: traits
& ~NSItalicFontMask
780 weight
: fixLeopardBug
size: pixel_size
];
783 /* LastResort not really a family */
784 if (nsfont
== nil
&& [@"LastResort" isEqualToString
: family
])
785 nsfont
= [NSFont fontWithName
: @"LastResort"
size: pixel_size
];
790 message_with_string
("
*** Warning
: font in family
'%s' not found"
,
791 build_string
([family UTF8String
]), 1);
792 nsfont
= [NSFont userFixedPitchFontOfSize
: pixel_size
];
796 NSLog
(@"
%@\n", nsfont);
798 font_object
= font_make_object
(VECSIZE
(struct nsfont_info
),
799 font_entity
, pixel_size
);
800 font_info
= (struct nsfont_info
*) XFONT_OBJECT
(font_object
);
801 font
= (struct font
*) font_info
;
805 return Qnil
; /* FIXME: other terms do, but return Qnil causes segfault */
808 font_info
->glyphs
= xzalloc
(0x100 * sizeof
*font_info
->glyphs
);
809 font_info
->metrics
= xzalloc
(0x100 * sizeof
*font_info
->metrics
);
813 sfont
= [nsfont screenFontWithRenderingMode
:
814 NSFontAntialiasedIntegerAdvancementsRenderingMode
];
816 sfont
= [nsfont screenFont
];
822 /* non-metric backend font struct fields */
823 font
= (struct font
*) font_info
;
824 font
->pixel_size
= [sfont pointSize
];
825 font
->driver
= &nsfont_driver
;
826 font
->encoding_charset
= -1;
827 font
->repertory_charset
= -1;
828 font
->default_ascent
= 0;
829 font
->vertical_centering
= 0;
830 font
->baseline_offset
= 0;
831 font
->relative_compose
= 0;
832 font
->font_encoder
= NULL;
834 font
->props
[FONT_FORMAT_INDEX
] = Qns
;
835 font
->props
[FONT_FILE_INDEX
] = Qnil
;
838 const
char *fontName
= [[nsfont fontName
] UTF8String
];
840 /* The values specified by fonts are not always exact. For
841 * example, a 6x8 font could specify that the descender is
842 * -2.00000405... (represented by 0xc000000220000000). Without
843 * adjustment, the code below would round the descender to -3,
844 * resulting in a font that would be one pixel higher than
846 CGFloat adjusted_descender
= [sfont descender
] + 0.0001;
848 #ifdef NS_IMPL_GNUSTEP
849 font_info
->nsfont
= sfont
;
851 font_info
->nsfont
= nsfont
;
853 [font_info
->nsfont retain
];
855 /* set up ns_font (defined in nsgui.h) */
856 font_info
->name
= xstrdup
(fontName
);
857 font_info
->bold
= [fontMgr traitsOfFont
: nsfont
] & NSBoldFontMask
;
859 synthItal ||
([fontMgr traitsOfFont
: nsfont
] & NSItalicFontMask
);
861 /* Metrics etc.; some fonts return an unusually large max advance, so we
862 only use it for fonts that have wide characters. */
863 font_info
->width
= ([sfont numberOfGlyphs
] > 2000) ?
864 [sfont maximumAdvancement
].width
: ns_char_width
(sfont
, '0');
866 brect
= [sfont boundingRectForFont
];
868 font_info
->underpos
= [sfont underlinePosition
];
869 font_info
->underwidth
= [sfont underlineThickness
];
870 font_info
->size = font
->pixel_size
;
873 font_info
->max_bounds.ascent
= lrint
([sfont ascender
]);
874 /* Descender is usually negative. Use floor to avoid
875 clipping descenders. */
876 font_info
->max_bounds.descent
= -lrint
(floor(adjusted_descender
));
878 font_info
->max_bounds.ascent
+ font_info
->max_bounds.descent
;
879 font_info
->max_bounds.width
= lrint
(font_info
->width
);
880 font_info
->max_bounds.lbearing
= lrint
(brect.origin.x
);
881 font_info
->max_bounds.rbearing
=
882 lrint
(brect.
size.width
- (CGFloat
) font_info
->width
);
885 /* set up synthItal and the CG font */
886 font_info
->synthItal
= synthItal
;
888 ATSFontRef atsFont
= ATSFontFindFromPostScriptName
889 ((CFStringRef
)[nsfont fontName
], kATSOptionFlagsDefault
);
891 if (atsFont
== kATSFontRefUnspecified
)
893 /* see if we can get it by dropping italic (then synthesizing) */
894 atsFont
= ATSFontFindFromPostScriptName
((CFStringRef
)
895 [[fontMgr convertFont
: nsfont toNotHaveTrait
: NSItalicFontMask
]
896 fontName
], kATSOptionFlagsDefault
);
897 if (atsFont
!= kATSFontRefUnspecified
)
898 font_info
->synthItal
= YES
;
901 /* last resort fallback */
902 atsFont
= ATSFontFindFromPostScriptName
903 ((CFStringRef
)@"Monaco"
, kATSOptionFlagsDefault
);
906 font_info
->cgfont
= CGFontCreateWithPlatformFont
((void
*)&atsFont
);
910 /* set up metrics portion of font struct */
911 font
->ascent
= lrint
([sfont ascender
]);
912 font
->descent
= -lrint
(floor(adjusted_descender
));
913 font
->space_width
= lrint
(ns_char_width
(sfont
, ' '));
914 font
->max_width
= lrint
(font_info
->max_bounds.width
);
915 font
->min_width
= font
->space_width
; /* Approximate. */
916 font
->average_width
= ns_ascii_average_width
(sfont
);
918 font
->height
= lrint
(font_info
->height
);
919 font
->underline_position
= lrint
(font_info
->underpos
);
920 font
->underline_thickness
= lrint
(font_info
->underwidth
);
922 font
->props
[FONT_NAME_INDEX
] = Ffont_xlfd_name
(font_object
, Qnil
);
923 font
->props
[FONT_FULLNAME_INDEX
] = build_unibyte_string
(font_info
->name
);
931 /* Close FONT on frame F. */
933 nsfont_close
(struct frame
*f
, struct font
*font
)
935 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
938 /* FIXME: this occurs apparently due to same failure to detect same font
939 that causes need for cache in nsfont_open () */
943 for (i
=0; i
<0x100; i
++)
945 xfree
(font_info
->glyphs
[i
]);
946 xfree
(font_info
->metrics
[i
]);
948 [font_info
->nsfont release
];
950 CGFontRelease
(font_info
->cgfont
);
952 xfree
(font_info
->name
);
957 /* If FONT_ENTITY has a glyph for character C (Unicode code point),
958 return 1. If not, return 0. If a font must be opened to check
961 nsfont_has_char
(Lisp_Object entity
, int c
)
967 /* Return a glyph code of FONT for character C (Unicode code point).
968 If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
970 nsfont_encode_char
(struct font
*font
, int c
)
972 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
973 unsigned
char high
= (c
& 0xff00) >> 8, low
= c
& 0x00ff;
977 return FONT_INVALID_CODE
;
979 /* did we already cache this block? */
980 if (!font_info
->glyphs
[high
])
981 ns_uni_to_glyphs
(font_info
, high
);
983 g
= font_info
->glyphs
[high
][low
];
984 return g
== 0xFFFF ? FONT_INVALID_CODE
: g
;
988 /* Perform the size computation of glyphs of FONT and fill in members
989 of METRICS. The glyphs are specified by their glyph codes in
990 CODE (length NGLYPHS). */
992 nsfont_text_extents
(struct font
*font
, unsigned int
*code
, int nglyphs
,
993 struct font_metrics
*metrics
)
995 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
996 struct font_metrics
*pcm
;
997 unsigned
char high
, low
;
1001 memset
(metrics
, 0, sizeof
(struct font_metrics
));
1003 for (i
=0; i
<nglyphs
; i
++)
1005 /* get metrics for this glyph, filling cache if need be */
1006 /* TODO: get metrics for whole string from an NSLayoutManager
1007 (if not too slow) */
1008 high
= (code
[i
] & 0xFF00) >> 8;
1009 low
= code
[i
] & 0x00FF;
1010 if (!font_info
->metrics
[high
])
1011 ns_glyph_metrics
(font_info
, high
);
1012 pcm
= &(font_info
->metrics
[high
][low
]);
1014 if (metrics
->lbearing
> totalWidth
+ pcm
->lbearing
)
1015 metrics
->lbearing
= totalWidth
+ pcm
->lbearing
;
1016 if (metrics
->rbearing
< totalWidth
+ pcm
->rbearing
)
1017 metrics
->rbearing
= totalWidth
+ pcm
->rbearing
;
1018 if (metrics
->ascent
< pcm
->ascent
)
1019 metrics
->ascent
= pcm
->ascent
;
1020 if (metrics
->descent
< pcm
->descent
)
1021 metrics
->descent
= pcm
->descent
;
1023 totalWidth
+= pcm
->width
;
1026 metrics
->width
= totalWidth
;
1028 return totalWidth
; /* not specified in doc, but xfont.c does it */
1032 /* Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
1033 position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
1034 fill the background in advance. It is assured that WITH_BACKGROUND
1035 is false when (FROM > 0 || TO < S->nchars). */
1037 nsfont_draw
(struct glyph_string
*s
, int from
, int to
, int x
, int y
,
1038 bool with_background
)
1039 /* NOTE: focus and clip must be set
1040 also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */
1042 static unsigned
char cbuf
[1024];
1043 unsigned
char *c
= cbuf
;
1044 #ifdef NS_IMPL_GNUSTEP
1045 static float advances
[1024];
1046 float
*adv
= advances
;
1048 static CGSize advances
[1024];
1049 CGSize
*adv
= advances
;
1053 struct nsfont_info
*font
= ns_tmp_font
;
1054 NSColor
*col
, *bgCol
;
1055 unsigned short
*t
= s
->char2b
;
1057 char isComposite
= s
->first_glyph
->type == COMPOSITE_GLYPH
;
1058 int
end = isComposite ? s
->cmp_to
: s
->nchars
;
1061 /* Select face based on input flags */
1062 switch (ns_tmp_flags
)
1064 case NS_DUMPGLYPH_CURSOR
:
1067 case NS_DUMPGLYPH_MOUSEFACE
:
1068 face
= FACE_FROM_ID
(s
->f
, MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
1070 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
1077 if (s
->face
->box
!= FACE_NO_BOX
&& s
->first_glyph
->left_box_line_p
)
1078 r.origin.x
+= abs (s
->face
->box_line_width
);
1081 r.
size.height
= FONT_HEIGHT
(font
);
1083 /* Convert UTF-16 (?) to UTF-8 and determine advances. Note if we just ask
1084 NS to render the string, it will come out differently from the individual
1085 character widths added up because of layout processing. */
1087 int cwidth
, twidth
= 0;
1089 /* FIXME: composition: no vertical displacement is considered. */
1090 t
+= s
->cmp_from
; /* advance into composition */
1091 for (i
= s
->cmp_from
; i
< end; i
++, t
++)
1093 hi
= (*t
& 0xFF00) >> 8;
1097 if (!s
->first_glyph
->u.cmp.automatic
)
1098 cwidth
= s
->cmp
->offsets
[i
* 2] /* (H offset) */ - twidth
;
1101 Lisp_Object gstring
= composition_gstring_from_id
(s
->cmp_id
);
1102 Lisp_Object glyph
= LGSTRING_GLYPH
(gstring
, i
);
1103 if (NILP
(LGLYPH_ADJUSTMENT
(glyph
)))
1104 cwidth
= LGLYPH_WIDTH
(glyph
);
1107 cwidth
= LGLYPH_WADJUST
(glyph
);
1108 #ifdef NS_IMPL_GNUSTEP
1109 *(adv
-1) += LGLYPH_XOFF
(glyph
);
1111 (*(adv
-1)).width
+= LGLYPH_XOFF
(glyph
);
1118 if (!font
->metrics
[hi
]) /* FIXME: why/how can we need this now? */
1119 ns_glyph_metrics
(font
, hi
);
1120 cwidth
= font
->metrics
[hi
][lo
].width
;
1123 #ifdef NS_IMPL_GNUSTEP
1125 CHAR_STRING_ADVANCE
(*t
, c
); /* this converts the char to UTF-8 */
1127 (*adv
++).width
= cwidth
;
1130 len
= adv
- advances
;
1131 r.
size.width
= twidth
;
1135 /* fill background if requested */
1136 if (with_background
&& !isComposite
)
1139 int fibw
= FRAME_INTERNAL_BORDER_WIDTH
(s
->f
);
1140 int mbox_line_width
= max (s
->face
->box_line_width
, 0);
1142 if (s
->row
->full_width_p
)
1144 if (br.origin.x
<= fibw
+ 1 + mbox_line_width
)
1146 br.
size.width
+= br.origin.x
- mbox_line_width
;
1147 br.origin.x
= mbox_line_width
;
1149 if (FRAME_PIXEL_WIDTH
(s
->f
) - (br.origin.x
+ br.
size.width
)
1151 br.
size.width
+= fibw
;
1153 if (s
->face
->box
== FACE_NO_BOX
)
1155 /* expand unboxed top row over internal border */
1156 if (br.origin.y
<= fibw
+ 1 + mbox_line_width
)
1158 br.
size.height
+= br.origin.y
;
1164 int correction
= abs (s
->face
->box_line_width
)+1;
1165 br.origin.y
+= correction
;
1166 br.
size.height
-= 2*correction
;
1167 br.origin.x
+= correction
;
1168 br.
size.width
-= 2*correction
;
1171 if (!s
->face
->stipple
)
1172 [(NS_FACE_BACKGROUND
(face
) != 0
1173 ? ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
)
1174 : FRAME_BACKGROUND_COLOR
(s
->f
)) set];
1177 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(s
->f
);
1178 [[dpyinfo
->bitmaps
[face
->stipple
-1].img stippleMask
] set];
1184 /* set up for character rendering */
1185 r.origin.y
= s
->ybase
;
1187 col
= (NS_FACE_FOREGROUND
(face
) != 0
1188 ? ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), s
->f
)
1189 : FRAME_FOREGROUND_COLOR
(s
->f
));
1190 /* FIXME: find another way to pass this */
1191 bgCol
= (ns_tmp_flags
!= NS_DUMPGLYPH_FOREGROUND ? nil
1192 : (NS_FACE_BACKGROUND
(face
) != 0
1193 ? ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
)
1194 : FRAME_BACKGROUND_COLOR
(s
->f
)));
1196 /* render under GNUstep using DPS */
1197 #ifdef NS_IMPL_GNUSTEP
1199 NSGraphicsContext
*context
= GSCurrentContext
();
1204 /* do erase if "foreground" mode */
1208 DPSmoveto
(context
, r.origin.x
, r.origin.y
);
1209 /*[context GSSetTextDrawingMode: GSTextFillStroke]; /// not implemented yet */
1210 DPSxshow
(context
, (const
char *) cbuf
, advances
, len
);
1211 DPSstroke
(context
);
1213 /*[context GSSetTextDrawingMode: GSTextFill]; /// not implemented yet */
1218 /* draw with DPSxshow () */
1219 DPSmoveto
(context
, r.origin.x
, r.origin.y
);
1220 DPSxshow
(context
, (const
char *) cbuf
, advances
, len
);
1221 DPSstroke
(context
);
1223 DPSgrestore
(context
);
1226 #
else /* NS_IMPL_COCOA */
1228 CGContextRef gcontext
=
1229 [[NSGraphicsContext currentContext
] graphicsPort
];
1230 static CGAffineTransform fliptf
;
1231 static BOOL firstTime
= YES
;
1236 fliptf
= CGAffineTransformMakeScale
(1.0, -1.0);
1239 CGContextSaveGState
(gcontext
);
1241 fliptf.c
= font
->synthItal ? Fix2X
(kATSItalicQDSkew
) : 0.0;
1243 CGContextSetFont
(gcontext
, font
->cgfont
);
1244 CGContextSetFontSize
(gcontext
, font
->size);
1245 if (NILP
(ns_antialias_text
) || font
->size <= ns_antialias_threshold
)
1246 CGContextSetShouldAntialias
(gcontext
, 0);
1248 CGContextSetShouldAntialias
(gcontext
, 1);
1250 CGContextSetTextMatrix
(gcontext
, fliptf
);
1254 /* foreground drawing; erase first to avoid overstrike */
1256 CGContextSetTextDrawingMode
(gcontext
, kCGTextFillStroke
);
1257 CGContextSetTextPosition
(gcontext
, r.origin.x
, r.origin.y
);
1258 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
, advances
, len
);
1259 CGContextSetTextDrawingMode
(gcontext
, kCGTextFill
);
1264 CGContextSetTextPosition
(gcontext
, r.origin.x
, r.origin.y
);
1265 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
+ s
->cmp_from
,
1268 if (face
->overstrike
)
1270 CGContextSetTextPosition
(gcontext
, r.origin.x
+0.5, r.origin.y
);
1271 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
+ s
->cmp_from
,
1275 CGContextRestoreGState
(gcontext
);
1277 #endif
/* NS_IMPL_COCOA */
1279 /* Draw underline, overline, strike-through. */
1280 ns_draw_text_decoration
(s
, face
, col
, r.
size.width
, r.origin.x
);
1288 /* ==========================================================================
1290 Font glyph and metrics caching functions
1292 ========================================================================== */
1294 /* Find and cache corresponding glyph codes for unicode values in given
1295 hi-byte block of 256. */
1297 ns_uni_to_glyphs
(struct nsfont_info
*font_info
, unsigned
char block
)
1299 #ifdef NS_IMPL_COCOA
1300 static EmacsGlyphStorage
*glyphStorage
;
1301 static
char firstTime
= 1;
1303 unichar
*unichars
= xmalloc
(0x101 * sizeof
(unichar
));
1304 unsigned int i
, g
, idx
;
1305 unsigned short
*glyphs
;
1308 fprintf (stderr
, "
%p\tFinding glyphs for glyphs in block %d\n",
1313 #ifdef NS_IMPL_COCOA
1317 glyphStorage
= [[EmacsGlyphStorage alloc
] initWithCapacity
: 0x100];
1321 font_info
->glyphs
[block
] = xmalloc
(0x100 * sizeof
(unsigned short
));
1322 if (!unichars ||
!(font_info
->glyphs
[block
]))
1325 /* create a string containing all Unicode characters in this block */
1326 for (idx
= block
<<8, i
= 0; i
< 0x100; idx
++, i
++)
1327 if (idx
< 0xD800 || idx
> 0xDFFF)
1330 unichars
[i
] = 0xFEFF;
1331 unichars
[0x100] = 0;
1334 #ifdef NS_IMPL_COCOA
1335 NSString
*allChars
= [[NSString alloc
]
1336 initWithCharactersNoCopy
: unichars
1339 NSGlyphGenerator
*glyphGenerator
= [NSGlyphGenerator sharedGlyphGenerator
];
1340 /*NSCharacterSet *coveredChars = [nsfont coveredCharacterSet]; */
1341 unsigned int numGlyphs
= [font_info
->nsfont numberOfGlyphs
];
1342 NSUInteger gInd
= 0, cInd
= 0;
1344 [glyphStorage setString
: allChars font
: font_info
->nsfont
];
1345 [glyphGenerator generateGlyphsForGlyphStorage
: glyphStorage
1346 desiredNumberOfCharacters
: glyphStorage
->maxChar
1347 glyphIndex
: &gInd characterIndex
: &cInd
];
1349 glyphs
= font_info
->glyphs
[block
];
1350 for (i
= 0; i
< 0x100; i
++, glyphs
++)
1352 #ifdef NS_IMPL_GNUSTEP
1355 g
= glyphStorage
->cglyphs
[i
];
1356 /* TODO: is this a good check? maybe need to use coveredChars.. */
1358 g
= 0xFFFF; /* hopefully unused... */
1363 #ifdef NS_IMPL_COCOA
1373 /* Determine and cache metrics for corresponding glyph codes in given
1374 hi-byte block of 256. */
1376 ns_glyph_metrics
(struct nsfont_info
*font_info
, unsigned
char block
)
1379 unsigned int numGlyphs
= [font_info
->nsfont numberOfGlyphs
];
1381 struct font_metrics
*metrics
;
1384 fprintf (stderr
, "
%p\tComputing metrics for glyphs in block %d\n",
1387 #ifdef NS_IMPL_GNUSTEP
1388 /* not implemented yet (as of startup 0.18), so punt */
1390 numGlyphs
= 0x10000;
1394 #ifdef NS_IMPL_COCOA
1395 sfont
= [font_info
->nsfont screenFontWithRenderingMode
:
1396 NSFontAntialiasedIntegerAdvancementsRenderingMode
];
1398 sfont
= [font_info
->nsfont screenFont
];
1401 font_info
->metrics
[block
] = xzalloc
(0x100 * sizeof
(struct font_metrics
));
1402 if (!(font_info
->metrics
[block
]))
1405 metrics
= font_info
->metrics
[block
];
1406 for (g
= block
<<8, i
=0; i
<0x100 && g
< numGlyphs
; g
++, i
++, metrics
++)
1409 NSRect r
= [sfont boundingRectForGlyph
: g
];
1411 w
= max ([sfont advancementForGlyph
: g
].width
, 2.0);
1412 metrics
->width
= lrint
(w
);
1415 rb
= r.
size.width
- w
;
1416 // Add to bearing
for LCD smoothing. We don
't know if it is there.
1418 metrics->lbearing = round (lb - LCD_SMOOTHING_MARGIN);
1419 if (font_info->ital)
1420 rb += (CGFloat) (0.22F * font_info->height);
1421 metrics->rbearing = lrint (w + rb + LCD_SMOOTHING_MARGIN);
1423 metrics->descent = r.origin.y < 0 ? -r.origin.y : 0;
1424 /*lrint (hshrink * [sfont ascender] + expand * hd/2); */
1425 metrics->ascent = r.size.height - metrics->descent;
1426 /*-lrint (hshrink* [sfont descender] - expand * hd/2); */
1432 #ifdef NS_IMPL_COCOA
1433 /* helper for font glyph setup */
1434 @implementation EmacsGlyphStorage
1438 return [self initWithCapacity: 1024];
1441 - initWithCapacity: (unsigned long) c
1443 self = [super init];
1446 dict = [NSMutableDictionary new];
1447 cglyphs = xmalloc (c * sizeof (CGGlyph));
1460 - (void) setString: (NSString *)str font: (NSFont *)font
1462 [dict setObject: font forKey: NSFontAttributeName];
1465 attrStr = [[NSAttributedString alloc] initWithString: str attributes: dict];
1466 maxChar = [str length];
1470 /* NSGlyphStorage protocol */
1471 - (NSUInteger)layoutOptions
1476 - (NSAttributedString *)attributedString
1481 - (void)insertGlyphs: (const NSGlyph *)glyphs length: (NSUInteger)length
1482 forStartingGlyphAtIndex: (NSUInteger)glyphIndex
1483 characterIndex: (NSUInteger)charIndex
1485 len = glyphIndex+length;
1486 for (i =glyphIndex; i<len; i++)
1487 cglyphs[i] = glyphs[i-glyphIndex];
1492 - (void)setIntAttribute: (NSInteger)attributeTag value: (NSInteger)val
1493 forGlyphAtIndex: (NSUInteger)glyphIndex
1499 #endif /* NS_IMPL_COCOA */
1504 ns_dump_glyphstring (struct glyph_string *s)
1508 fprintf (stderr, "Glyph string len = %d at (%d, %d) overhang (%d, %d),"
1509 "overlap = %d, bg_filled = %d:",
1510 s->nchars, s->x, s->y, s->left_overhang, s->right_overhang,
1511 s->row->overlapping_p, s->background_filled_p);
1512 for (i =0; i<s->nchars; i++)
1513 fprintf (stderr, "%c", s->first_glyph[i].u.ch);
1514 fprintf (stderr, "\n");
1519 syms_of_nsfont (void)
1521 nsfont_driver.type = Qns;
1522 register_font_driver (&nsfont_driver, NULL);
1523 DEFSYM (Qcondensed, "condensed");
1524 DEFSYM (Qexpanded, "expanded");
1525 DEFSYM (Qapple, "apple");
1526 DEFSYM (Qroman, "roman");
1527 DEFSYM (Qmedium, "medium");
1528 DEFVAR_LISP ("ns-reg-to-script", Vns_reg_to_script,
1529 doc: /* Internal use: maps font registry to Unicode script. */);
1531 ascii_printable = NULL;