1 /* Font back-end driver for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 2006-2012 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. */
29 #include "dispextern.h"
30 #include "composite.h"
31 #include "blockinput.h"
38 #include "character.h"
42 /* TODO: Drop once we can assume gnustep-gui 0.17.1. */
43 #ifdef NS_IMPL_GNUSTEP
44 #import
<AppKit
/NSFontDescriptor.h
>
47 #define NSFONT_TRACE
0
49 extern Lisp_Object Qns
;
50 extern Lisp_Object Qnormal
, Qbold
, Qitalic
, Qcondensed
, Qexpanded
;
51 static Lisp_Object Qapple
, Qroman
, Qmedium
;
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
;
57 /* font glyph and metrics caching functions, implemented at end */
58 static void ns_uni_to_glyphs
(struct nsfont_info
*font_info
,
60 static void ns_glyph_metrics
(struct nsfont_info
*font_info
,
64 /* ==========================================================================
68 ========================================================================== */
71 /* Replace spaces w/another character so emacs core font parsing routines
74 ns_escape_name
(char *name
)
76 int i
=0, len
=strlen
(name
);
83 /* Reconstruct spaces in a font family name passed through emacs. */
85 ns_unescape_name
(char *name
)
87 int i
=0, len
=strlen
(name
);
94 /* Extract family name from a font spec. */
96 ns_get_family
(Lisp_Object font_spec
)
98 Lisp_Object tem
= AREF
(font_spec
, FONT_FAMILY_INDEX
);
103 char *tmp
= xstrdup
(SDATA
(SYMBOL_NAME
(tem
)));
105 ns_unescape_name
(tmp
);
106 family
= [NSString stringWithUTF8String
: tmp
];
113 /* Return 0 if attr not set, else value (which might also be 0).
114 On Leopard 0 gets returned even on descriptors where the attribute
115 was never set, so there's no way to distinguish between unspecified
116 and set to not have. Callers should assume 0 means unspecified. */
118 ns_attribute_fvalue
(NSFontDescriptor
*fdesc
, NSString
*trait
)
120 NSDictionary
*tdict
= [fdesc objectForKey
: NSFontTraitsAttribute
];
121 NSNumber
*val
= [tdict objectForKey
: trait
];
122 return val
== nil ?
0.0 : [val floatValue
];
126 /* Converts FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, plus family and script/lang
127 to NSFont descriptor. Information under extra only needed for matching. */
128 #define STYLE_REF
100
129 static NSFontDescriptor
*
130 ns_spec_to_descriptor
(Lisp_Object font_spec
)
132 NSFontDescriptor
*fdesc
;
133 NSMutableDictionary
*fdAttrs
= [NSMutableDictionary new
];
134 NSMutableDictionary
*tdict
= [NSMutableDictionary new
];
135 NSString
*family
= ns_get_family
(font_spec
);
138 /* add each attr in font_spec to fdAttrs.. */
139 n
= min (FONT_WEIGHT_NUMERIC
(font_spec
), 200);
140 if (n
!= -1 && n
!= STYLE_REF
)
141 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0) / 100.0]
142 forKey
: NSFontWeightTrait
];
143 n
= min (FONT_SLANT_NUMERIC
(font_spec
), 200);
144 if (n
!= -1 && n
!= STYLE_REF
)
145 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0) / 100.0]
146 forKey
: NSFontSlantTrait
];
147 n
= min (FONT_WIDTH_NUMERIC
(font_spec
), 200);
148 if (n
> -1 && (n
> STYLE_REF
+ 10 || n
< STYLE_REF
- 10))
149 [tdict setObject
: [NSNumber numberWithFloat
: (n
- 100.0) / 100.0]
150 forKey
: NSFontWidthTrait
];
151 if ([tdict count
] > 0)
152 [fdAttrs setObject
: tdict forKey
: NSFontTraitsAttribute
];
154 fdesc
= [NSFontDescriptor fontDescriptorWithFontAttributes
: fdAttrs
];
157 fdesc
= [fdesc fontDescriptorWithFamily
: family
];
166 /* Converts NSFont descriptor to FONT_WEIGHT, FONT_SLANT, FONT_WIDTH, etc.. */
168 ns_descriptor_to_entity
(NSFontDescriptor
*desc
,
172 Lisp_Object font_entity
= font_make_entity
();
173 /* NSString *psName = [desc postscriptName]; */
174 NSString
*family
= [desc objectForKey
: NSFontFamilyAttribute
];
175 unsigned int traits
= [desc symbolicTraits
];
178 /* Shouldn't happen, but on Tiger fallback desc gets name but no family. */
180 family
= [desc objectForKey
: NSFontNameAttribute
];
182 family
= [[NSFont userFixedPitchFontOfSize
: 0] familyName
];
184 escapedFamily
= xstrdup
([family UTF8String
]);
185 ns_escape_name
(escapedFamily
);
187 ASET
(font_entity
, FONT_TYPE_INDEX
, Qns
);
188 ASET
(font_entity
, FONT_FOUNDRY_INDEX
, Qapple
);
189 ASET
(font_entity
, FONT_FAMILY_INDEX
, intern
(escapedFamily
));
190 ASET
(font_entity
, FONT_ADSTYLE_INDEX
, style ? intern
(style
) : Qnil
);
191 ASET
(font_entity
, FONT_REGISTRY_INDEX
, Qiso10646_1
);
193 FONT_SET_STYLE
(font_entity
, FONT_WEIGHT_INDEX
,
194 traits
& NSFontBoldTrait ? Qbold
: Qmedium
);
195 /* FONT_SET_STYLE (font_entity, FONT_WEIGHT_INDEX,
196 make_number (100 + 100
197 * ns_attribute_fvalue (desc, NSFontWeightTrait)));*/
198 FONT_SET_STYLE
(font_entity
, FONT_SLANT_INDEX
,
199 traits
& NSFontItalicTrait ? Qitalic
: Qnormal
);
200 /* FONT_SET_STYLE (font_entity, FONT_SLANT_INDEX,
201 make_number (100 + 100
202 * ns_attribute_fvalue (desc, NSFontSlantTrait)));*/
203 FONT_SET_STYLE
(font_entity
, FONT_WIDTH_INDEX
,
204 traits
& NSFontCondensedTrait ? Qcondensed
:
205 traits
& NSFontExpandedTrait ? Qexpanded
: Qnormal
);
206 /* FONT_SET_STYLE (font_entity, FONT_WIDTH_INDEX,
207 make_number (100 + 100
208 * ns_attribute_fvalue (desc, NSFontWidthTrait)));*/
210 ASET
(font_entity
, FONT_SIZE_INDEX
, make_number
(0));
211 ASET
(font_entity
, FONT_AVGWIDTH_INDEX
, make_number
(0));
212 ASET
(font_entity
, FONT_SPACING_INDEX
,
213 make_number
([desc symbolicTraits
] & NSFontMonoSpaceTrait
214 ? FONT_SPACING_MONO
: FONT_SPACING_PROPORTIONAL
));
216 ASET
(font_entity
, FONT_EXTRA_INDEX
, extra
);
217 ASET
(font_entity
, FONT_OBJLIST_INDEX
, Qnil
);
221 fprintf (stderr
, "created font_entity
:\n "
);
222 debug_print
(font_entity
);
225 xfree
(escapedFamily
);
230 /* Default font entity. */
232 ns_fallback_entity
(void
)
234 return ns_descriptor_to_entity
([[NSFont userFixedPitchFontOfSize
: 0]
235 fontDescriptor
], Qnil
, NULL);
239 /* Utility: get width of a char c in screen font sfont */
241 ns_char_width
(NSFont
*sfont
, int c
)
244 NSString
*cstr
= [NSString stringWithFormat
: @"
%c", c];
246 NSGlyph glyph
= [sfont glyphWithName
: cstr
];
249 float w
= [sfont advancementForGlyph
: glyph
].width
;
255 NSDictionary
*attrsDictionary
=
256 [NSDictionary dictionaryWithObject
: sfont forKey
: NSFontAttributeName
];
257 w
= [cstr sizeWithAttributes
: attrsDictionary
].width
;
263 /* Return whether set1 covers set2 to a reasonable extent given by pct.
264 We check, out of each 16 Unicode char range containing chars in set2,
265 whether at least one character is present in set1.
266 This must be true for pct of the pairs to consider it covering. */
268 ns_charset_covers
(NSCharacterSet
*set1
, NSCharacterSet
*set2
, float pct
)
270 const unsigned short
*bytes1
= [[set1 bitmapRepresentation
] bytes
];
271 const unsigned short
*bytes2
= [[set2 bitmapRepresentation
] bytes
];
272 int i
, off
= 0, tot
= 0;
274 for (i
=0; i
<4096; i
++, bytes1
++, bytes2
++)
278 if (*bytes1
== 0) // *bytes1
& *bytes2
!= *bytes2
281 //fprintf(stderr
, "off
= %d\ttot = %d\n", off,tot);
282 return (float
)off
/ tot
< 1.0 - pct
;
286 /* Convert :lang property to a script. Use of :lang property by font backend
287 seems to be limited for now (2009/05) to ja, zh, and ko. */
289 *ns_lang_to_script
(Lisp_Object lang
)
291 if (!strcmp (SDATA
(SYMBOL_NAME
(lang
)), "ja"
))
293 /* NOTE: ja given for any hanzi that's also a kanji, but Chinese fonts
294 have more characters. */
295 else if (!strcmp (SDATA
(SYMBOL_NAME
(lang
)), "zh"
))
297 else if (!strcmp (SDATA
(SYMBOL_NAME
(lang
)), "ko"
))
304 /* Convert OTF 4-letter script code to emacs script name. (Why can't
305 everyone just use some standard Unicode names for these?) */
307 *ns_otf_to_script
(Lisp_Object otf
)
309 Lisp_Object
script = assq_no_quit
(XCAR
(otf
), Votf_script_alist
);
310 return CONSP
(script)
311 ?
[NSString stringWithUTF8String
: SDATA
(SYMBOL_NAME
(XCDR
((script))))]
316 /* Convert a font registry, such as */
318 *ns_registry_to_script
(char *reg
)
320 Lisp_Object
script, r
, rts
= Vns_reg_to_script
;
323 r
= XCAR
(XCAR
(rts
));
324 if (!strncmp
(SDATA
(r
), reg
, strlen
(SDATA
(r
))))
326 script = XCDR
(XCAR
(rts
));
327 return [NSString stringWithUTF8String
: SDATA
(SYMBOL_NAME
(script))];
335 /* Searches the :script, :lang, and :otf extra-bundle properties of the spec,
336 plus registry regular property, for something that can be mapped to a
337 Unicode script. Empty string returned if no script spec found. */
339 *ns_get_req_script
(Lisp_Object font_spec
)
341 Lisp_Object reg
= AREF
(font_spec
, FONT_REGISTRY_INDEX
);
342 Lisp_Object extra
= AREF
(font_spec
, FONT_EXTRA_INDEX
);
344 /* The extra-bundle properties have priority. */
345 for ( ; CONSP
(extra
); extra
= XCDR
(extra
))
347 Lisp_Object tmp
= XCAR
(extra
);
350 Lisp_Object key
= XCAR
(tmp
), val
= XCDR
(tmp
);
351 if (EQ
(key
, QCscript
) && SYMBOLP
(val
))
352 return [NSString stringWithUTF8String
:
353 SDATA
(SYMBOL_NAME
(val
))];
354 if (EQ
(key
, QClang
) && SYMBOLP
(val
))
355 return ns_lang_to_script
(val
);
356 if (EQ
(key
, QCotf
) && CONSP
(val
) && SYMBOLP
(XCAR
(val
)))
357 return ns_otf_to_script
(val
);
361 /* If we get here, check the charset portion of the registry. */
364 /* XXX: iso10646 is passed in for non-ascii latin-1 characters
365 (which causes box rendering if we don't treat it like iso8858-1)
366 but also for ascii (which causes unnecessary font substitution). */
368 if (EQ
(reg
, Qiso10646_1
))
371 return ns_registry_to_script
(SDATA
(SYMBOL_NAME
(reg
)));
378 /* This small function is static in fontset.c. If it can be made public for
379 all ports, remove this, but otherwise it doesn't seem worth the ifdefs. */
381 accumulate_script_ranges
(Lisp_Object arg
, Lisp_Object range
, Lisp_Object val
)
383 if (EQ
(XCAR
(arg
), val
))
386 XSETCDR
(arg
, Fcons
(Fcons
(XCAR
(range
), XCDR
(range
)), XCDR
(arg
)));
388 XSETCDR
(arg
, Fcons
(Fcons
(range
, range
), XCDR
(arg
)));
393 /* Use the Unicode range information in Vchar_script_table to convert a script
394 name into an NSCharacterSet. */
395 static NSCharacterSet
396 *ns_script_to_charset
(NSString
*scriptName
)
398 NSMutableCharacterSet
*charset
= [NSMutableCharacterSet new
];
399 Lisp_Object
script = intern
([scriptName UTF8String
]);
400 Lisp_Object script_list
= XCHAR_TABLE
(Vchar_script_table
)->extras
[0];
402 if (! NILP
(Fmemq
(script, script_list
)))
404 Lisp_Object ranges
, range_list
;
406 ranges
= Fcons
(script, Qnil
);
407 map_char_table
(accumulate_script_ranges
, Qnil
, Vchar_script_table
,
409 range_list
= Fnreverse
(XCDR
(ranges
));
410 if (! NILP
(range_list
))
412 for (; CONSP
(range_list
); range_list
= XCDR
(range_list
))
414 int start
= XINT
(XCAR
(XCAR
(range_list
)));
415 int
end = XINT
(XCDR
(XCAR
(range_list
)));
417 debug_print
(XCAR
(range_list
));
419 [charset addCharactersInRange
:
420 NSMakeRange
(start
, end-start
)];
428 /* Return an array of font families containing characters for the given
429 script, for the given coverage criterion, including at least LastResort.
430 Results are cached by script for faster access.
431 If none are found, we reduce the percentage and try again, until 5%.
432 This provides a font with at least some characters if such can be found.
433 We don't use isSupersetOfSet: because (a) it doesn't work on Tiger, and
434 (b) need approximate match as fonts covering full Unicode ranges are rare. */
436 *ns_get_covering_families
(NSString
*script, float pct
)
438 static NSMutableDictionary
*scriptToFamilies
= nil
;
439 NSMutableSet
*families
;
442 NSLog
(@"Request covering families
for script: '%@'"
, script);
444 if (scriptToFamilies
== nil
)
445 scriptToFamilies
= [[NSMutableDictionary alloc
] init
];
447 if ((families
= [scriptToFamilies objectForKey
: script]) == nil
)
449 NSFontManager
*fontMgr
= [NSFontManager sharedFontManager
];
450 NSArray
*allFamilies
= [fontMgr availableFontFamilies
];
452 if ([script length] == 0)
453 families
= [NSMutableSet setWithArray
: allFamilies
];
456 NSCharacterSet
*charset
= ns_script_to_charset
(script);
458 families
= [NSMutableSet setWithCapacity
: 10];
461 NSEnumerator
*allFamiliesEnum
= [allFamilies objectEnumerator
];
462 while (family
= [allFamiliesEnum nextObject
])
464 NSCharacterSet
*fset
= [[fontMgr fontWithFamily
: family
465 traits
: 0 weight
: 5 size: 12.0] coveredCharacterSet
];
466 /* Some fonts on OS X, maybe many on GNUstep, return nil. */
468 fset
= [NSCharacterSet characterSetWithRange
:
469 NSMakeRange
(0, 127)];
470 if (ns_charset_covers
(fset
, charset
, pct
))
471 [families addObject
: family
];
474 if ([families count
] > 0 || pct
< 0.05)
480 if ([families count
] == 0)
481 [families addObject
: @"LastResort"
];
483 [scriptToFamilies setObject
: families forKey
: script];
487 NSLog
(@" returning
%d families", [families count]);
492 /* Implementation for list() and match(). List() can return nil, match()
493 must return something. Strategy is to drop family name from attribute
494 matching set for match. */
496 ns_findfonts
(Lisp_Object font_spec
, BOOL isMatch
)
498 Lisp_Object tem
, list
= Qnil
;
499 NSFontDescriptor
*fdesc
, *desc
;
501 NSArray
*matchingDescs
;
509 fprintf (stderr
, "nsfont
: %s for fontspec:\n ",
510 (isMatch ? "match"
: "list"
));
511 debug_print
(font_spec
);
514 cFamilies
= ns_get_covering_families
(ns_get_req_script
(font_spec
), 0.90);
516 fdesc
= ns_spec_to_descriptor
(font_spec
);
517 fkeys
= [NSMutableSet setWithArray
: [[fdesc fontAttributes
] allKeys
]];
519 [fkeys removeObject
: NSFontFamilyAttribute
];
521 matchingDescs
= [fdesc matchingFontDescriptorsWithMandatoryKeys
: fkeys
];
523 NSLog
(@"Got desc
%@ and found %d matching fonts from it: ", fdesc,
524 [matchingDescs count
]);
526 for (dEnum
= [matchingDescs objectEnumerator
]; desc
= [dEnum nextObject
]; )
528 if (![cFamilies containsObject
:
529 [desc objectForKey
: NSFontFamilyAttribute
]])
531 tem
= ns_descriptor_to_entity
(desc
,
532 AREF
(font_spec
, FONT_EXTRA_INDEX
),
536 list
= Fcons
(tem
, list
);
537 if (fabs
(ns_attribute_fvalue
(desc
, NSFontSlantTrait
)) > 0.05)
541 /* Add synthItal member if needed. */
542 family
= [fdesc objectForKey
: NSFontFamilyAttribute
];
543 if (family
!= nil
&& !foundItal
&& XINT
(Flength
(list
)) > 0)
545 NSFontDescriptor
*s1
= [NSFontDescriptor new
];
546 NSFontDescriptor
*sDesc
547 = [[s1 fontDescriptorWithSymbolicTraits
: NSFontItalicTrait
]
548 fontDescriptorWithFamily
: family
];
549 list
= Fcons
(ns_descriptor_to_entity
(sDesc
,
550 AREF
(font_spec
, FONT_EXTRA_INDEX
),
555 /* Return something if was a match and nothing found. */
557 return ns_fallback_entity
();
560 fprintf (stderr
, " Returning
%"pI"d entities.\n",
561 XINT
(Flength
(list
)));
568 /* ==========================================================================
570 Font driver implementation
572 ========================================================================== */
575 static Lisp_Object nsfont_get_cache
(FRAME_PTR frame
);
576 static Lisp_Object nsfont_list
(Lisp_Object frame
, Lisp_Object font_spec
);
577 static Lisp_Object nsfont_match
(Lisp_Object frame
, Lisp_Object font_spec
);
578 static Lisp_Object nsfont_list_family
(Lisp_Object frame
);
579 static Lisp_Object nsfont_open
(FRAME_PTR f
, Lisp_Object font_entity
,
581 static void nsfont_close
(FRAME_PTR f
, struct font
*font
);
582 static int nsfont_has_char
(Lisp_Object entity
, int c
);
583 static unsigned int nsfont_encode_char
(struct font
*font
, int c
);
584 static int nsfont_text_extents
(struct font
*font
, unsigned int
*code
,
585 int nglyphs
, struct font_metrics
*metrics
);
586 static int nsfont_draw
(struct glyph_string
*s
, int from
, int to
, int x
, int y
,
587 int with_background
);
589 struct font_driver nsfont_driver
=
592 1, /* case sensitive */
597 NULL, /*free_entity */
600 NULL, /* prepare_face */
601 NULL, /* done_face */
606 /* excluded: get_bitmap, free_bitmap, get_outline, free_outline,
607 anchor_point, otf_capability, otf_driver,
608 start_for_frame, end_for_frame, shape */
612 /* Return a cache of font-entities on FRAME. The cache must be a
613 cons whose cdr part is the actual cache area. */
615 nsfont_get_cache
(FRAME_PTR frame
)
617 Display_Info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(frame
);
618 return (dpyinfo
->name_list_element
);
622 /* List fonts exactly matching with FONT_SPEC on FRAME. The value is a
623 **list** of font-entities. This and match () are sole APIs that allocate
624 font-entities. Properties to be considered (2009/05/19) are:
625 regular: foundry, family, adstyle, registry
626 extended: script, lang, otf
627 "Extended" properties are not part of the vector but get stored as
628 lisp properties under FONT_EXTRA_INDEX.
630 The returned entities should have type set (to 'ns), plus the following:
631 foundry, family, adstyle, registry,
632 weight, slant, width, size (0 if scalable),
633 dpi, spacing, avgwidth (0 if scalable) */
635 nsfont_list
(Lisp_Object frame
, Lisp_Object font_spec
)
637 return ns_findfonts
(font_spec
, NO
);
641 /* Return a font entity most closely matching with FONT_SPEC on
642 FRAME. The closeness is determined by the font backend, thus
643 `face-font-selection-order' is ignored here.
644 Properties to be considered are same as for list(). */
646 nsfont_match
(Lisp_Object frame
, Lisp_Object font_spec
)
648 return ns_findfonts
(font_spec
, YES
);
652 /* List available families. The value is a list of family names
655 nsfont_list_family
(Lisp_Object frame
)
657 Lisp_Object list
= Qnil
;
658 NSEnumerator
*families
=
659 [[[NSFontManager sharedFontManager
] availableFontFamilies
]
662 while (family
= [families nextObject
])
663 list
= Fcons
(intern
([family UTF8String
]), list
);
664 /* FIXME: escape the name? */
667 fprintf (stderr
, "nsfont
: list families returning
%"pI"d entries\n",
668 XINT
(Flength
(list
)));
674 /* Open a font specified by FONT_ENTITY on frame F. If the font is
675 scalable, open it with PIXEL_SIZE. */
677 nsfont_open
(FRAME_PTR f
, Lisp_Object font_entity
, int pixel_size
)
680 unsigned int traits
= 0;
681 struct nsfont_info
*font_info
;
683 NSFontDescriptor
*fontDesc
= ns_spec_to_descriptor
(font_entity
);
684 NSFontManager
*fontMgr
= [NSFontManager sharedFontManager
];
686 NSFont
*nsfont
, *sfont
;
689 Lisp_Object font_object
;
692 static NSMutableDictionary
*fontCache
= nil
;
695 /* 2008/03/08: The same font may end up being requested for different
696 entities, due to small differences in numeric values or other issues,
697 or for different copies of the same entity. Therefore we cache to
698 avoid creating multiple struct font objects (with metrics cache, etc.)
699 for the same NSFont object. */
700 if (fontCache
== nil
)
701 fontCache
= [[NSMutableDictionary alloc
] init
];
705 fprintf (stderr
, "nsfont
: open
size %d of fontentity:\n ", pixel_size);
706 debug_print
(font_entity
);
711 /* try to get it out of frame params */
712 Lisp_Object tem
= get_frame_param
(f
, Qfontsize
);
713 pixel_size
= NILP
(tem
) ?
0 : XFASTINT
(tem
);
716 tem
= AREF
(font_entity
, FONT_ADSTYLE_INDEX
);
717 synthItal
= !NILP
(tem
) && !strncmp
("synthItal"
, SDATA
(SYMBOL_NAME
(tem
)),
719 family
= ns_get_family
(font_entity
);
721 family
= [[NSFont userFixedPitchFontOfSize
: 0] familyName
];
722 /* Should be > 0.23 as some font descriptors (e.g. Terminus) set to that
723 when setting family in ns_spec_to_descriptor(). */
724 if (ns_attribute_fvalue
(fontDesc
, NSFontWeightTrait
) > 0.50)
725 traits |
= NSBoldFontMask
;
726 if (fabs
(ns_attribute_fvalue
(fontDesc
, NSFontSlantTrait
) > 0.05))
727 traits |
= NSItalicFontMask
;
729 /* see http://cocoadev.com/forums/comments.php?DiscussionID=74 */
730 fixLeopardBug
= traits
& NSBoldFontMask ?
10 : 5;
731 nsfont
= [fontMgr fontWithFamily
: family
732 traits
: traits weight
: fixLeopardBug
734 /* if didn't find, try synthetic italic */
735 if (nsfont
== nil
&& synthItal
)
737 nsfont
= [fontMgr fontWithFamily
: family
738 traits
: traits
& ~NSItalicFontMask
739 weight
: fixLeopardBug
size: pixel_size
];
742 /* LastResort not really a family */
743 if (nsfont
== nil
&& [@"LastResort" isEqualToString
: family
])
744 nsfont
= [NSFont fontWithName
: @"LastResort"
size: pixel_size
];
749 message_with_string
("
*** Warning
: font in family
'%s' not found"
,
750 build_string
([family UTF8String
]), 1);
751 nsfont
= [NSFont userFixedPitchFontOfSize
: pixel_size
];
755 NSLog
(@"
%@\n", nsfont);
757 /* Check the cache */
758 cached
= [fontCache objectForKey
: nsfont
];
759 if (cached
!= nil
&& !synthItal
)
762 fprintf(stderr
, "
*** nsfont_open CACHE HIT
!\n"
);
763 /* FIXME: Cast from (unsigned long) to Lisp_Object. */
764 XHASH
(font_object
) = [cached unsignedLongValue
];
769 font_object
= font_make_object
(VECSIZE
(struct nsfont_info
),
770 font_entity
, pixel_size
);
772 [fontCache setObject
: [NSNumber numberWithUnsignedLong
:
773 (unsigned
long) XHASH
(font_object
)]
777 font_info
= (struct nsfont_info
*) XFONT_OBJECT
(font_object
);
778 font
= (struct font
*) font_info
;
780 return Qnil
; /* FIXME: other terms do, but return Qnil causes segfault */
782 font_info
->glyphs
= xzalloc
(0x100 * sizeof
*font_info
->glyphs
);
783 font_info
->metrics
= xzalloc
(0x100 * sizeof
*font_info
->metrics
);
788 sfont
= [nsfont screenFont
];
792 /* non-metric backend font struct fields */
793 font
= (struct font
*) font_info
;
794 font
->pixel_size
= [sfont pointSize
];
795 font
->driver
= &nsfont_driver
;
796 font
->encoding_type
= FONT_ENCODING_NOT_DECIDED
;
797 font
->encoding_charset
= -1;
798 font
->repertory_charset
= -1;
799 font
->default_ascent
= 0;
800 font
->vertical_centering
= 0;
801 font
->baseline_offset
= 0;
802 font
->relative_compose
= 0;
803 font
->font_encoder
= NULL;
805 font
->props
[FONT_FORMAT_INDEX
] = Qns
;
806 font
->props
[FONT_FILE_INDEX
] = Qnil
;
809 const
char *fontName
= [[nsfont fontName
] UTF8String
];
810 int len
= strlen
(fontName
);
812 /* The values specified by fonts are not always exact. For
813 * example, a 6x8 font could specify that the descender is
814 * -2.00000405... (represented by 0xc000000220000000). Without
815 * adjustment, the code below would round the descender to -3,
816 * resulting in a font that would be one pixel higher than
818 CGFloat adjusted_descender
= [sfont descender
] + 0.0001;
820 #ifdef NS_IMPL_GNUSTEP
821 font_info
->nsfont
= sfont
;
823 font_info
->nsfont
= nsfont
;
825 [font_info
->nsfont retain
];
827 /* set up ns_font (defined in nsgui.h) */
828 font_info
->name
= xstrdup
(fontName
);
829 font_info
->bold
= [fontMgr traitsOfFont
: nsfont
] & NSBoldFontMask
;
831 synthItal ||
([fontMgr traitsOfFont
: nsfont
] & NSItalicFontMask
);
833 /* Metrics etc.; some fonts return an unusually large max advance, so we
834 only use it for fonts that have wide characters. */
835 font_info
->width
= ([sfont numberOfGlyphs
] > 2000) ?
836 [sfont maximumAdvancement
].width
: ns_char_width
(sfont
, '0');
838 brect
= [sfont boundingRectForFont
];
840 font_info
->underpos
= [sfont underlinePosition
];
841 font_info
->underwidth
= [sfont underlineThickness
];
842 font_info
->size = font
->pixel_size
;
845 font_info
->max_bounds.ascent
= lrint
([sfont ascender
]);
846 /* Descender is usually negative. Use floor to avoid
847 clipping descenders. */
848 font_info
->max_bounds.descent
= -lrint
(floor(adjusted_descender
));
850 font_info
->max_bounds.ascent
+ font_info
->max_bounds.descent
;
851 font_info
->max_bounds.width
= lrint
(font_info
->width
);
852 font_info
->max_bounds.lbearing
= lrint
(brect.origin.x
);
853 font_info
->max_bounds.rbearing
=
854 lrint
(brect.
size.width
- font_info
->width
);
857 /* set up synthItal and the CG font */
858 font_info
->synthItal
= synthItal
;
860 ATSFontRef atsFont
= ATSFontFindFromPostScriptName
861 ((CFStringRef
)[nsfont fontName
], kATSOptionFlagsDefault
);
863 if (atsFont
== kATSFontRefUnspecified
)
865 /* see if we can get it by dropping italic (then synthesizing) */
866 atsFont
= ATSFontFindFromPostScriptName
((CFStringRef
)
867 [[fontMgr convertFont
: nsfont toNotHaveTrait
: NSItalicFontMask
]
868 fontName
], kATSOptionFlagsDefault
);
869 if (atsFont
!= kATSFontRefUnspecified
)
870 font_info
->synthItal
= YES
;
873 /* last resort fallback */
874 atsFont
= ATSFontFindFromPostScriptName
875 ((CFStringRef
)@"Monaco"
, kATSOptionFlagsDefault
);
878 font_info
->cgfont
= CGFontCreateWithPlatformFont
((void
*)&atsFont
);
882 /* set up metrics portion of font struct */
883 font
->ascent
= lrint
([sfont ascender
]);
884 font
->descent
= -lrint
(floor(adjusted_descender
));
885 font
->min_width
= ns_char_width
(sfont
, '|');
886 font
->space_width
= lrint
(ns_char_width
(sfont
, ' '));
887 font
->average_width
= lrint
(font_info
->width
);
888 font
->max_width
= lrint
(font_info
->max_bounds.width
);
889 font
->height
= lrint
(font_info
->height
);
890 font
->underline_position
= lrint
(font_info
->underpos
);
891 font
->underline_thickness
= lrint
(font_info
->underwidth
);
893 font
->props
[FONT_NAME_INDEX
] = Ffont_xlfd_name
(font_object
, Qnil
);
894 font
->props
[FONT_FULLNAME_INDEX
] =
895 make_unibyte_string
(font_info
->name
, strlen
(font_info
->name
));
903 /* Close FONT on frame F. */
905 nsfont_close
(FRAME_PTR f
, struct font
*font
)
907 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
910 /* FIXME: this occurs apparently due to same failure to detect same font
911 that causes need for cache in nsfont_open () */
915 for (i
=0; i
<0x100; i
++)
917 xfree
(font_info
->glyphs
[i
]);
918 xfree
(font_info
->metrics
[i
]);
920 [font_info
->nsfont release
];
922 CGFontRelease
(font_info
->cgfont
);
924 xfree
(font_info
->name
);
929 /* If FONT_ENTITY has a glyph for character C (Unicode code point),
930 return 1. If not, return 0. If a font must be opened to check
933 nsfont_has_char
(Lisp_Object entity
, int c
)
939 /* Return a glyph code of FONT for character C (Unicode code point).
940 If FONT doesn't have such a glyph, return FONT_INVALID_CODE. */
942 nsfont_encode_char
(struct font
*font
, int c
)
944 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
945 unsigned
char high
= (c
& 0xff00) >> 8, low
= c
& 0x00ff;
949 return FONT_INVALID_CODE
;
951 /* did we already cache this block? */
952 if (!font_info
->glyphs
[high
])
953 ns_uni_to_glyphs
(font_info
, high
);
955 g
= font_info
->glyphs
[high
][low
];
956 return g
== 0xFFFF ? FONT_INVALID_CODE
: g
;
960 /* Perform the size computation of glyphs of FONT and fill in members
961 of METRICS. The glyphs are specified by their glyph codes in
962 CODE (length NGLYPHS). */
964 nsfont_text_extents
(struct font
*font
, unsigned int
*code
, int nglyphs
,
965 struct font_metrics
*metrics
)
967 struct nsfont_info
*font_info
= (struct nsfont_info
*)font
;
968 struct font_metrics
*pcm
;
969 unsigned
char high
, low
;
973 memset
(metrics
, 0, sizeof
(struct font_metrics
));
975 for (i
=0; i
<nglyphs
; i
++)
977 /* get metrics for this glyph, filling cache if need be */
978 /* TODO: get metrics for whole string from an NSLayoutManager
980 high
= (code
[i
] & 0xFF00) >> 8;
981 low
= code
[i
] & 0x00FF;
982 if (!font_info
->metrics
[high
])
983 ns_glyph_metrics
(font_info
, high
);
984 pcm
= &(font_info
->metrics
[high
][low
]);
986 if (metrics
->lbearing
> totalWidth
+ pcm
->lbearing
)
987 metrics
->lbearing
= totalWidth
+ pcm
->lbearing
;
988 if (metrics
->rbearing
< totalWidth
+ pcm
->rbearing
)
989 metrics
->rbearing
= totalWidth
+ pcm
->rbearing
;
990 if (metrics
->ascent
< pcm
->ascent
)
991 metrics
->ascent
= pcm
->ascent
;
992 if (metrics
->descent
< pcm
->descent
)
993 metrics
->descent
= pcm
->descent
;
995 totalWidth
+= pcm
->width
;
998 metrics
->width
= totalWidth
;
1000 return totalWidth
; /* not specified in doc, but xfont.c does it */
1004 /* Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
1005 position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
1006 is nonzero, fill the background in advance. It is assured that
1007 WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars). */
1009 nsfont_draw
(struct glyph_string
*s
, int from
, int to
, int x
, int y
,
1010 int with_background
)
1011 /* NOTE: focus and clip must be set
1012 also, currently assumed (true in nsterm.m call) from ==0, to ==nchars */
1014 static
char cbuf
[1024];
1016 #ifdef NS_IMPL_GNUSTEP
1017 static float advances
[1024];
1018 float
*adv
= advances
;
1020 static CGSize advances
[1024];
1021 CGSize
*adv
= advances
;
1025 struct nsfont_info
*font
= ns_tmp_font
;
1026 NSColor
*col
, *bgCol
;
1027 unsigned short
*t
= s
->char2b
;
1029 char isComposite
= s
->first_glyph
->type == COMPOSITE_GLYPH
;
1030 int
end = isComposite ? s
->cmp_to
: s
->nchars
;
1032 /* Select face based on input flags */
1033 switch (ns_tmp_flags
)
1035 case NS_DUMPGLYPH_CURSOR
:
1038 case NS_DUMPGLYPH_MOUSEFACE
:
1039 face
= FACE_FROM_ID
(s
->f
, MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
1041 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
1048 if (s
->face
->box
!= FACE_NO_BOX
&& s
->first_glyph
->left_box_line_p
)
1049 r.origin.x
+= abs (s
->face
->box_line_width
);
1052 r.
size.height
= FONT_HEIGHT
(font
);
1054 /* Convert UTF-16 (?) to UTF-8 and determine advances. Note if we just ask
1055 NS to render the string, it will come out differently from the individual
1056 character widths added up because of layout processing. */
1059 int cwidth
, twidth
= 0;
1061 /* FIXME: composition: no vertical displacement is considered. */
1062 t
+= s
->cmp_from
; /* advance into composition */
1063 for (i
= s
->cmp_from
; i
< end; i
++, t
++)
1065 hi
= (*t
& 0xFF00) >> 8;
1069 if (!s
->first_glyph
->u.cmp.automatic
)
1070 cwidth
= s
->cmp
->offsets
[i
* 2] /* (H offset) */ - twidth
;
1073 Lisp_Object gstring
= composition_gstring_from_id
(s
->cmp_id
);
1074 Lisp_Object glyph
= LGSTRING_GLYPH
(gstring
, i
);
1075 if (NILP
(LGLYPH_ADJUSTMENT
(glyph
)))
1076 cwidth
= LGLYPH_WIDTH
(glyph
);
1079 cwidth
= LGLYPH_WADJUST
(glyph
);
1080 #ifdef NS_IMPL_GNUSTEP
1081 *(adv
-1) += LGLYPH_XOFF
(glyph
);
1083 (*(adv
-1)).width
+= LGLYPH_XOFF
(glyph
);
1090 if (!font
->metrics
[hi
]) /* FIXME: why/how can we need this now? */
1091 ns_glyph_metrics
(font
, hi
);
1092 cwidth
= font
->metrics
[hi
][lo
].width
;
1095 #ifdef NS_IMPL_GNUSTEP
1097 CHAR_STRING_ADVANCE
(*t
, c
); /* this converts the char to UTF-8 */
1099 (*adv
++).width
= cwidth
;
1102 len
= adv
- advances
;
1103 r.
size.width
= twidth
;
1107 /* fill background if requested */
1108 if (with_background
&& !isComposite
)
1111 int fibw
= FRAME_INTERNAL_BORDER_WIDTH
(s
->f
);
1112 int mbox_line_width
= max (s
->face
->box_line_width
, 0);
1114 if (s
->row
->full_width_p
)
1116 if (br.origin.x
<= fibw
+ 1 + mbox_line_width
)
1118 br.
size.width
+= br.origin.x
- mbox_line_width
;
1119 br.origin.x
= mbox_line_width
;
1121 if (FRAME_PIXEL_WIDTH
(s
->f
) - (br.origin.x
+ br.
size.width
)
1123 br.
size.width
+= fibw
;
1125 if (s
->face
->box
== FACE_NO_BOX
)
1127 /* expand unboxed top row over internal border */
1128 if (br.origin.y
<= fibw
+ 1 + mbox_line_width
)
1130 br.
size.height
+= br.origin.y
;
1136 int correction
= abs (s
->face
->box_line_width
)+1;
1137 br.origin.y
+= correction
;
1138 br.
size.height
-= 2*correction
;
1139 br.origin.x
+= correction
;
1140 br.
size.width
-= 2*correction
;
1143 if (!s
->face
->stipple
)
1144 [(NS_FACE_BACKGROUND
(face
) != 0
1145 ? ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
)
1146 : FRAME_BACKGROUND_COLOR
(s
->f
)) set];
1149 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(s
->f
);
1150 [[dpyinfo
->bitmaps
[face
->stipple
-1].img stippleMask
] set];
1156 /* set up for character rendering */
1157 r.origin.y
= s
->ybase
;
1159 col
= (NS_FACE_FOREGROUND
(face
) != 0
1160 ? ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), s
->f
)
1161 : FRAME_FOREGROUND_COLOR
(s
->f
));
1162 /* FIXME: find another way to pass this */
1163 bgCol
= (ns_tmp_flags
!= NS_DUMPGLYPH_FOREGROUND ? nil
1164 : (NS_FACE_BACKGROUND
(face
) != 0
1165 ? ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
)
1166 : FRAME_BACKGROUND_COLOR
(s
->f
)));
1168 /* render under GNUstep using DPS */
1169 #ifdef NS_IMPL_GNUSTEP
1171 NSGraphicsContext
*context
= GSCurrentContext
();
1176 /* do erase if "foreground" mode */
1180 DPSmoveto
(context
, r.origin.x
, r.origin.y
);
1181 /*[context GSSetTextDrawingMode: GSTextFillStroke]; /// not implemented yet */
1182 DPSxshow
(context
, cbuf
, advances
, len
);
1183 DPSstroke
(context
);
1185 /*[context GSSetTextDrawingMode: GSTextFill]; /// not implemented yet */
1190 /* draw with DPSxshow () */
1191 DPSmoveto
(context
, r.origin.x
, r.origin.y
);
1192 DPSxshow
(context
, cbuf
, advances
, len
);
1193 DPSstroke
(context
);
1195 DPSgrestore
(context
);
1198 #
else /* NS_IMPL_COCOA */
1200 CGContextRef gcontext
=
1201 [[NSGraphicsContext currentContext
] graphicsPort
];
1202 static CGAffineTransform fliptf
;
1203 static BOOL firstTime
= YES
;
1208 fliptf
= CGAffineTransformMakeScale
(1.0, -1.0);
1211 CGContextSaveGState
(gcontext
);
1213 fliptf.c
= font
->synthItal ? Fix2X
(kATSItalicQDSkew
) : 0.0;
1215 CGContextSetFont
(gcontext
, font
->cgfont
);
1216 CGContextSetFontSize
(gcontext
, font
->size);
1217 if (NILP
(ns_antialias_text
) || font
->size <= ns_antialias_threshold
)
1218 CGContextSetShouldAntialias
(gcontext
, 0);
1220 CGContextSetShouldAntialias
(gcontext
, 1);
1222 CGContextSetTextMatrix
(gcontext
, fliptf
);
1226 /* foreground drawing; erase first to avoid overstrike */
1228 CGContextSetTextDrawingMode
(gcontext
, kCGTextFillStroke
);
1229 CGContextSetTextPosition
(gcontext
, r.origin.x
, r.origin.y
);
1230 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
, advances
, len
);
1231 CGContextSetTextDrawingMode
(gcontext
, kCGTextFill
);
1236 CGContextSetTextPosition
(gcontext
, r.origin.x
, r.origin.y
);
1237 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
+ s
->cmp_from
,
1240 if (face
->overstrike
)
1242 CGContextSetTextPosition
(gcontext
, r.origin.x
+0.5, r.origin.y
);
1243 CGContextShowGlyphsWithAdvances
(gcontext
, s
->char2b
+ s
->cmp_from
,
1247 CGContextRestoreGState
(gcontext
);
1249 #endif
/* NS_IMPL_COCOA */
1251 /* Draw underline, overline, strike-through. */
1252 ns_draw_text_decoration
(s
, face
, col
, r.
size.width
, r.origin.x
);
1259 /* ==========================================================================
1261 Font glyph and metrics caching functions
1263 ========================================================================== */
1265 /* Find and cache corresponding glyph codes for unicode values in given
1266 hi-byte block of 256. */
1268 ns_uni_to_glyphs
(struct nsfont_info
*font_info
, unsigned
char block
)
1270 #ifdef NS_IMPL_COCOA
1271 static EmacsGlyphStorage
*glyphStorage
;
1272 static
char firstTime
= 1;
1274 unichar
*unichars
= xmalloc
(0x101 * sizeof
(unichar
));
1275 unsigned int i
, g
, idx
;
1276 unsigned short
*glyphs
;
1279 fprintf (stderr
, "
%p\tFinding glyphs for glyphs in block %d\n",
1284 #ifdef NS_IMPL_COCOA
1288 glyphStorage
= [[EmacsGlyphStorage alloc
] initWithCapacity
: 0x100];
1292 font_info
->glyphs
[block
] = xmalloc
(0x100 * sizeof
(unsigned short
));
1293 if (!unichars ||
!(font_info
->glyphs
[block
]))
1296 /* create a string containing all Unicode characters in this block */
1297 for (idx
= block
<<8, i
= 0; i
< 0x100; idx
++, i
++)
1298 if (idx
< 0xD800 || idx
> 0xDFFF)
1301 unichars
[i
] = 0xFEFF;
1302 unichars
[0x100] = 0;
1305 #ifdef NS_IMPL_COCOA
1306 NSString
*allChars
= [[NSString alloc
]
1307 initWithCharactersNoCopy
: unichars
1310 NSGlyphGenerator
*glyphGenerator
= [NSGlyphGenerator sharedGlyphGenerator
];
1311 /*NSCharacterSet *coveredChars = [nsfont coveredCharacterSet]; */
1312 unsigned int numGlyphs
= [font_info
->nsfont numberOfGlyphs
];
1313 NSUInteger gInd
= 0, cInd
= 0;
1315 [glyphStorage setString
: allChars font
: font_info
->nsfont
];
1316 [glyphGenerator generateGlyphsForGlyphStorage
: glyphStorage
1317 desiredNumberOfCharacters
: glyphStorage
->maxChar
1318 glyphIndex
: &gInd characterIndex
: &cInd
];
1320 glyphs
= font_info
->glyphs
[block
];
1321 for (i
= 0; i
< 0x100; i
++, glyphs
++)
1323 #ifdef NS_IMPL_GNUSTEP
1326 g
= glyphStorage
->cglyphs
[i
];
1327 /* TODO: is this a good check? maybe need to use coveredChars.. */
1329 g
= 0xFFFF; /* hopefully unused... */
1334 #ifdef NS_IMPL_COCOA
1344 /* Determine and cache metrics for corresponding glyph codes in given
1345 hi-byte block of 256. */
1347 ns_glyph_metrics
(struct nsfont_info
*font_info
, unsigned
char block
)
1350 unsigned int numGlyphs
= [font_info
->nsfont numberOfGlyphs
];
1352 struct font_metrics
*metrics
;
1355 fprintf (stderr
, "
%p\tComputing metrics for glyphs in block %d\n",
1358 #ifdef NS_IMPL_GNUSTEP
1359 /* not implemented yet (as of startup 0.18), so punt */
1361 numGlyphs
= 0x10000;
1365 sfont
= [font_info
->nsfont screenFont
];
1367 font_info
->metrics
[block
] = xzalloc
(0x100 * sizeof
(struct font_metrics
));
1368 if (!(font_info
->metrics
[block
]))
1371 metrics
= font_info
->metrics
[block
];
1372 for (g
= block
<<8, i
=0; i
<0x100 && g
< numGlyphs
; g
++, i
++, metrics
++)
1375 NSRect r
= [sfont boundingRectForGlyph
: g
];
1377 w
= max ([sfont advancementForGlyph
: g
].width
, 2.0);
1378 metrics
->width
= lrint
(w
);
1381 rb
= r.
size.width
- w
;
1383 metrics
->lbearing
= round (lb
);
1384 if (font_info
->ital
)
1385 rb
+= 0.22 * font_info
->height
;
1386 metrics
->rbearing
= lrint
(w
+ rb
);
1388 metrics
->descent
= r.origin.y
< 0 ?
-r.origin.y
: 0;
1389 /*lrint (hshrink * [sfont ascender] + expand * hd/2); */
1390 metrics
->ascent
= r.
size.height
- metrics
->descent
;
1391 /*-lrint (hshrink* [sfont descender] - expand * hd/2); */
1397 #ifdef NS_IMPL_COCOA
1398 /* helper for font glyph setup */
1399 @implementation EmacsGlyphStorage
1403 return [self initWithCapacity
: 1024];
1406 - initWithCapacity
: (unsigned
long) c
1408 self
= [super init
];
1411 dict
= [NSMutableDictionary new
];
1412 cglyphs
= xmalloc
(c
* sizeof
(CGGlyph
));
1425 - (void
) setString
: (NSString
*)str font
: (NSFont
*)font
1427 [dict setObject
: font forKey
: NSFontAttributeName
];
1430 attrStr
= [[NSAttributedString alloc
] initWithString
: str attributes
: dict
];
1431 maxChar
= [str
length];
1435 /* NSGlyphStorage protocol */
1436 - (NSUInteger
)layoutOptions
1441 - (NSAttributedString
*)attributedString
1446 - (void
)insertGlyphs
: (const NSGlyph
*)glyphs
length: (NSUInteger
)length
1447 forStartingGlyphAtIndex
: (NSUInteger
)glyphIndex
1448 characterIndex
: (NSUInteger
)charIndex
1450 len
= glyphIndex
+length;
1451 for (i
=glyphIndex
; i
<len
; i
++)
1452 cglyphs
[i
] = glyphs
[i
-glyphIndex
];
1457 - (void
)setIntAttribute
: (NSInteger
)attributeTag value
: (NSInteger
)val
1458 forGlyphAtIndex
: (NSUInteger
)glyphIndex
1464 #endif
/* NS_IMPL_COCOA */
1469 ns_dump_glyphstring
(struct glyph_string
*s
)
1473 fprintf (stderr
, "Glyph string len
= %d at (%d, %d) overhang (%d, %d),"
1474 "overlap
= %d, bg_filled = %d:",
1475 s
->nchars
, s
->x
, s
->y
, s
->left_overhang
, s
->right_overhang
,
1476 s
->row
->overlapping_p
, s
->background_filled_p
);
1477 for (i
=0; i
<s
->nchars
; i
++)
1478 fprintf (stderr
, "
%c", s->first_glyph[i].u.ch);
1479 fprintf (stderr
, "
\n"
);
1484 syms_of_nsfont
(void
)
1486 nsfont_driver.
type = Qns
;
1487 register_font_driver
(&nsfont_driver
, NULL);
1488 DEFSYM
(Qapple
, "apple"
);
1489 DEFSYM
(Qroman
, "roman"
);
1490 DEFSYM
(Qmedium
, "medium"
);
1491 DEFVAR_LISP
("ns
-reg
-to
-script"
, Vns_reg_to_script
,
1492 doc: /* Internal use: maps font registry to Unicode script. */);