summaryrefslogtreecommitdiff
path: root/src/fl_font_mac.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/fl_font_mac.cxx')
-rw-r--r--src/fl_font_mac.cxx243
1 files changed, 158 insertions, 85 deletions
diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx
index ebcc5ca..b83c77f 100644
--- a/src/fl_font_mac.cxx
+++ b/src/fl_font_mac.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: fl_font_mac.cxx 4587 2005-10-09 16:27:45Z matt $"
+// "$Id: fl_font_mac.cxx 5651 2007-02-01 20:13:57Z matt $"
//
// MacOS font selection routines for the Fast Light Tool Kit (FLTK).
//
@@ -27,12 +27,6 @@
#include <config.h>
-//: MeasureText, FontMetrics, WidthTabHandle, GetSysFont, SysFontSize
-//: TextSize, TextFont
-//: GetFNum (theName: Str255; VAR familyID: Integer);
-//: FUNCTION FMSwapFont (inRec: FMInput): FMOutPtr;
-//: SetFractEnable
-
Fl_FontSize::Fl_FontSize(const char* name, int Size) {
next = 0;
# if HAVE_GL
@@ -57,24 +51,66 @@ Fl_FontSize::Fl_FontSize(const char* name, int Size) {
for (int i=0; i<256; i++) width[i] = fOut->widMax;
minsize = maxsize = size;
#elif defined(__APPLE_QUARTZ__)
+ knowWidths = 0;
+ // OpenGL needs those for its font handling
q_name = strdup(name);
size = Size;
+ OSStatus err;
+ // fill our structure with a few default values
ascent = Size*3/4;
descent = Size-ascent;
q_width = Size*2/3;
minsize = maxsize = Size;
- // Using ATS to get the genral Glyph size information
- CFStringRef cfname = CFStringCreateWithCString(0L, q_name, kCFStringEncodingASCII);
+ // now use ATS to get the actual Glyph size information
+ CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingASCII);
ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault);
if (font) {
ATSFontMetrics m = { 0 };
ATSFontGetHorizontalMetrics(font, kATSOptionFlagsDefault, &m);
- if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*size);
- // playing with the offsets a little to make standard sizes fit
- if (m.ascent) ascent = int(m.ascent*size-0.5f);
- if (m.descent) descent = -int(m.descent*size-1.5f);
+ if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*Size);
+ // playing with the offsets a little to make standard sizes fit
+ if (m.ascent) ascent = int(m.ascent*Size-0.5f);
+ if (m.descent) descent = -int(m.descent*Size-1.5f);
}
CFRelease(cfname);
+ // now we allocate everything needed to render text in this font later
+ // get us the default layout and style
+ err = ATSUCreateTextLayout(&layout);
+ UniChar mTxt[2] = { 65, 0 };
+ err = ATSUSetTextPointerLocation(layout, mTxt, kATSUFromTextBeginning, 1, 1);
+ err = ATSUCreateStyle(&style);
+ err = ATSUSetRunStyle(layout, style, kATSUFromTextBeginning, kATSUToTextEnd);
+ // now set the actual font, size and attributes. We also set the font matrix to
+ // render our font up-side-down, so when rendered through our inverted CGContext,
+ // text will appear normal again.
+ Fixed fsize = IntToFixed(Size);
+ ATSUFontID fontID = FMGetFontFromATSFontRef(font);
+ static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
+ ATSUAttributeTag sTag[] = { kATSUFontTag, kATSUSizeTag, kATSUFontMatrixTag };
+ ByteCount sBytes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(CGAffineTransform) };
+ ATSUAttributeValuePtr sAttr[] = { &fontID, &fsize, &font_mx };
+ err = ATSUSetAttributes(style, 3, sTag, sBytes, sAttr);
+ // next, make sure that Quartz will only render at integer coordinates
+ ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics|kATSLineDisableAllLayoutOperations;
+ ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag };
+ ByteCount aBytes[] = { sizeof(ATSLineLayoutOptions) };
+ ATSUAttributeValuePtr aAttr[] = { &llo };
+ err = ATSUSetLineControls (layout, kATSUFromTextBeginning, 1, aTag, aBytes, aAttr);
+ // now we are finally ready to measure some letter to get the bounding box
+ Fixed bBefore, bAfter, bAscent, bDescent;
+ err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent);
+ // Requesting a certain height font on Mac does not guarantee that ascent+descent
+ // equal the requested height. fl_height will reflect the actual height that we got.
+ // The font "Apple Chancery" is a pretty extreme example of overlapping letters.
+ float fa = -FixedToFloat(bAscent), fd = -FixedToFloat(bDescent);
+ if (fa>0.0f && fd>0.0f) {
+ //float f = Size/(fa+fd);
+ ascent = fa; //int(fa*f+0.5f);
+ descent = fd; //Size - ascent;
+ }
+ int w = FixedToInt(bAfter);
+ if (w)
+ q_width = FixedToInt(bAfter);
#endif
}
@@ -97,7 +133,8 @@ Fl_FontSize::~Fl_FontSize() {
*/
if (this == fl_fontsize) fl_fontsize = 0;
#ifdef __APPLE_QUARTZ__
- free(q_name);
+ ATSUDisposeTextLayout(layout);
+ ATSUDisposeStyle(style);
#endif
}
@@ -141,6 +178,47 @@ static Fl_Fontdesc built_in_table[] = {
#endif
};
+#ifdef __APPLE_QUARTZ__
+static UniChar utf16lut[128] = {
+ 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
+ 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
+ 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
+ 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
+ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
+ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
+ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
+ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
+ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
+ 0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
+ 0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
+ 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
+ 0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
+ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
+};
+static UniChar *utf16buf = 0;
+static int utf16len = 0;
+UniChar *fl_macToUtf16(const char *txt, int len)
+{
+ if ((len+1)>utf16len) {
+ utf16len = len+100;
+ free(utf16buf);
+ utf16buf = (UniChar*)malloc((utf16len+1)*sizeof(UniChar));
+ }
+ int i;
+ unsigned char c;
+ const unsigned char *src = (unsigned char const*)txt;
+ UniChar *dst = utf16buf;
+ for (i=0; i<len; i++) {
+ c = *src++;
+ *dst++ =(c<128) ? c : utf16lut[c-128];
+ }
+ *dst = 0;
+ return utf16buf;
+}
+#endif
+
Fl_Fontdesc* fl_fonts = built_in_table;
void fl_font(Fl_FontSize* s) {
@@ -161,9 +239,7 @@ void fl_font(Fl_FontSize* s) {
fl_fontsize->knowMetrics = 1;
}
#elif defined(__APPLE_QUARTZ__)
- if (!s) return;
- if (!fl_gc) return; // no worries, we will assign the font to the context later
- CGContextSelectFont(fl_gc, s->q_name, (float)s->size, kCGEncodingMacRoman);
+ // we will use fl_fontsize later to access the required style and layout
#else
# error : need to defined either Quartz or Quickdraw
#endif
@@ -188,6 +264,11 @@ int fl_font_ = 0;
int fl_size_ = 0;
void fl_font(int fnum, int size) {
+ if (fnum==-1) {
+ fl_font_ = 0;
+ fl_size_ = 0;
+ return;
+ }
fl_font_ = fnum;
fl_size_ = size;
fl_font(find(fnum, size));
@@ -203,88 +284,69 @@ int fl_descent() {
else return -1;
}
-// MRS: The default character set is MacRoman, which is different from
-// ISO-8859-1; in FLTK 2.0 we'll use UTF-8 with Quartz...
-
-static uchar macroman_lut[256] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
- 202, 193, 162, 163, 164, 180, 166, 164, 172, 169, 187, 199, 194, 173, 168, 248,
- 161, 177, 178, 179, 171, 181, 166, 225, 252, 185, 188, 200, 188, 189, 190, 192,
- 203, 231, 229, 204, 128, 129, 174, 130, 233, 131, 230, 232, 237, 234, 235, 236,
- 208, 132, 241, 238, 239, 205, 133, 215, 175, 244, 242, 243, 134, 221, 222, 167,
- 136, 135, 137, 139, 138, 140, 190, 141, 143, 142, 144, 145, 147, 146, 148, 149,
- 240, 150, 152, 151, 153, 155, 154, 214, 191, 157, 156, 158, 159, 253, 254, 216
-};
-
-static char *iso_buf = 0;
-static int n_iso_buf = 0;
-
-// this function must be available for OpenGL character drawing as well
-const char *fl_iso2macRoman(const char *s, int n) {
- // do not do a text lookup for 'Symbol' or 'WebDings'. This fails
- // if the user assigns a new font to these numbers though.
- if (fl_font_ == 12 || fl_font_ == 15)
- return s;
- if (n>n_iso_buf) {
- if (iso_buf) free(iso_buf);
- iso_buf = (char*)malloc(n+500);
- n_iso_buf = n;
- }
- uchar *src = (uchar*)s;
- uchar *dst = (uchar*)iso_buf;
- for (;n--;) {
- *dst++ = macroman_lut[*src++];
- }
- return iso_buf;
-}
-
-double fl_width(const char* c, int n) {
- const char *txt = fl_iso2macRoman(c, n);
+double fl_width(const char* txt, int n) {
#ifdef __APPLE_QD__
return (double)TextWidth( txt, 0, n );
#else
- if (!fl_gc) {
- Fl_Window *w = Fl::first_window();
- if (w) w->make_current();
- if (!fl_gc) return -1;
+ if (!fl_fontsize) {
+ fl_font(0, 12); // avoid a crash!
+ if (!fl_fontsize)
+ return 8*n; // user must select a font first!
+ }
+ if (!fl_fontsize->knowWidths) {
+ if (!fl_gc) {
+ Fl_Window *w = Fl::first_window();
+ if (w) w->make_current();
+ if (!fl_gc) {
+ if (fl_fontsize) return fl_fontsize->q_width*n;
+ return 8*n;
+ // We fall back to some internal QuickDraw port.
+ // The result should be the same.
+ }
+ }
+ char buf[2];
+ for (int i=0; i<256; i++) {
+ OSStatus err;
+ buf[0] = (char)i;
+ // convert to UTF-16 first
+ UniChar *uniStr = fl_macToUtf16(buf, 1);
+ // now collect our ATSU resources
+ ATSUTextLayout layout = fl_fontsize->layout;
+ // activate the current GC
+ ByteCount iSize = sizeof(CGContextRef);
+ ATSUAttributeTag iTag = kATSUCGContextTag;
+ ATSUAttributeValuePtr iValuePtr=&fl_gc;
+ ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr);
+ // now measure the bounding box
+ err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, 1, 1);
+ Fixed bBefore, bAfter, bAscent, bDescent;
+ err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, 1, &bBefore, &bAfter, &bAscent, &bDescent);
+ fl_fontsize->width[i] = FixedToInt(bAfter);
+ }
+ fl_fontsize->knowWidths = 1;
}
- // according to the Apple developer docs, this is the correct way to
- // find the length of a rendered text...
- CGContextSetTextPosition(fl_gc, 0, 0);
- CGContextSetTextDrawingMode(fl_gc, kCGTextInvisible);
- CGContextShowText(fl_gc, txt, n);
- CGContextSetTextDrawingMode(fl_gc, kCGTextFill);
- CGPoint p = CGContextGetTextPosition(fl_gc);
- return p.x;
+ int len = 0;
+ const char *src = txt;
+ for (int j=0; j<n; j++) {
+ unsigned char c = *src++;
+ len += fl_fontsize->width[c];
+ }
+ return len;
#endif
}
double fl_width(uchar c) {
-#ifdef __APPLE_QD__
- return (double)TextWidth((const char*)(macroman_lut + c), 0, 1 );
-#else
return fl_width((const char*)(&c), 1);
-#endif
}
void fl_draw(const char *str, int n, float x, float y);
void fl_draw(const char* str, int n, int x, int y) {
#ifdef __APPLE_QD__
- const char *txt = fl_iso2macRoman(str, n);
MoveTo(x, y);
- DrawText((const char *)txt, 0, n);
+ DrawText((const char *)str, 0, n);
#elif defined(__APPLE_QUARTZ__)
- fl_draw(str, n, (float)x, (float)y);
+ fl_draw(str, n, (float)x-0.0f, (float)y-0.5f);
#else
# error : neither Quartz no Quickdraw chosen
#endif
@@ -294,13 +356,24 @@ void fl_draw(const char *str, int n, float x, float y) {
#ifdef __APPLE_QD__
fl_draw(str, n, (int)x, (int)y);
#elif defined(__APPLE_QUARTZ__)
- const char *txt = fl_iso2macRoman(str, n);
- CGContextShowTextAtPoint(fl_gc, x, y, txt, n);
+ OSStatus err;
+ // convert to UTF-16 first
+ UniChar *uniStr = fl_macToUtf16(str, n);
+ // now collect our ATSU resources
+ ATSUTextLayout layout = fl_fontsize->layout;
+
+ ByteCount iSize = sizeof(CGContextRef);
+ ATSUAttributeTag iTag = kATSUCGContextTag;
+ ATSUAttributeValuePtr iValuePtr=&fl_gc;
+ ATSUSetLayoutControls(layout, 1, &iTag, &iSize, &iValuePtr);
+
+ err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n);
+ err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x), FloatToFixed(y));
#else
# error : neither Quartz no Quickdraw chosen
#endif
}
//
-// End of "$Id: fl_font_mac.cxx 4587 2005-10-09 16:27:45Z matt $".
+// End of "$Id: fl_font_mac.cxx 5651 2007-02-01 20:13:57Z matt $".
//