JSize JXFontManager::GetCharWidth ( const JFontID fontID, const JSize size, const JFontStyle& style, const JCharacter c ) const { const FontInfo info = itsFontList->GetElement(fontID); if (info.monoWidth > 0) { return info.monoWidth; } else if (info.xfont.type == kStdType) { return XTextWidth(info.xfont.xfstd, &c, 1); } else { assert( info.xfont.type == kTrueType ); XGlyphInfo g; XftTextExtents8(*itsDisplay, info.xfont.xftrue, (FcChar8*) &c, 1, &g); return g.xOff; } }
// outer code may need line height, width, etc void textbox_extents(textbox *tb) { int length = strlen(tb->text) + strlen(tb->prompt); char *line = alloca(length + 1); sprintf(line, "%s%s", tb->prompt, tb->text); XftTextExtents8(display, tb->font, (unsigned char*)line, length, &tb->extents); }
int FontX11::get_string_width(const String& p_string) const { if (!font) return 0; XGlyphInfo ginfo; // this will dissapear at compile time switch(sizeof(String::CharType)) { case 1: { // ascii? XftTextExtents8( x11_display, font, (FcChar8*)p_string.c_str(), p_string.length(), &ginfo ); } break; case 2: { // ucs16 XftTextExtents16( x11_display, font, (FcChar16*)p_string.c_str(), p_string.length(), &ginfo ); } break; case 4: { // ucs32 XftTextExtents32( x11_display, font, (FcChar32*)p_string.c_str(), p_string.length(), &ginfo ); } break; } return ginfo.width; }
void xwindow_draw_string_xft(XWindow *xw, char *text, int x, int y) { int n; XftDraw *draw; XftColor color; XRenderColor rc; XftFont *font; XGlyphInfo extents; float shift[] = { 0.0, 0.0, -0.5, -1.0 }; n = strlen(text); font = xw->font->font_xft; if(!font) { return; } draw = XftDrawCreate(DISPLAY(xw), xw->buffer, VISUAL(xw), DefaultColormap(DISPLAY(xw), SCREEN(xw))); /* Set Text from current Color */ rc.red = xw->color->red; rc.green = xw->color->green; rc.blue = xw->color->blue; rc.alpha = 0xFFFF; /* 65535 */ XftColorAllocValue(DISPLAY(xw), VISUAL(xw), DefaultColormap(DISPLAY(xw), SCREEN(xw)), &rc, &color); XftTextExtents8(DISPLAY(xw), font, (FcChar8*)text, n, &extents); if(cmgdm.tangle != 0.0) { XftMatrix m; m.xx = 0.0; m.xy = -1.0; m.yx = 1.0; m.yy = 0.0; y = y - shift[cmgdm.ihjust] * extents.xOff; x = x - shift[cmgdm.ivjust] * (font->ascent + font->descent); font = XftFontOpen(DISPLAY(xw), SCREEN(xw), XFT_FAMILY, XftTypeString, xw->font->family, XFT_SIZE, XftTypeDouble, xw->font->size, XFT_STYLE, XftTypeString, xfont_style(xw->font), XFT_ANTIALIAS, XftTypeBool, xw->font->antialias, XFT_MATRIX, XftTypeMatrix, &m, NULL); } else { x = x + shift[cmgdm.ihjust] * extents.xOff; y = y - shift[cmgdm.ivjust] * (font->ascent + font->descent); } XftDrawString8(draw, &color, font, x, y, (FcChar8 *)text, n); }
static int charWidth (DviWidget dw, XftFont *font, char c) { XGlyphInfo extents; XftTextExtents8 (XtDisplay (dw), font, (unsigned char *) &c, 1, &extents); return extents.xOff; }
static int ui_info_font_normal_char_width() { XftChar8 ch = 'a'; XGlyphInfo extents; XftTextExtents8(ui_display, ui_infofont, &ch, 1, &extents); return extents.width; }
/* draw text in a given color at a given (x,y) */ int render_text(XftColor *c, int x, int y, const char *str) { XGlyphInfo extents; XftTextExtents8( XINFO.disp, XINFO.font, (XftChar8 *)str, strlen(str), &extents ); XftDrawString8(XINFO.xftdraw, c, XINFO.font, x, y, (XftChar8 *)str, strlen(str)); return extents.width; }
inline JCoordinate JXFontManager::IsMonospace ( const XFont& xfont ) const { if (xfont.type == kStdType) { return (xfont.xfstd->min_bounds.width == xfont.xfstd->max_bounds.width ? xfont.xfstd->min_bounds.width : 0); } else { assert( xfont.type == kTrueType ); XGlyphInfo g1, g2; XftTextExtents8(*itsDisplay, xfont.xftrue, (FcChar8*) "M", 1, &g1); XftTextExtents8(*itsDisplay, xfont.xftrue, (FcChar8*) "|", 1, &g2); return (g1.xOff == g2.xOff ? g1.xOff : 0); } }
void neo_draw_pen_draw_text(NeoDrawHandle *handle, NeoDrawPen *pen,NeoDrawWindow *win, int x, int y, char *text) { if(!handle || !pen || !win) return; int len = strlen(text); XGlyphInfo inf; XftTextExtents8(handle->display, pen->xft_font, (XftChar8 *) text, len, &inf); int height = inf.y; int width = inf.x; XftDrawString8(pen->xft_draw, &pen->xft_color, pen->xft_font, x + width, y +height, (XftChar8 *)text, len); }
int rp_text_width (rp_screen *s, XFontSet font, char *string, int count) { if (count < 0) count = strlen (string); #ifdef USE_XFT_FONT if (s->xft_font) { XGlyphInfo extents; XftTextExtents8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); return extents.xOff; } else #endif return XmbTextEscapement (font, string, count); }
void draw_text(char **message, XftColor *color) { int len; int i, x, y; XGlyphInfo extents; i = 0; y = height / 3; while (message[i] != NULL) { len = strlen(message[i]); XftTextExtents8(display, font, message[i], len, &extents); x = (width - extents.width)/2; XftDrawString8(draw, color, font, x, y, message[i], len); y += extents.height * 1.5; i++; } }
JSize JXFontManager::GetStringWidth ( const JFontID fontID, const JSize size, const JFontStyle& style, const JCharacter* str, const JSize charCount ) const { const FontInfo info = itsFontList->GetElement(fontID); if (info.monoWidth > 0) { return charCount * info.monoWidth; } else { const JSize maxStringLength = itsDisplay->GetMaxStringLength(); JSize width = 0; JSize offset = 0; XGlyphInfo g; while (offset < charCount) { const JSize count = JMin(charCount - offset, maxStringLength); if (info.xfont.type == kStdType) { width += XTextWidth(info.xfont.xfstd, str + offset, count); } else { assert( info.xfont.type == kTrueType ); XftTextExtents8(*itsDisplay, info.xfont.xftrue, (FcChar8*) (str + offset), count, &g); width += g.xOff; } offset += count; } return width; } }
uint defont_get_text_width(DEFont *font, const char *text, uint len) { #ifdef HAVE_X11_XFT if(font->font!=NULL){ XGlyphInfo extents; if(ioncore_g.enc_utf8) XftTextExtentsUtf8(ioncore_g.dpy, font->font, (XftChar8*)text, len, &extents); else XftTextExtents8(ioncore_g.dpy, font->font, (XftChar8*)text, len, &extents); return extents.xOff; } #endif /* HAVE_X11_XFT */ #ifdef HAVE_X11_BMF if(font->fontset!=NULL){ XRectangle lext; #ifdef CF_DE_USE_XUTF8 if(ioncore_g.enc_utf8) Xutf8TextExtents(font->fontset, text, len, NULL, &lext); else #endif XmbTextExtents(font->fontset, text, len, NULL, &lext); return lext.width; }else if(font->fontstruct!=NULL){ if(ioncore_g.enc_utf8){ XChar2b *str16; int len16=0; uint res; toucs(text, len, &str16, &len16); res=XTextWidth16(font->fontstruct, str16, len16); free(str16); return res; }else{ return XTextWidth(font->fontstruct, text, len); } } #endif /* HAVE_X11_BMF */ else{ return 0; } }
JSize JXFontManager::GetLineHeight ( const JFontID fontID, const JSize size, const JFontStyle& style, JCoordinate* ascent, JCoordinate* descent ) const { FontInfo info = itsFontList->GetElement(fontID); if (info.xfont.type == kStdType) { *ascent = info.xfont.xfstd->ascent; *descent = info.xfont.xfstd->descent; } else { assert( info.xfont.type == kTrueType ); if (info.ascent == 0) { XGlyphInfo g; XftTextExtents8(*itsDisplay, info.xfont.xftrue, (FcChar8*) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789|_", 64, &g); info.ascent = g.y + 1 + size/10; info.descent = g.height - g.y; itsFontList->SetElement(fontID, info); } *ascent = info.ascent; *descent = info.descent; } const JCoordinate underlineHeight = 2 * GetUnderlineThickness(size) * style.underlineCount; if (*descent < underlineHeight) { *descent = underlineHeight; } return (*ascent + *descent); }
int WMWidthOfString(WMFont *font, char *text, int length) { XGlyphInfo extents; wassertrv(font!=NULL, 0); wassertrv(text!=NULL, 0); if (font->screen->useWideChar) { wchar_t *wtext; const char *mtext; int len; wtext = (wchar_t *)wmalloc(sizeof(wchar_t)*(length+1)); mtext = text; len = wmbsnrtowcs(wtext, &mtext, length, length); if (len>0) { wtext[len] = L'\0'; /* not really necessary here */ XftTextExtents32(font->screen->display, font->font, (XftChar32 *)wtext, len, &extents); } else { if (len==-1) { wwarning(_("Conversion to widechar failed (possible " "invalid multibyte sequence): '%s':(pos %d)\n"), text, mtext-text+1); } extents.xOff = 0; } wfree(wtext); } else if (font->screen->useMultiByte) { XftTextExtentsUtf8(font->screen->display, font->font, (XftChar8 *)text, length, &extents); } else { XftTextExtents8(font->screen->display, font->font, (XftChar8 *)text, length, &extents); } return extents.xOff; /* don't ask :P */ }
void tooltip_map(Tooltip *tt, int x, int y, const FcChar8 *text, int len) { XUnmapWindow(tt->mainwin->dpy, tt->window); XftTextExtents8(tt->mainwin->dpy, tt->font, text, len, &tt->extents); tt->width = tt->extents.width + 8; tt->height = tt->font_height + 5 + (tt->shadow.pixel ? 2 : 0); XResizeWindow(tt->mainwin->dpy, tt->window, tt->width, tt->height); tooltip_move(tt, x, y); if(tt->text) free(tt->text); tt->text = (FcChar8 *)malloc(len); memcpy(tt->text, text, len); tt->text_len = len; XMapWindow(tt->mainwin->dpy, tt->window); XRaiseWindow(tt->mainwin->dpy, tt->window); }
static void ui_draw_tag_value(const char* tag, const char* value, XftFont* font, int x, int y, int maxwidth, int* width) { int accx = x; int tagwidth = 0; ui_draw_string(tag, font, &ui_infocolortag, accx, y, maxwidth, &tagwidth); accx += tagwidth; XGlyphInfo extents; XftTextExtents8(ui_display, font, (XftChar8*) "x", 1, &extents); accx += extents.width; int valuewidth = 0; ui_draw_string(value, font, &ui_infocolor, accx, y, maxwidth - (accx - x), &valuewidth); accx += valuewidth; if (NULL != width) { *width = accx - x; } }
static void debrush_do_draw_string_default_xft( DEBrush *brush, int x, int y, const char *str, int len, bool needfill, DEColourGroup *colours) { Window win = brush->win; GC gc=brush->d->normal_gc; XftDraw *draw; XftFont *font; if(brush->d->font==NULL) return; font=brush->d->font->font; draw=debrush_get_draw(brush, win); if(needfill){ XGlyphInfo extents; if(ioncore_g.enc_utf8){ XftTextExtentsUtf8(ioncore_g.dpy, font, (XftChar8*)str, len, &extents); }else{ XftTextExtents8(ioncore_g.dpy, font, (XftChar8*)str, len, &extents); } XftDrawRect(draw, &(colours->bg), x-extents.x, y-extents.y, extents.width+10, extents.height); } if(ioncore_g.enc_utf8){ XftDrawStringUtf8(draw, &(colours->fg), font, x, y, (XftChar8*)str, len); }else{ XftDrawString8(draw, &(colours->fg), font, x, y, (XftChar8*)str, len); } }
static Lisp_Object xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { FcResult result; Display *display = FRAME_X_DISPLAY (f); Lisp_Object val, filename, idx, font_object; FcPattern *pat = NULL, *match; struct xftfont_info *xftfont_info = NULL; struct font *font; double size = 0; XftFont *xftfont = NULL; int spacing; char name[256]; int len, i; XGlyphInfo extents; FT_Face ft_face; FcMatrix *matrix; val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); if (! CONSP (val)) return Qnil; val = XCDR (val); filename = XCAR (val); idx = XCDR (val); size = XINT (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) size = pixel_size; pat = FcPatternCreate (); FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity)); i = FONT_SLANT_NUMERIC (entity) - 100; if (i < 0) i = 0; FcPatternAddInteger (pat, FC_SLANT, i); FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity)); FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size); val = AREF (entity, FONT_FAMILY_INDEX); if (! NILP (val)) FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); val = AREF (entity, FONT_FOUNDRY_INDEX); if (! NILP (val)) FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); val = AREF (entity, FONT_SPACING_INDEX); if (! NILP (val)) FcPatternAddInteger (pat, FC_SPACING, XINT (val)); val = AREF (entity, FONT_DPI_INDEX); if (! NILP (val)) { double dbl = XINT (val); FcPatternAddDouble (pat, FC_DPI, dbl); } val = AREF (entity, FONT_AVGWIDTH_INDEX); if (INTEGERP (val) && XINT (val) == 0) FcPatternAddBool (pat, FC_SCALABLE, FcTrue); /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz over 10x20-ISO8859-1.pcf.gz). */ FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity)); xftfont_add_rendering_parameters (pat, entity); FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename)); FcPatternAddInteger (pat, FC_INDEX, XINT (idx)); block_input (); /* Make sure that the Xrender extension is added before the Xft one. Otherwise, the close-display hook set by Xft is called after the one for Xrender, and the former tries to re-add the latter. This results in inconsistency of internal states and leads to X protocol error when one reconnects to the same X server. (Bug#1696) */ { int event_base, error_base; XRenderQueryExtension (display, &event_base, &error_base); } /* Substitute in values from X resources and XftDefaultSet. */ XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result); xftfont_fix_match (pat, match); FcPatternDestroy (pat); xftfont = XftFontOpenPattern (display, match); if (!xftfont) { unblock_input (); XftPatternDestroy (match); return Qnil; } ft_face = XftLockFace (xftfont); unblock_input (); /* We should not destroy PAT here because it is kept in XFTFONT and destroyed automatically when XFTFONT is closed. */ font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size); ASET (font_object, FONT_TYPE_INDEX, Qxft); len = font_unparse_xlfd (entity, size, name, 256); if (len > 0) ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); len = font_unparse_fcname (entity, size, name, 256); if (len > 0) ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); else ASET (font_object, FONT_FULLNAME_INDEX, AREF (font_object, FONT_NAME_INDEX)); ASET (font_object, FONT_FILE_INDEX, filename); ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (xftfont->pattern, filename)); font = XFONT_OBJECT (font_object); font->pixel_size = size; font->driver = &xftfont_driver; font->encoding_charset = font->repertory_charset = -1; xftfont_info = (struct xftfont_info *) font; xftfont_info->display = display; xftfont_info->xftfont = xftfont; /* This means that there's no need of transformation. */ xftfont_info->matrix.xx = 0; if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix) == FcResultMatch) { xftfont_info->matrix.xx = 0x10000L * matrix->xx; xftfont_info->matrix.yy = 0x10000L * matrix->yy; xftfont_info->matrix.xy = 0x10000L * matrix->xy; xftfont_info->matrix.yx = 0x10000L * matrix->yx; } if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))) spacing = XINT (AREF (entity, FONT_SPACING_INDEX)); else spacing = FC_PROPORTIONAL; if (! ascii_printable[0]) { int ch; for (ch = 0; ch < 95; ch++) ascii_printable[ch] = ' ' + ch; } block_input (); /* Unfortunately Xft doesn't provide a way to get minimum char width. So, we set min_width to space_width. */ if (spacing != FC_PROPORTIONAL #ifdef FC_DUAL && spacing != FC_DUAL #endif /* FC_DUAL */ ) { font->min_width = font->max_width = font->average_width = font->space_width = xftfont->max_advance_width; XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); } else { XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents); font->min_width = font->max_width = font->space_width = extents.xOff; if (font->space_width <= 0) /* dirty workaround */ font->space_width = pixel_size; XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); font->average_width = (font->space_width + extents.xOff) / 95; } unblock_input (); font->ascent = xftfont->ascent; font->descent = xftfont->descent; if (pixel_size >= 5) { /* The above condition is a dirty workaround because XftTextExtents8 behaves strangely for some fonts (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */ if (font->ascent < extents.y) font->ascent = extents.y; if (font->descent < extents.height - extents.y) font->descent = extents.height - extents.y; } font->height = font->ascent + font->descent; if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0) { int upEM = ft_face->units_per_EM; font->underline_position = -ft_face->underline_position * size / upEM; font->underline_thickness = ft_face->underline_thickness * size / upEM; if (font->underline_thickness > 2) font->underline_position -= font->underline_thickness / 2; } else { font->underline_position = -1; font->underline_thickness = 0; } #ifdef HAVE_LIBOTF xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; xftfont_info->otf = NULL; #endif /* HAVE_LIBOTF */ xftfont_info->ft_size = ft_face->size; font->baseline_offset = 0; font->relative_compose = 0; font->default_ascent = 0; font->vertical_centering = 0; #ifdef FT_BDF_H if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT)) { BDF_PropertyRec rec; if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->baseline_offset = rec.u.integer; if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->relative_compose = rec.u.integer; if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->default_ascent = rec.u.integer; } #endif return font_object; }
void gui_draw_task (task *tk) { int len; int x = tk->pos_x; int taskw = tk->width; #ifdef XFT XGlyphInfo ext; XftColor col; #endif if (!tk->name) return; gui_draw_vline (x); if (tk->focused) { draw_box (x, taskw); } else { set_foreground (5); /* mid gray */ fill_rect (x + 2, 0, taskw - 1, WINHEIGHT); } { register int text_x = x + TEXTPAD + TEXTPAD + ICONWIDTH; #ifdef XFT /* check how many chars can fit */ len = strlen (tk->name); while (len > 0) { XftTextExtents8 (dd, xfs, tk->name, len, &ext); if (ext.width < taskw - (text_x - x) - 2) break; len--; } col.color.alpha = 0xffff; if (tk->iconified) { /* draw task's name dark (iconified) */ col.color.red = cols[3].red; col.color.green = cols[3].green; col.color.blue = cols[3].blue; XftDrawString8 (xftdraw, &col, xfs, text_x, text_y + 1, tk->name, len); col.color.red = cols[3].red; col.color.green = cols[3].green; col.color.blue = cols[3].blue; } else { col.color.red = cols[3].red; col.color.green = cols[3].green; col.color.blue = cols[3].blue; } /* draw task's name here */ XftDrawString8 (xftdraw, &col, xfs, text_x, text_y, tk->name, len); #else /* check how many chars can fit */ len = strlen (tk->name); while (XTextWidth (xfs, tk->name, len) >= taskw - (text_x - x) - 2 && len > 0) len--; if (tk->iconified) { /* draw task's name dark (iconified) */ set_foreground (4); XDrawString (dd, tb.win, fore_gc, text_x, text_y + 1, tk->name, len); set_foreground (3); } else if (tk->focused) { set_foreground (7); } else { set_foreground (4); } /* draw task's name here */ XDrawString (dd, tb.win, fore_gc, text_x, text_y, tk->name, len); #endif } #ifndef HAVE_XPM if (!tk->icon) return; #endif /* draw the task's icon */ XSetClipMask (dd, fore_gc, tk->mask); XSetClipOrigin (dd, fore_gc, x + TEXTPAD, (WINHEIGHT - ICONHEIGHT) / 2); XCopyArea (dd, tk->icon, tb.win, fore_gc, 0, 0, ICONWIDTH, ICONHEIGHT, x + TEXTPAD, (WINHEIGHT - ICONHEIGHT) / 2); XSetClipMask (dd, fore_gc, None); }
int xwindow_text_width_xft(XWindow *xw, char *text) { XGlyphInfo extents; XftTextExtents8(DISPLAY(xw), xw->font->font_xft, (FcChar8 *)text, strlen(text), &extents); return extents.xOff; }
void textbox_draw(textbox *tb) { int i; XGlyphInfo extents; GC context = XCreateGC(display, tb->window, 0, 0); Pixmap canvas = XCreatePixmap(display, tb->window, tb->w, tb->h, DefaultDepth(display, DefaultScreen(display))); XftDraw *draw = XftDrawCreate(display, canvas, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display))); // clear canvas XftDrawRect(draw, &tb->color_bg, 0, 0, tb->w, tb->h); char *line = tb->text, *text = tb->text ? tb->text: "", *prompt = tb->prompt ? tb->prompt: ""; int text_len = strlen(text); int length = text_len; int line_height = tb->font->ascent + tb->font->descent; int line_width = 0; int cursor_x = 0; int cursor_offset = 0; int cursor_width = MAX(2, line_height/10); if (tb->flags & TB_EDITABLE) { int prompt_len = strlen(prompt); length = text_len + prompt_len; cursor_offset = MIN(tb->cursor + prompt_len, length); line = alloca(length + 10); sprintf(line, "%s%s", prompt, text); // replace spaces so XftTextExtents8 includes their width for (i = 0; i < length; i++) if (isspace(line[i])) line[i] = '_'; // calc cursor position XftTextExtents8(display, tb->font, (unsigned char*)line, cursor_offset, &extents); cursor_x = extents.width; // restore correct text string with spaces sprintf(line, "%s%s", prompt, text); } // calc full input text width XftTextExtents8(display, tb->font, (unsigned char*)line, length, &extents); line_width = extents.width; int x = 0, y = tb->font->ascent; if (tb->flags & TB_RIGHT) x = tb->w - line_width; if (tb->flags & TB_CENTER) x = (tb->w - line_width) / 2; // draw the text, including any prompt in edit mode XftDrawString8(draw, &tb->color_fg, tb->font, x, y, (unsigned char*)line, length); // draw the cursor if (tb->flags & TB_EDITABLE) XftDrawRect(draw, &tb->color_fg, cursor_x, 2, cursor_width, line_height-4); // flip canvas to window XCopyArea(display, canvas, tb->window, context, 0, 0, tb->w, tb->h, 0, 0); XFreeGC(display, context); XftDrawDestroy(draw); XFreePixmap(display, canvas); }