TGlyphInfo *glyph_cache_get_info(TGlyphCache *cache, gunichar glyph) { TGlyphInfo *gfi; XftFont *xftfont; PangoFont *font; PangoGlyph pglyph; PangoRectangle ink, logical; gint ascent, descent; gint x_offset; gint nominal_width; double scale_y, scale_x; if (!cache->hash) return NULL; gfi = g_hash_table_lookup(cache->hash, GINT_TO_POINTER(glyph)); if (gfi) return gfi; font = pango_fontset_get_font(cache->font_set, glyph); pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph); if (!pglyph) { fprintf (stderr, "Error: Unable to find glyph %d.\n", glyph); if (!pglyph) pglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), glyph); if (!pglyph) pglyph = PANGO_GET_UNKNOWN_GLYPH (glyph); if (!pglyph) return NULL; } pango_font_get_glyph_extents(font, pglyph, &ink, &logical); ascent = PANGO_ASCENT(logical); descent = PANGO_DESCENT(logical); xftfont = pango_xft_font_get_font(font); x_offset = 0; nominal_width = cache->width; if (g_unichar_iswide(glyph)) nominal_width *= 2; scale_x = scale_y = 1.0; if (logical.width > nominal_width) { if (logical.width) scale_x = (double)nominal_width / (double)logical.width; else scale_x = 1.0; } if (logical.height != cache->height) { double scale; if (ascent) { scale_y = (double)cache->ascent / (double)ascent; } else { scale_y = 1.0; } if (descent) { scale = (double)cache->descent / (double)descent; if (scale < scale_y) scale_y = scale; } } if (scale_x >= 1.0) { scale_x = 1.0; x_offset += (nominal_width - logical.width) / 2; } if (scale_x < 1.0 || scale_y != 1.0) { FcBool scalable; FcPatternGetBool(xftfont->pattern, FC_SCALABLE, 0, &scalable); if (!scalable) { /* Bah. Need better handling of non-scalable fonts */ if (scale_x < 1.0) scale_x = 1.0; scale_y = 1.0; } else if (scale_x < 1.0 || scale_y != 1.0) { FcPattern *pattern; FcMatrix mat; pattern = FcPatternDuplicate(xftfont->pattern); FcMatrixInit (&mat); FcMatrixScale(&mat, scale_x, scale_y); FcPatternDel (pattern, FC_MATRIX); FcPatternAddMatrix(pattern, FC_MATRIX, &mat); xftfont = XftFontOpenPattern( GDK_DISPLAY_XDISPLAY(cache->display), pattern ); } ascent = ascent * scale_y; } g_object_unref(font); // gfi = calloc(sizeof(TGlyphInfo), 1); gfi = g_slice_new(TGlyphInfo); gfi->font = xftfont; gfi->x_offset = PANGO_PIXELS(x_offset); gfi->y_offset = cache->ascent + (cache->ascent - ascent); gfi->y_offset = PANGO_PIXELS(gfi->y_offset); g_hash_table_insert(cache->hash, GINT_TO_POINTER(glyph), gfi); return gfi; }
static XftFont * GetFont( UnixFtFont *fontPtr, FcChar32 ucs4, double angle) { int i; if (ucs4) { for (i = 0; i < fontPtr->nfaces; i++) { FcCharSet *charset = fontPtr->faces[i].charset; if (charset && FcCharSetHasChar(charset, ucs4)) { break; } } if (i == fontPtr->nfaces) { i = 0; } } else { i = 0; } if ((angle == 0.0 && !fontPtr->faces[i].ft0Font) || (angle != 0.0 && (!fontPtr->faces[i].ftFont || fontPtr->faces[i].angle != angle))){ FcPattern *pat = FcFontRenderPrepare(0, fontPtr->pattern, fontPtr->faces[i].source); double s = sin(angle*PI/180.0), c = cos(angle*PI/180.0); FcMatrix mat; XftFont *ftFont; /* * Initialize the matrix manually so this can compile with HP-UX cc * (which does not allow non-constant structure initializers). [Bug * 2978410] */ mat.xx = mat.yy = c; mat.xy = -(mat.yx = s); if (angle != 0.0) { FcPatternAddMatrix(pat, FC_MATRIX, &mat); } ftFont = XftFontOpenPattern(fontPtr->display, pat); if (!ftFont) { /* * The previous call to XftFontOpenPattern() should not fail, but * sometimes does anyway. Usual cause appears to be a * misconfigured fontconfig installation; see [Bug 1090382]. Try a * fallback: */ ftFont = XftFontOpen(fontPtr->display, fontPtr->screen, FC_FAMILY, FcTypeString, "sans", FC_SIZE, FcTypeDouble, 12.0, FC_MATRIX, FcTypeMatrix, &mat, NULL); } if (!ftFont) { /* * The previous call should definitely not fail. Impossible to * proceed at this point. */ Tcl_Panic("Cannot find a usable font"); } if (angle == 0.0) { fontPtr->faces[i].ft0Font = ftFont; } else { if (fontPtr->faces[i].ftFont) { XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont); } fontPtr->faces[i].ftFont = ftFont; fontPtr->faces[i].angle = angle; } } return (angle==0.0? fontPtr->faces[i].ft0Font : fontPtr->faces[i].ftFont); }