Problem: I cannot draw the XFT text in the buffer.

This forum is read only. No new submissions are accepted.

Questions about motif? Contact us

9 posts / 0 new
Last post
Problem: I cannot draw the XFT text in the buffer.

Submitted by merblud on Thu, 06/05/2008 - 16:26.

I draw the text in the offscreen buffer. I use function XmStringDraw.
Then I copy it on the screen. Such way does not work, when the text is drawn via XFT. I think, that the reason in the following circumstance. Before creating XftDraw OpenMotif tries to receive attributes of window in which it is necessary to draw the text. As in my case it not a window, and Pixmap there is a mistake. The XftDraw is not created correctly. The XFT text is not drawn. How to solve this problem?

Thu, 06/12/2008 - 14:36#1

Thu, 06/12/2008 - 14:36#1

fredk

Re: Problem: I cannot draw the XFT text in the buffer.

We can only guess what you mean by "I use function XmStringDraw" and "I copy it on the screen" and "the text is drawn via XFT". You say it doesn't work, but you do not say what actually happens. What are you expecting, and what do you get instead? Show some actual code!

Thu, 06/12/2008 - 18:48#2

Thu, 06/12/2008 - 18:48#2

merblud

Re: Problem: I cannot draw the XFT text in the buffer.

Example for demonstration only. He is not my present code. Here the offscreen pixmap is created. In the pixmap the text is drawn. Then the pixmap is inserted into a label.
I define parameters of drawing so that the XFT was used. In result the text is not displayed. The Xlib gives out the following errors:

Ignoring Xlib error: error code 8 request code 3
Ignoring Xlib error: error code 8 request code 158
Ignoring Xlib error: error code 182 request code 158

I define parameters of drawing so that was not used a XFT. In result the text is displayed.

In my program I use the offscreen buffer for caching images. The text with anti-aliased fonts is drawn slowly.

#include

XGCValues values;
unsigned long mask;
GC gc;
XmRenderTable rt;
Pixmap pix;

int main(int argc, char *argv[]) {
Widget toplevel;
Arg args[10];
Cardinal n;
XtAppContext app;
XmString str;
XmRendition Rendition;
XmStringTag RenditionTag;

XtSetLanguageProc(NULL, NULL, NULL);
toplevel = XtAppInitialize(&app, "test", NULL, 0, &argc, argv, NULL, NULL, 0);

pix = XCreatePixmap(XtDisplay(toplevel), RootWindowOfScreen(XtScreen(toplevel)),
50, 30,
DefaultDepthOfScreen(XtScreen(toplevel)));

values.line_style = LineSolid;
values.line_width = 1;
values.fill_style = FillSolid;

mask = GCLineStyle | GCLineWidth | GCFillStyle ;

gc=XCreateGC(XtDisplay(toplevel), pix, mask, &values);

XSetForeground(XtDisplay(toplevel), gc, XWhitePixelOfScreen(XtScreen(toplevel)));

XFillRectangle(XtDisplay(toplevel), pix, gc, 1, 1, 49, 29);

XSetForeground(XtDisplay(toplevel), gc, XBlackPixelOfScreen(XtScreen(toplevel)));
XSetBackground(XtDisplay(toplevel), gc, XWhitePixelOfScreen(XtScreen(toplevel)));

n = 0;
XtSetArg( args[n], XmNrenditionForeground, XBlackPixelOfScreen(XtScreen(toplevel))); n++;
XtSetArg( args[n], XmNrenditionBackground, XWhitePixelOfScreen(XtScreen(toplevel))); n++;
XtSetArg( args[n], XmNfontName, "Times" ); n++;
// XtSetArg( args[n], XmNfontName, "-misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1" ); n++;
XtSetArg( args[n], XmNfontType, XmFONT_IS_XFT ); n++;
// XtSetArg( args[n], XmNfontType, XmFONT_IS_FONT ); n++;
XtSetArg( args[n], XmNunderlineType, XmSINGLE_LINE ); n++;

RenditionTag = (XmStringTag) "Rendition1";
Rendition = XmRenditionCreate( toplevel, RenditionTag, args, n );

rt = XmRenderTableAddRenditions ( NULL, &Rendition, 1, XmMERGE_NEW);
str = XmStringCreateLocalized("text");

XmStringDraw( XtDisplay(toplevel), pix, rt, str, gc, 5, 5, 30, XmALIGNMENT_BEGINNING, XmSTRING_DIRECTION_DEFAULT, NULL);

n = 0;
XtSetArg(args[n], XmNlabelType, XmPIXMAP); n++;
XtSetArg(args[n], XmNlabelPixmap, pix); n++;
// XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
// XtSetArg(args[n], XmNlabelString, str); n++;
XtSetArg(args[n], XmNrenderTable, rt); n++;

(void)XtCreateManagedWidget("label", xmLabelWidgetClass, toplevel, args, n);
XmStringFree(str);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}

Mon, 06/30/2008 - 18:42#3

Mon, 06/30/2008 - 18:42#3

dpeterc

Re: Problem: I cannot draw the XFT text in the buffer.

I have just quickly looked at your code, without trying to fully understand it and/or debug it.
So the answer to your question will not be really direct solution.

Recently I have implemented this in my programs, so here is my advice.
I think you approach is wrong - if you need off-screen rendering into a buffer with antialiased fonts using XFT, you should use XFT functions directly, just like you use Xlib to draw a line with XDrawLine(...).

It is relatively simple, just that the documentation is hard to find, as most people nowadays use high level toolkits, which contain all the complex drawing functions (unlike Motif).
You should look at the following pages:
http://keithp.com/~keithp/render/Xft.tutorial
http://keithp.com/~keithp/talks/xtc2001/paper/
It can be a dense read at times, but is relatively complete, and if you are able to draw a text using
XDrawString(...)
you will also be able to do it using
XftDrawStringUTF8(...)

Let me know if this gets you over the hurdle, otherwise I can post some skeleton code for you to copy.

Tue, 07/01/2008 - 16:45#4

Tue, 07/01/2008 - 16:45#4

merblud

Re: Problem: I cannot draw the XFT text in the buffer.

Use of the XFT directly is not difficult. If to consider it in a separation from a task. But there are problems:

1. For definition of fonts I use resources of the Xt/Motif (XmRenderTable). It will be necessary to write itself a code for the analysis of XmRenderTable to receive names of fonts in old and new style. It is the minimal job which should be executed. What for it to do? It is already made in Motif 2.3. There is a second variant. It is possible to invent own resource describing a font. I think, that the second variant not strongly differs from the first.

2. Function XmStringDraw of Motif normally draws the text a usual font in the pixmap. When the Anti-Aliased font this function is used does not work. It is a bug of the Motif 2.3. It is necessary to correct bug, instead of to invent roundabout ways.

 

 

Wed, 07/02/2008 - 19:36#5

dpeterc

Re: Problem: I cannot draw the XFT text in the buffer.

That is a great find, Merblud!
I agree with both your points - if your application only needs to draw some text in in a Pixmap with the same font as the interface, then it is better to use the high level function like XmStringDraw.
My application changes font sizes and generates the print image, so I need to use XFT directly.

Reinventing the wheel with XFT font name creation is also a useless pain, just like you say.

The name of the bug should be:
XmStringDraw does not work with antialiased fonts and UTF8
You should post a bug report with a minimum sample code here:
http://bugs.motifzone.net/
If you will not do it, then I will do it, since this bug is also very important for me. Namely, third some party open source widgets do not work with antialiased fonts and UTF8 because of this. One such example is Microline widget set, which was used in Netscape, and is now used in nedit. That code is very clean, and does not use XDrawString at all, it only uses XmStringDraw() so that it does not work properly with antialiased fonts.
I am sure that there are other widgets which will display the same problem, if the bug is not fixed.

 

Fri, 07/04/2008 - 16:28#6

Fri, 07/04/2008 - 16:28#6

merblud

Re: Problem: I cannot draw the XFT text in the buffer.

Fragment of a code from OpenMotif 2.3. The module XmRenderT.c. Function _XmXftDrawCreate.

XftDraw *
2890 _XmXftDrawCreate(Display *display, Window window)
2891 {
2892 XftDraw *draw;
2893 XWindowAttributes wa;
2894 int i;
2895 Status status;
2896
2897 for (i=0; i<_XmXftDrawCacheSize; i++) {
2898 if (_XmXftDrawCache[i].display == display &&
2899 _XmXftDrawCache[i].window == window) {
2900 return _XmXftDrawCache[i].draw;
2901 }
2902 }
2903 oldErrorHandler = XSetErrorHandler (_XmXftErrorHandler);
2904 xft_error = 0;
2905 XGetWindowAttributes(display, window, &wa);
2906 if (xft_error != BadWindow) {
2907 draw = XftDrawCreate(display, window,
2908 DefaultVisual(display, DefaultScreen(display)),
2909 DefaultColormap(display, DefaultScreen(display)));
2910 } else {
2911 draw = XftDrawCreateBitmap(display, window);
2912 }
2913
2914 /* Store it in the cache. Look for an empty slot first */
2915 for (i=0; i<_XmXftDrawCacheSize; i++)
2916 if (_XmXftDrawCache[i].display == NULL) {
2917 _XmXftDrawCache[i].display = display;
2918 _XmXftDrawCache[i].draw = draw;
2919 _XmXftDrawCache[i].window = window;
2920 return draw;
2921 }
2922 i = _XmXftDrawCacheSize; /* Next free index */
2923 _XmXftDrawCacheSize = _XmXftDrawCacheSize * 2 + 8;
2924 _XmXftDrawCache = (struct _XmXftDrawCacheStruct *)
2925 XtRealloc((char *)_XmXftDrawCache,
2926 sizeof(struct _XmXftDrawCacheStruct) * _XmXftDrawCacheSize);
2927
2928 _XmXftDrawCache[i].display = display;
2929 _XmXftDrawCache[i].draw = draw;
2930 _XmXftDrawCache[i].window = window;
2931
2932 return draw;
2933 }

Function _XmXftDrawCreate is called, if it is necessary to draw the text the Anti-Aliased font.
Before creating XftDraw, function XGetWindowAttributes is called (line 2905). If the argument # 2 of functions _XmXftDrawCreate is a window, very well.
If the argument # 2 of functions _XmXftDrawCreate is the Pixmap then the XftDraw is not created correctly.
I cannot understand, function XGetWindowAttributes what for is called. I assume, that so the window is checked.
But what for it to do? Probably the XFT cannot draw the text in a Pixmap. I did not check it.
But to documentation on a XFT it is written clearly. Argument of function XftDrawCreate is the Drawable.
Except for that. When function XmStringDraw draws the text not Anti-Aliased font (via XDrawText, XmbDrawText etc.) such check is not carried out.
Function XmbDrawText draws the text both in a window and in pixmap. There can be I do not understand something important.
The most simple way to check up my guesses it to build a OpenMotif 2.3 without check. But now I cannot make it.

Mon, 07/07/2008 - 18:18#7

Mon, 07/07/2008 - 18:18#7

fredk

Re: Problem: I cannot draw the XFT text in the buffer.

I have not looked at the Motif2.3 code, but if this is indeed that code, there is a major flaw in it.
At line 2903, it replaces the X error handler with _XmXftErrorHandler(), which presumable can
set a global variable "xft_error" if XGetWindowAttributes fails. That value is checked in line 2906.

But the code fails to restore the original error handler. This is a serious error.

- Fred

 

Wed, 09/03/2008 - 11:30#8

Wed, 09/03/2008 - 11:30#8

dpeterc

Re: Problem: I cannot draw the XFT text in the buffer.

I have posted a bug report regarding XFT drawing with XmStringDrawImage
http://bugs.motifzone.net/show_bug.cgi?id=1451
other than that, I think it should be possible to draw XFT text in the buffer,
since XmStringDraw draws into a drawable, and this can be a pixmap.
You can look in my but report sample code to see how to use it.