2 // "$Id: fl_font_mac.cxx 8597 2011-04-17 13:18:55Z ianmacarthur $"
4 // MacOS font selection routines for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2011 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
31 extern unsigned fl_utf8toUtf16(const char* src
, unsigned srclen
, unsigned short* dst
, unsigned dstlen
);
33 static CGAffineTransform font_mx
= { 1, 0, 0, -1, 0, 0 };
34 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
35 static CFMutableDictionaryRef attributes
= NULL
;
38 Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name
, Fl_Fontsize Size
) {
45 // OpenGL needs those for its font handling
46 q_name
= strdup(name
);
48 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
49 if (fl_mac_os_version
>= 100500) {//unfortunately, CTFontCreateWithName != NULL on 10.4 also!
50 CFStringRef str
= CFStringCreateWithCString(NULL
, name
, kCFStringEncodingUTF8
);
51 fontref
= CTFontCreateWithName(str
, size
, NULL
);
53 const UniChar A
[2]={'W','.'};
54 CTFontGetGlyphsForCharacters(fontref
, A
, glyph
, 2);
57 CTFontGetAdvancesForGlyphs(fontref
, kCTFontHorizontalOrientation
, glyph
, advances
, 2);
58 w
= advances
[0].width
;
59 if ( abs(advances
[0].width
- advances
[1].width
) < 1E-2 ) {//this is a fixed-width font
60 // slightly rescale fixed-width fonts so the character width has an integral value
62 CGFloat fsize
= size
/ ( w
/floor(w
+ 0.5) );
63 fontref
= CTFontCreateWithName(str
, fsize
, NULL
);
64 w
= CTFontGetAdvancesForGlyphs(fontref
, kCTFontHorizontalOrientation
, glyph
, NULL
, 1);
67 ascent
= (short)(CTFontGetAscent(fontref
) + 0.5);
68 descent
= (short)(CTFontGetDescent(fontref
) + 0.5);
70 for (unsigned i
= 0; i
< sizeof(width
)/sizeof(float*); i
++) width
[i
] = NULL
;
72 static CFNumberRef zero_ref
;
74 zero_ref
= CFNumberCreate(NULL
, kCFNumberFloat32Type
, &zero
);
75 // deactivate kerning for all fonts, so that string width = sum of character widths
76 // which allows fast fl_width() implementation.
77 attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
79 &kCFTypeDictionaryKeyCallBacks
,
80 &kCFTypeDictionaryValueCallBacks
);
81 CFDictionarySetValue (attributes
, kCTKernAttributeName
, zero_ref
);
83 if (ascent
== 0) { // this may happen with some third party fonts
84 CFDictionarySetValue (attributes
, kCTFontAttributeName
, fontref
);
85 CFAttributedStringRef mastr
= CFAttributedStringCreate(kCFAllocatorDefault
, CFSTR("Wj"), attributes
);
86 CTLineRef ctline
= CTLineCreateWithAttributedString(mastr
);
88 CGFloat fascent
, fdescent
;
89 CTLineGetTypographicBounds(ctline
, &fascent
, &fdescent
, NULL
);
91 ascent
= (short)(fascent
+ 0.5);
92 descent
= (short)(fdescent
+ 0.5);
99 // fill our structure with a few default values
101 descent
= Size
-ascent
;
103 // now use ATS to get the actual Glyph size information
104 // say that our passed-in name is encoded as UTF-8, since this works for plain ASCII names too...
105 CFStringRef cfname
= CFStringCreateWithCString(0L, name
, kCFStringEncodingUTF8
);
106 ATSFontRef font
= ATSFontFindFromName(cfname
, kATSOptionFlagsDefault
);
108 ATSFontMetrics m
= { 0 };
109 ATSFontGetHorizontalMetrics(font
, kATSOptionFlagsDefault
, &m
);
110 if (m
.avgAdvanceWidth
) q_width
= int(m
.avgAdvanceWidth
*Size
);
111 // playing with the offsets a little to make standard sizes fit
112 if (m
.ascent
) ascent
= int(m
.ascent
*Size
-0.5f
);
113 if (m
.descent
) descent
= -int(m
.descent
*Size
-1.5f
);
116 // now we allocate everything needed to render text in this font later
117 // get us the default layout and style
118 err
= ATSUCreateTextLayout(&layout
);
119 UniChar mTxt
[2] = { 65, 0 };
120 err
= ATSUSetTextPointerLocation(layout
, mTxt
, kATSUFromTextBeginning
, 1, 1);
121 err
= ATSUCreateStyle(&style
);
122 err
= ATSUSetRunStyle(layout
, style
, kATSUFromTextBeginning
, kATSUToTextEnd
);
123 // now set the actual font, size and attributes. We also set the font matrix to
124 // render our font up-side-down, so when rendered through our inverted CGContext,
125 // text will appear normal again.
126 Fixed fsize
= IntToFixed(Size
);
127 // ATSUFontID fontID = FMGetFontFromATSFontRef(font);
129 ATSUFindFontFromName(name
, strlen(name
), kFontFullName
, kFontMacintoshPlatform
, kFontRomanScript
, kFontEnglishLanguage
, &fontID
);
131 // draw the font upside-down... Compensate for fltk/OSX origin differences
132 ATSUAttributeTag sTag
[] = { kATSUFontTag
, kATSUSizeTag
, kATSUFontMatrixTag
};
133 ByteCount sBytes
[] = { sizeof(ATSUFontID
), sizeof(Fixed
), sizeof(CGAffineTransform
) };
134 ATSUAttributeValuePtr sAttr
[] = { &fontID
, &fsize
, &font_mx
};
135 err
= ATSUSetAttributes(style
, 3, sTag
, sBytes
, sAttr
);
136 // next, make sure that Quartz will only render at integer coordinates
137 ATSLineLayoutOptions llo
= kATSLineUseDeviceMetrics
| kATSLineDisableAllLayoutOperations
;
138 ATSUAttributeTag aTag
[] = { kATSULineLayoutOptionsTag
};
139 ByteCount aBytes
[] = { sizeof(ATSLineLayoutOptions
) };
140 ATSUAttributeValuePtr aAttr
[] = { &llo
};
141 err
= ATSUSetLineControls (layout
, kATSUFromTextBeginning
, 1, aTag
, aBytes
, aAttr
);
142 // now we are finally ready to measure some letter to get the bounding box
143 Fixed bBefore
, bAfter
, bAscent
, bDescent
;
144 err
= ATSUGetUnjustifiedBounds(layout
, kATSUFromTextBeginning
, 1, &bBefore
, &bAfter
, &bAscent
, &bDescent
);
145 // Requesting a certain height font on Mac does not guarantee that ascent+descent
146 // equal the requested height. fl_height will reflect the actual height that we got.
147 // The font "Apple Chancery" is a pretty extreme example of overlapping letters.
148 float fa
= -FixedToFloat(bAscent
), fd
= -FixedToFloat(bDescent
);
149 if (fa
>0.0f
&& fd
>0.0f
) {
150 //float f = Size/(fa+fd);
151 ascent
= int(fa
); //int(fa*f+0.5f);
152 descent
= int(fd
); //Size - ascent;
154 int w
= FixedToInt(bAfter
);
156 q_width
= FixedToInt(bAfter
);
158 # define ENABLE_TRANSIENT_FONTS 1
160 # ifdef ENABLE_TRANSIENT_FONTS
161 // Now, by way of experiment, try enabling Transient Font Matching, this will
162 // cause ATSU to find a suitable font to render any chars the current font can't do...
163 ATSUSetTransientFontMatching (layout
, true);
166 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
171 Fl_Font_Descriptor::~Fl_Font_Descriptor() {
174 // ++ todo: remove OpenGL font alocations
175 // Delete list created by gl_draw(). This is not done by this code
176 // as it will link in GL unnecessarily. There should be some kind
177 // of "free" routine pointer, or a subclass?
179 // int base = font->min_char_or_byte2;
180 // int size = font->max_char_or_byte2-base+1;
181 // int base = 0; int size = 256;
182 // glDeleteLists(listbase+base,size);
186 if (this == fl_graphics_driver
->font_descriptor()) fl_graphics_driver
->font_descriptor(NULL
);
187 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
188 if (fl_mac_os_version
>= 100500) {
190 for (unsigned i
= 0; i
< sizeof(width
)/sizeof(float*); i
++) {
191 if (width
[i
]) free(width
[i
]);
197 ////////////////////////////////////////////////////////////////
199 static Fl_Fontdesc built_in_table
[] = {
203 {"Arial Bold Italic"},
205 {"Courier New Bold"},
206 {"Courier New Italic"},
207 {"Courier New Bold Italic"},
209 {"Times New Roman Bold"},
210 {"Times New Roman Italic"},
211 {"Times New Roman Bold Italic"},
214 {"Andale Mono"}, // there is no bold Monaco font on standard Mac
218 static UniChar
*utfWbuf
= 0;
219 static unsigned utfWlen
= 0;
221 static UniChar
*mac_Utf8_to_Utf16(const char *txt
, int len
, int *new_len
)
223 unsigned wlen
= fl_utf8toUtf16(txt
, len
, (unsigned short*)utfWbuf
, utfWlen
);
226 utfWlen
= wlen
+ 100;
227 if (utfWbuf
) free(utfWbuf
);
228 utfWbuf
= (UniChar
*)malloc((utfWlen
)*sizeof(UniChar
));
229 wlen
= fl_utf8toUtf16(txt
, len
, (unsigned short*)utfWbuf
, utfWlen
);
233 } // mac_Utf8_to_Utf16
235 Fl_Fontdesc
* fl_fonts
= built_in_table
;
237 static Fl_Font_Descriptor
* find(Fl_Font fnum
, Fl_Fontsize size
) {
238 Fl_Fontdesc
* s
= fl_fonts
+fnum
;
239 if (!s
->name
) s
= fl_fonts
; // use 0 if fnum undefined
240 Fl_Font_Descriptor
* f
;
241 for (f
= s
->first
; f
; f
= f
->next
)
242 if (f
->size
== size
) return f
;
243 f
= new Fl_Font_Descriptor(s
->name
, size
);
249 ////////////////////////////////////////////////////////////////
252 void Fl_Quartz_Graphics_Driver::font(Fl_Font fnum
, Fl_Fontsize size
) {
254 Fl_Graphics_Driver::font(0, 0);
257 Fl_Graphics_Driver::font(fnum
, size
);
258 this->font_descriptor( find(fnum
, size
) );
261 int Fl_Quartz_Graphics_Driver::height() {
262 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
263 Fl_Font_Descriptor
*fl_fontsize
= font_descriptor();
264 return fl_fontsize
->ascent
+ fl_fontsize
->descent
;
267 int Fl_Quartz_Graphics_Driver::descent() {
268 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
269 Fl_Font_Descriptor
*fl_fontsize
= font_descriptor();
270 return fl_fontsize
->descent
+1;
273 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
274 // returns width of a pair of UniChar's in the surrogate range
275 static CGFloat
surrogate_width(const UniChar
*txt
, Fl_Font_Descriptor
*fl_fontsize
)
277 CTFontRef font2
= fl_fontsize
->fontref
;
278 bool must_release
= false;
280 bool b
= CTFontGetGlyphsForCharacters(font2
, txt
, glyphs
, 2);
282 if(!b
) { // the current font doesn't contain this char
283 CFStringRef str
= CFStringCreateWithCharactersNoCopy(NULL
, txt
, 2, kCFAllocatorNull
);
284 // find a font that contains it
285 font2
= CTFontCreateForString(font2
, str
, CFRangeMake(0,2));
288 b
= CTFontGetGlyphsForCharacters(font2
, txt
, glyphs
, 2);
290 if (b
) CTFontGetAdvancesForGlyphs(font2
, kCTFontHorizontalOrientation
, glyphs
, &a
, 1);
291 else a
.width
= fl_fontsize
->q_width
;
292 if(must_release
) CFRelease(font2
);
297 static double fl_mac_width(const UniChar
* txt
, int n
, Fl_Font_Descriptor
*fl_fontsize
) {
298 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
299 if (fl_mac_os_version
>= 100500) {
303 for (i
= 0; i
< n
; i
++) { // loop over txt
305 if (uni
>= 0xD800 && uni
<= 0xDBFF) { // handles the surrogate range
306 retval
+= surrogate_width(&txt
[i
], fl_fontsize
);
307 i
++; // because a pair of UniChar's represent a single character
310 const int block
= 0x10000 / (sizeof(fl_fontsize
->width
)/sizeof(float*)); // block size
311 // r: index of the character block containing uni
312 unsigned int r
= uni
>> 7; // change 7 if sizeof(width) is changed
313 if (!fl_fontsize
->width
[r
]) { // this character block has not been hit yet
314 //fprintf(stderr,"r=%d size=%d name=%s\n",r,fl_fontsize->size, fl_fontsize->q_name);
315 // allocate memory to hold width of each character in the block
316 fl_fontsize
->width
[r
] = (float*) malloc(sizeof(float) * block
);
317 UniChar ii
= r
* block
;
320 for (int j
= 0; j
< block
; j
++) { // loop over the block
321 CTFontRef font2
= fl_fontsize
->fontref
;
322 bool must_release
= false;
323 // ii spans all characters of this block
324 bool b
= CTFontGetGlyphsForCharacters(font2
, &ii
, &glyph
, 1);
325 if (!b
) { // the current font doesn't contain this char
326 CFStringRef str
= CFStringCreateWithCharactersNoCopy(NULL
, &ii
, 1, kCFAllocatorNull
);
327 // find a font that contains it
328 font2
= CTFontCreateForString(font2
, str
, CFRangeMake(0,1));
331 b
= CTFontGetGlyphsForCharacters(font2
, &ii
, &glyph
, 1);
333 if (b
) CTFontGetAdvancesForGlyphs(font2
, kCTFontHorizontalOrientation
, &glyph
, &advance_size
, 1);
334 else advance_size
.width
= 0.;
335 // the width of one character of this block of characters
336 fl_fontsize
->width
[r
][j
] = advance_size
.width
;
337 if (must_release
) CFRelease(font2
);
341 // sum the widths of all characters of txt
342 retval
+= fl_fontsize
->width
[r
][uni
& (block
-1)];
349 Fixed bBefore
, bAfter
, bAscent
, bDescent
;
350 ATSUTextLayout layout
;
352 ATSUAttributeTag iTag
;
353 ATSUAttributeValuePtr iValuePtr
;
355 // Here's my ATSU text measuring attempt... This seems to do the Right Thing
356 // now collect our ATSU resources and measure our text string
357 layout
= fl_fontsize
->layout
;
358 // activate the current GC
359 iSize
= sizeof(CGContextRef
);
360 iTag
= kATSUCGContextTag
;
362 ATSUSetLayoutControls(layout
, 1, &iTag
, &iSize
, &iValuePtr
);
363 // now measure the bounding box
364 err
= ATSUSetTextPointerLocation(layout
, txt
, kATSUFromTextBeginning
, n
, n
);
365 err
= ATSUGetUnjustifiedBounds(layout
, kATSUFromTextBeginning
, n
, &bBefore
, &bAfter
, &bAscent
, &bDescent
);
366 // If err is OK then return length, else return 0. Or something...
367 int len
= FixedToInt(bAfter
);
370 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
376 double Fl_Quartz_Graphics_Driver::width(const char* txt
, int n
) {
378 UniChar
*uniStr
= mac_Utf8_to_Utf16(txt
, n
, &wc_len
);
379 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
380 return fl_mac_width(uniStr
, wc_len
, font_descriptor());
383 double Fl_Quartz_Graphics_Driver::width(unsigned int wc
) {
384 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
393 // l = fl_utf8encode(wc, buf);
394 // l = (int)fl_utf8toUtf16(buf, l, utf16, 3);
395 l
= (int)fl_ucs_to_Utf16(wc
, utf16
, 3);
397 return fl_mac_width(utf16
, l
, font_descriptor());
400 // text extent calculation
401 void Fl_Quartz_Graphics_Driver::text_extents(const char *str8
, int n
, int &dx
, int &dy
, int &w
, int &h
) {
402 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
403 Fl_Font_Descriptor
*fl_fontsize
= font_descriptor();
404 UniChar
*txt
= mac_Utf8_to_Utf16(str8
, n
, &n
);
405 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
406 if (fl_mac_os_version
>= 100500) {
407 CFStringRef str16
= CFStringCreateWithCharactersNoCopy(NULL
, txt
, n
, kCFAllocatorNull
);
408 CFDictionarySetValue (attributes
, kCTFontAttributeName
, fl_fontsize
->fontref
);
409 CFAttributedStringRef mastr
= CFAttributedStringCreate(kCFAllocatorDefault
, str16
, attributes
);
411 CTLineRef ctline
= CTLineCreateWithAttributedString(mastr
);
413 CGContextSetTextPosition(fl_gc
, 0, 0);
414 CGContextSetShouldAntialias(fl_gc
, true);
415 CGRect rect
= CTLineGetImageBounds(ctline
, fl_gc
);
416 CGContextSetShouldAntialias(fl_gc
, false);
418 dx
= floor(rect
.origin
.x
+ 0.5);
419 dy
= floor(- rect
.origin
.y
- rect
.size
.height
+ 0.5);
420 w
= rect
.size
.width
+ 0.5;
421 h
= rect
.size
.height
+ 0.5;
427 ATSUTextLayout layout
;
429 ATSUAttributeTag iTag
;
430 ATSUAttributeValuePtr iValuePtr
;
432 // Here's my ATSU text measuring attempt... This seems to do the Right Thing
433 // now collect our ATSU resources and measure our text string
434 layout
= fl_fontsize
->layout
;
435 // activate the current GC
436 iSize
= sizeof(CGContextRef
);
437 iTag
= kATSUCGContextTag
;
439 ATSUSetLayoutControls(layout
, 1, &iTag
, &iSize
, &iValuePtr
);
440 // now measure the bounding box
441 err
= ATSUSetTextPointerLocation(layout
, txt
, kATSUFromTextBeginning
, n
, n
);
443 err
= ATSUMeasureTextImage(layout
, kATSUFromTextBeginning
, n
, 0, 0, &bbox
);
444 w
= bbox
.right
- bbox
.left
;
445 h
= bbox
.bottom
- bbox
.top
;
448 //printf("r: %d l: %d t: %d b: %d w: %d h: %d\n", bbox.right, bbox.left, bbox.top, bbox.bottom, w, h);
450 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
456 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
457 static CGColorRef
flcolortocgcolor(Fl_Color i
)
460 Fl::get_color(i
, r
, g
, b
);
461 CGFloat components
[4] = {r
/255.0f
, g
/255.0f
, b
/255.0f
, 1.};
462 static CGColorSpaceRef cspace
= NULL
;
463 if (cspace
== NULL
) {
464 cspace
= CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB
);
466 return CGColorCreate(cspace
, components
);
470 static void fl_mac_draw(const char *str
, int n
, float x
, float y
, Fl_Graphics_Driver
*driver
) {
471 // convert to UTF-16 first
472 UniChar
*uniStr
= mac_Utf8_to_Utf16(str
, n
, &n
);
473 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
474 if (fl_mac_os_version
>= 100500) {
475 CFStringRef str16
= CFStringCreateWithCharactersNoCopy(NULL
, uniStr
, n
, kCFAllocatorNull
);
476 if (str16
== NULL
) return; // shd not happen
477 CGColorRef color
= flcolortocgcolor(driver
->color());
478 CFDictionarySetValue (attributes
, kCTFontAttributeName
, driver
->font_descriptor()->fontref
);
479 CFDictionarySetValue (attributes
, kCTForegroundColorAttributeName
, color
);
480 CFAttributedStringRef mastr
= CFAttributedStringCreate(kCFAllocatorDefault
, str16
, attributes
);
483 CTLineRef ctline
= CTLineCreateWithAttributedString(mastr
);
485 CGContextSetTextMatrix(fl_gc
, font_mx
);
486 CGContextSetTextPosition(fl_gc
, x
, y
);
487 CGContextSetShouldAntialias(fl_gc
, true);
488 CTLineDraw(ctline
, fl_gc
);
489 CGContextSetShouldAntialias(fl_gc
, false);
495 // now collect our ATSU resources
496 ATSUTextLayout layout
= driver
->font_descriptor()->layout
;
498 ByteCount iSize
= sizeof(CGContextRef
);
499 ATSUAttributeTag iTag
= kATSUCGContextTag
;
500 ATSUAttributeValuePtr iValuePtr
=&fl_gc
;
501 ATSUSetLayoutControls(layout
, 1, &iTag
, &iSize
, &iValuePtr
);
503 err
= ATSUSetTextPointerLocation(layout
, uniStr
, kATSUFromTextBeginning
, n
, n
);
504 CGContextSetShouldAntialias(fl_gc
, true);
505 err
= ATSUDrawText(layout
, kATSUFromTextBeginning
, n
, FloatToFixed(x
), FloatToFixed(y
));
506 CGContextSetShouldAntialias(fl_gc
, false);
508 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
513 void Fl_Quartz_Graphics_Driver::draw(const char *str
, int n
, float x
, float y
) {
514 // avoid a crash if no font has been selected by user yet !
515 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
516 fl_mac_draw(str
, n
, x
, y
, this);
519 void Fl_Quartz_Graphics_Driver::draw(const char* str
, int n
, int x
, int y
) {
520 // avoid a crash if no font has been selected by user yet !
521 if (!font_descriptor()) font(FL_HELVETICA
, FL_NORMAL_SIZE
);
522 fl_mac_draw(str
, n
, (float)x
-0.0f
, (float)y
+0.5f
, this);
525 void Fl_Quartz_Graphics_Driver::draw(int angle
, const char *str
, int n
, int x
, int y
) {
526 CGContextSaveGState(fl_gc
);
527 CGContextTranslateCTM(fl_gc
, x
, y
);
528 CGContextRotateCTM(fl_gc
, - angle
*(M_PI
/180) );
530 CGContextRestoreGState(fl_gc
);
533 void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c
, int n
, int x
, int y
) {
535 text_extents(c
, n
, dx
, dy
, w
, h
);
536 draw(c
, n
, x
- w
- dx
, y
);
540 // End of "$Id: fl_font_mac.cxx 8597 2011-04-17 13:18:55Z ianmacarthur $".