diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2008-09-10 23:56:49 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2008-09-10 23:56:49 +0000 |
| commit | b6bde2e4569aa617c8a6af64947c688c624ed7f8 (patch) | |
| tree | 010d15843eb7d4faf7cd1b0cd44d5b9c00462a83 /src/fl_font_mac.cxx | |
| parent | dfb50e85292687561927610e689eb5ab30d0ba26 (diff) | |
Merging the UTF8 patch, consisting of O'ksi'd s original 1.1.6 patch and additions by Ian. PLEASE BE AWARE that the patch in its current incarnation is a regression in many aspects and further work is required before we can announce Unicode support.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6212 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/fl_font_mac.cxx')
| -rw-r--r-- | src/fl_font_mac.cxx | 241 |
1 files changed, 83 insertions, 158 deletions
diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx index 0914b1498..1b26b03d7 100644 --- a/src/fl_font_mac.cxx +++ b/src/fl_font_mac.cxx @@ -27,31 +27,15 @@ #include <config.h> +/* from fl_utf.c */ +extern unsigned fl_utf8toUtf16(const char* src, unsigned srclen, unsigned short* dst, unsigned dstlen); + Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { next = 0; # if HAVE_GL listbase = 0; # endif -#ifdef __APPLE_QD__ - knowMetrics = 0; - switch (*name++) { - case 'I': face = italic; break; - case 'P': face = italic | bold; break; - case 'B': face = bold; break; - default: face = 0; break; - } - unsigned char fn[80]; - fn[0] = strlen(name); strcpy((char*)(fn+1), name); - GetFNum(fn, &font); - size = Size; - FMInput fIn = { font, size, face, 0, 0, { 1, 1}, { 1, 1} }; - FMOutput *fOut = FMSwapFont(&fIn); - ascent = fOut->ascent; //: the following three lines give only temporary aproimations - descent = fOut->descent; - for (int i=0; i<256; i++) width[i] = fOut->widMax; - minsize = maxsize = size; -#elif defined(__APPLE_QUARTZ__) - knowWidths = 0; +// knowWidths = 0; // OpenGL needs those for its font handling q_name = strdup(name); size = Size; @@ -62,7 +46,8 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { q_width = Size*2/3; minsize = maxsize = Size; // now use ATS to get the actual Glyph size information - CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingASCII); + // say that our passed-in name is encoded as UTF-8, since this works for plain ASCII names too... + CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingUTF8); ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault); if (font) { ATSFontMetrics m = { 0 }; @@ -80,18 +65,22 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { 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 + // 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 = FloatToFixed(Size); - ATSUFontID fontID = FMGetFontFromATSFontRef(font); + Fixed fsize = IntToFixed(Size); +// ATSUFontID fontID = FMGetFontFromATSFontRef(font); + ATSUFontID fontID; + ATSUFindFontFromName(name, strlen(name), kFontFullName, kFontMacintoshPlatform, kFontRomanScript, kFontEnglishLanguage, &fontID); + + // draw the font upside-down... Compensate for fltk/OSX origin differences 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; + ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics | kATSLineDisableAllLayoutOperations; ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag }; ByteCount aBytes[] = { sizeof(ATSLineLayoutOptions) }; ATSUAttributeValuePtr aAttr[] = { &llo }; @@ -109,8 +98,15 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { descent = fd; //Size - ascent; } int w = FixedToInt(bAfter); - if (w) + if (w) q_width = FixedToInt(bAfter); + +#define ENABLE_TRANSIENT_FONTS 1 + +#ifdef ENABLE_TRANSIENT_FONTS + // Now, by way of experiment, try enabling Transient Font Matching, this will + // cause ATSU to find a suitable font to render any chars the current font can't do... + ATSUSetTransientFontMatching (layout, true); #endif } @@ -132,33 +128,13 @@ Fl_Font_Descriptor::~Fl_Font_Descriptor() { #endif */ if (this == fl_fontsize) fl_fontsize = 0; -#ifdef __APPLE_QUARTZ__ ATSUDisposeTextLayout(layout); ATSUDisposeStyle(style); -#endif } //////////////////////////////////////////////////////////////// static Fl_Fontdesc built_in_table[] = { -#ifdef __APPLE_QD__ -{" Arial"}, -{"BArial"}, -{"IArial"}, -{"PArial"}, -{" Courier New"}, -{"BCourier New"}, -{"ICourier New"}, -{"PCourier New"}, -{" Times New Roman"}, -{"BTimes New Roman"}, -{"ITimes New Roman"}, -{"PTimes New Roman"}, -{" Symbol"}, -{" Chicago"}, -{"BChicago"}, -{" Webdings"}, -#elif defined(__APPLE_QUARTZ__) {"Arial"}, {"Arial Bold"}, {"Arial Italic"}, @@ -175,74 +151,30 @@ static Fl_Fontdesc built_in_table[] = { {"Monaco"}, {"Andale Mono"}, // there is no bold Monaco font on standard Mac {"Webdings"}, -#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) +static UniChar *utfWbuf = 0; +static unsigned utfWlen = 0; + +static UniChar *mac_Utf8_to_Utf16(const char *txt, int len, int *new_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]; + unsigned wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen); + if(wlen >= utfWlen) + { + utfWlen = wlen + 100; + if(utfWbuf) free(utfWbuf); + utfWbuf = (UniChar*)malloc((utfWlen)*sizeof(UniChar)); + wlen = fl_utf8toUtf16(txt, len, (unsigned short*)utfWbuf, utfWlen); } - *dst = 0; - return utf16buf; -} -#endif + *new_len = wlen; + return utfWbuf; +} // mac_Utf8_to_Utf16 Fl_Fontdesc* fl_fonts = built_in_table; void fl_font(Fl_Font_Descriptor* s) { fl_fontsize = s; -#ifdef __APPLE_QD__ - if (fl_window) SetPort( GetWindowPort(fl_window) ); - TextFont(fl_fontsize->font); //: select font into current QuickDraw GC - TextFace(fl_fontsize->face); - TextSize(fl_fontsize->size); - if (!fl_fontsize->knowMetrics) { //: get the true metrics for the currnet GC - //: (fails on multiple monitors with different dpi's!) - FontInfo fi; GetFontInfo(&fi); - fl_fontsize->ascent = fi.ascent; - fl_fontsize->descent = fi.descent; - FMetricRec mr; FontMetrics(&mr); - short *f = (short*)*mr.wTabHandle; //: get the char size table - for (int i=0; i<256; i++) fl_fontsize->width[i] = f[2*i]; - fl_fontsize->knowMetrics = 1; - } -#elif defined(__APPLE_QUARTZ__) // we will use fl_fontsize later to access the required style and layout -#else -# error : need to defined either Quartz or Quickdraw -#endif } static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) { @@ -284,81 +216,59 @@ int fl_descent() { else return -1; } -double fl_width(const char* txt, int n) { -#ifdef __APPLE_QD__ - return (double)TextWidth( txt, 0, n ); -#else +double fl_width(const UniChar* txt, int n) { 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; + Fixed bBefore, bAfter, bAscent, bDescent; + ATSUTextLayout layout; + ByteCount iSize; + ATSUAttributeTag iTag; + ATSUAttributeValuePtr iValuePtr; + +// Here's my ATSU text measuring attempt... This seems to do the Right Thing + // now collect our ATSU resources and measure our text string + layout = fl_fontsize->layout; // activate the current GC - ByteCount iSize = sizeof(CGContextRef); - ATSUAttributeTag iTag = kATSUCGContextTag; - ATSUAttributeValuePtr iValuePtr=&fl_gc; + iSize = sizeof(CGContextRef); + iTag = kATSUCGContextTag; + 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; - } - int len = 0; - const char *src = txt; - for (int j=0; j<n; j++) { - unsigned char c = *src++; - len += fl_fontsize->width[c]; - } + err = ATSUSetTextPointerLocation(layout, txt, kATSUFromTextBeginning, n, n); + err = ATSUGetUnjustifiedBounds(layout, kATSUFromTextBeginning, n, &bBefore, &bAfter, &bAscent, &bDescent); + // If err is OK then return length, else return 0. Or something... + int len = FixedToInt(bAfter); return len; -#endif +} + +double fl_width(const char* txt, int n) { + int wc_len = n; + UniChar *uniStr = mac_Utf8_to_Utf16(txt, n, &wc_len); + return fl_width(uniStr, wc_len); } double fl_width(uchar c) { return fl_width((const char*)(&c), 1); } +double fl_width(unsigned int wc) { + return fl_width((const UniChar*)(&wc), 1); +} + 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__ - MoveTo(x, y); - DrawText((const char *)str, 0, n); -#elif defined(__APPLE_QUARTZ__) fl_draw(str, n, (float)x-0.0f, (float)y-0.5f); -#else -# error : neither Quartz no Quickdraw chosen -#endif } 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__) OSStatus err; - // convert to UTF-16 first - UniChar *uniStr = fl_macToUtf16(str, n); + // convert to UTF-16 first + UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n); // now collect our ATSU resources ATSUTextLayout layout = fl_fontsize->layout; @@ -369,11 +279,26 @@ void fl_draw(const char *str, int n, float x, float y) { err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n); err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x), FloatToFixed(y)); -#else -# error : neither Quartz no Quickdraw chosen -#endif } +void fl_rtl_draw(const char* c, int n, int x, int y) { +// I guess with ATSU the thing to do is force the layout mode to RTL and let ATSU draw the text... + double offs = fl_width(c, n); + OSStatus err; + // convert to UTF-16 first + UniChar *uniStr = mac_Utf8_to_Utf16(c, n, &n); + // now collect our ATSU resources + ATSUTextLayout layout = fl_fontsize->layout; + // reverse the layout direction + ATSUAttributeTag llo = kATSURightToLeftBaseDirection; // layout option + ByteCount iSize[] = {sizeof(ATSUAttributeTag), sizeof(CGContextRef)}; + ATSUAttributeTag iTag[] = {kATSULineDirectionTag, kATSUCGContextTag}; + ATSUAttributeValuePtr aAttr[] = { &llo, &fl_gc}; + ATSUSetLayoutControls (layout, 2, iTag, iSize, aAttr ); + + err = ATSUSetTextPointerLocation(layout, uniStr, kATSUFromTextBeginning, n, n); + err = ATSUDrawText(layout, kATSUFromTextBeginning, n, FloatToFixed(x-offs), FloatToFixed(y)); +} // // End of "$Id$". // |
