diff options
Diffstat (limited to 'src/fl_font_xft.cxx')
| -rw-r--r-- | src/fl_font_xft.cxx | 168 |
1 files changed, 156 insertions, 12 deletions
diff --git a/src/fl_font_xft.cxx b/src/fl_font_xft.cxx index e0d0fbf0c..0425cafeb 100644 --- a/src/fl_font_xft.cxx +++ b/src/fl_font_xft.cxx @@ -90,9 +90,11 @@ Fl_Fontdesc* fl_fonts = built_in_table; Fl_Font fl_font_ = 0; Fl_Fontsize fl_size_ = 0; -XFontStruct* fl_xfont = 0; +//XFontStruct* fl_xfont = 0; +XUtf8FontStruct* fl_xfont = 0; void *fl_xftfont = 0; -const char* fl_encoding_ = "iso8859-1"; +//const char* fl_encoding_ = "iso8859-1"; +const char* fl_encoding_ = "iso10646-1"; Fl_Font_Descriptor* fl_fontsize = 0; void fl_font(Fl_Font fnum, Fl_Fontsize size) { @@ -101,15 +103,15 @@ void fl_font(Fl_Font fnum, Fl_Fontsize size) { return; } if (fnum == fl_font_ && size == fl_size_ - && fl_fontsize - && !strcasecmp(fl_fontsize->encoding, fl_encoding_)) + && fl_fontsize) +// && !strcasecmp(fl_fontsize->encoding, fl_encoding_)) return; fl_font_ = fnum; fl_size_ = size; Fl_Fontdesc *font = fl_fonts + fnum; Fl_Font_Descriptor* f; // search the fontsizes we have generated already for (f = font->first; f; f = f->next) { - if (f->size == size && !strcasecmp(f->encoding, fl_encoding_)) + if (f->size == size)// && !strcasecmp(f->encoding, fl_encoding_)) break; } if (!f) { @@ -164,7 +166,7 @@ static XftFont* fontopen(const char* name, bool core) { default: name--; // no prefix, restore name } - if(comma_count) { // multiple comma-spearated names were passed + if(comma_count) { // multiple comma-separated names were passed char *local_name = strdup(name); // duplicate the full name so we can edit the copy char *curr = local_name; // points to first name in string char *nxt; // next name in string @@ -203,6 +205,7 @@ static XftFont* fontopen(const char* name, bool core) { XftPatternAddInteger(fnt_pat, XFT_SLANT, slant); XftPatternAddDouble (fnt_pat, XFT_PIXEL_SIZE, (double)fl_size_); XftPatternAddString (fnt_pat, XFT_ENCODING, fl_encoding_); + if (core) { XftPatternAddBool(fnt_pat, XFT_CORE, FcTrue); XftPatternAddBool(fnt_pat, XFT_RENDER, FcFalse); @@ -210,16 +213,67 @@ static XftFont* fontopen(const char* name, bool core) { XftPattern *match_pat; // the best available match on the system XftResult match_result; // the result of our matching attempt + // query the system to find a match for this font match_pat = XftFontMatch(fl_display, fl_screen, fnt_pat, &match_result); + +#if 0 // the XftResult never seems to get set to anything... abandon this code? + switch(match_result) { // how good a match is this font for our request? + case XftResultMatch: + puts("Object exists with the specified ID"); + break; + + case XftResultTypeMismatch: + puts("Object exists, but the type does not match"); + break; + + case XftResultNoId: + puts("Object exists, but has fewer values than specified"); + break; + + case FcResultOutOfMemory: + puts("FcResult: Malloc failed"); + break; + + case XftResultNoMatch: + puts("Object does not exist at all"); + break; + + default: + printf("Invalid XftResult status %d \n", match_result); + break; + } +#endif + +#if 0 // diagnostic to print the "full name" of the font we matched. This works. + FcChar8 *picked_name = FcNameUnparse(match_pat); + printf("Match: %s\n", picked_name); + free(picked_name); +#endif + // open the matched font the_font = XftFontOpenPattern(fl_display, match_pat); - // Tidy up the resources we allocated + +#if 0 // diagnostic to print the "full name" of the font we actually opened. This works. + FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern); + printf("Open : %s\n", picked_name2); + free(picked_name2); +#endif + XftPatternDestroy(fnt_pat); // XftPatternDestroy(match_pat); // FontConfig will destroy this resource for us. We must not! + return the_font; } else { // We were passed a font name in XLFD format + /* OksiD's X font code could handle being passed a comma separated list + * of XLFD's. It then attempted to find which font was "best" from this list. + * But XftFontOpenXlfd can not do this, so if a list is passed, we just + * terminate it at the first comma. + * A "better" solution might be to use XftXlfdParse() on each of the passed + * XLFD's to construct a "super-pattern" that incorporates attributes from all + * XLFD's and use that to perform a XftFontMatch(). Maybe... + */ char *local_name = strdup(name); if(comma_count) { // This means we were passed multiple XLFD's char *pc = strchr(local_name, ','); @@ -227,12 +281,18 @@ static XftFont* fontopen(const char* name, bool core) { } XftFont *the_font = XftFontOpenXlfd(fl_display, fl_screen, local_name); free(local_name); +#if 0 // diagnostic to print the "full name" of the font we actually opened. This works. +puts("Font Opened"); fflush(stdout); + FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern); + printf("Open : %s\n", picked_name2); fflush(stdout); + free(picked_name2); +#endif return the_font; } } // end of fontopen Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) { - encoding = fl_encoding_; +// encoding = fl_encoding_; size = fl_size_; #if HAVE_GL listbase = 0; @@ -258,7 +318,7 @@ int fl_descent() { double fl_width(const char *str, int n) { if (!current_font) return -1.0; XGlyphInfo i; - XftTextExtents8(fl_display, current_font, (XftChar8 *)str, n, &i); + XftTextExtentsUtf8(fl_display, current_font, (XftChar8 *)str, n, &i); return i.xOff; } @@ -266,6 +326,17 @@ double fl_width(uchar c) { return fl_width((const char *)(&c), 1); } +double fl_width(FcChar32 *str, int n) { + if (!current_font) return -1.0; + XGlyphInfo i; + XftTextExtents32(fl_display, current_font, str, n, &i); + return i.xOff; +} + +double fl_width(unsigned int c) { + return fl_width((FcChar32 *)(&c), 1); +} + #if HAVE_GL /* This code is used by opengl to get a bitmapped font. The original XFT-1 code * used XFT's "core" fonts methods to load an XFT font that was actually a @@ -313,6 +384,7 @@ static XFontStruct* load_xfont_for_xft2(void) { snprintf(xlfd, 128, "-*-*%s*-%s-%c-*--*-%d-*-*-*-*-*-*", name, weight, slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); // attempt to load the font at the right size } +//puts(xlfd); free(pc); // release our copy of the font name // if we have nothing loaded, try a generic proportional font @@ -325,6 +397,9 @@ static XFontStruct* load_xfont_for_xft2(void) { snprintf(xlfd, 128, "-*-courier-medium-%c-*--*-%d-*-*-*-*-*-*", slant, (size*10)); xgl_font = XLoadQueryFont(fl_display, xlfd); } +//printf("glf: %d\n%s\n%s\n", size, xlfd, fl_fonts[fl_font_].name); +//if(xgl_font) puts("ok"); + // Last chance fallback - this usually loads something... if (!xgl_font) xgl_font = XLoadQueryFont(fl_display, "fixed"); @@ -341,10 +416,10 @@ XFontStruct* fl_xxfont() { static int glfont = -1; // Do we need to load a new font? if ((!xgl_font) || (glsize != fl_size_) || (glfont != fl_font_)) { - if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it + // create a dummy XLFD for some font of the appropriate size... + if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea glsize = fl_size_; // record current font size glfont = fl_font_; // and face - // create a dummy XLFD for some font of the appropriate size... xgl_font = load_xfont_for_xft2(); } return xgl_font; @@ -417,13 +492,82 @@ void fl_draw(const char *str, int n, int x, int y) { color.color.blue = ((int)b)*0x101; color.color.alpha = 0xffff; - XftDrawString8(draw, &color, current_font, x, y, (XftChar8 *)str, n); + XftDrawStringUtf8(draw, &color, current_font, x, y, (XftChar8 *)str, n); } void fl_draw(const char* str, int n, float x, float y) { fl_draw(str, n, (int)x, (int)y); } +static void fl_drawUCS4(const FcChar32 *str, int n, int x, int y) { +#if USE_OVERLAY + XftDraw*& draw = fl_overlay ? draw_overlay : ::draw; + if (fl_overlay) { + if (!draw) + draw = XftDrawCreate(fl_display, draw_overlay_window = fl_window, + fl_overlay_visual->visual, fl_overlay_colormap); + else //if (draw_overlay_window != fl_window) + XftDrawChange(draw, draw_overlay_window = fl_window); + } else +#endif + if (!draw) + draw = XftDrawCreate(fl_display, draw_window = fl_window, + fl_visual->visual, fl_colormap); + else //if (draw_window != fl_window) + XftDrawChange(draw, draw_window = fl_window); + + Region region = fl_clip_region(); + if (region && XEmptyRegion(region)) return; + XftDrawSetClip(draw, region); + + // Use fltk's color allocator, copy the results to match what + // XftCollorAllocValue returns: + XftColor color; + color.pixel = fl_xpixel(fl_color_); + uchar r,g,b; Fl::get_color(fl_color_, r,g,b); + color.color.red = ((int)r)*0x101; + color.color.green = ((int)g)*0x101; + color.color.blue = ((int)b)*0x101; + color.color.alpha = 0xffff; + + XftDrawString32(draw, &color, current_font, x, y, (FcChar32 *)str, n); +} + + +void fl_rtl_draw(const char* c, int n, int x, int y) { +#warning Need to improve this XFT right to left draw function +// This actually draws LtoR, but aligned to R edge with the glyph order reversed... +// but you can't just byte-rev a UTF-8 string, that isn't valid. +// You can reverse a UCS4 string though... + int num_chars, wid, utf_len = strlen(c); + FcChar8 *u8 = (FcChar8 *)c; + FcBool valid = FcUtf8Len(u8, utf_len, &num_chars, &wid); + if (!valid) + { + // badly formed Utf-8 input string + return; + } + if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array + FcChar32 *ucs_txt = new FcChar32[n+1]; + FcChar32* pu; + int in, out, sz; + ucs_txt[n] = 0; + in = 0; out = n-1; + while ((out >= 0) && (utf_len > 0)) + { + pu = &ucs_txt[out]; + sz = FcUtf8ToUcs4(u8, pu, utf_len); + utf_len = utf_len - sz; + u8 = u8 + sz; + out = out - 1; + } + // Now we have a UCS4 version of the input text, reversed, in ucs_txt + int offs = (int)fl_width(ucs_txt, n); + fl_drawUCS4(ucs_txt, n, (x-offs), y); + + delete[] ucs_txt; +} + // // End of "$Id$" // |
