motifdeveloper.com
Sponsored by IST Limited
Formerly MW3: Motif on the World Wide Web [MW3 Logo]
Last Updated
November 18, 2002
 


X-Designer - The Leading X/Motif GUI Builder - Click to download a FREE evaluation
 

motifdeveloper.com
Home
About the site
Bulletin Board
News Archive
OpenGroup News
Events
Search
Frequently Asked Questions
The Motif FAQ
X/Motif FAQs
General FAQs
Ask Antony
Latest Q & A
All Q & As
Submit Question
Tips & Pointers
Code Examples
Software
OpenMotif
Widget Sets
GUI Toolkits & Libraries
Motif suppliers
Non-commercial S/W
Commercial Software
Multimedia
Miscellaneous
Organizations
Docs & Pubs
X/Motif Newsgroups
Security
Internationalization
Feedback
Feedback Form
Contributors
 

How do you draw clipped text?

28-Feb-01 14:00 GMT

Question: Can I use a clip mask use with "XDrawImageString()" to mask out part of a character. If so, how do I do it. If a clip mask won't work, is there another technique? I would like to clip off the top few pixels of each character

This is an unusual requirement, but I can see where the required techniques could lead to some interesting effects.

There is more than one way to go about masking off a portion of a character, although they all ultimately revolve around the manipulation of the graphics context (GC) which is passed to the XDrawImageString() routine. The various techniques for clipping drawing requests are:

  • Create a Clip Mask (an X Bitmap). Each bit in the bitmap indicates which pixels in the drawable are to be affected by subsequent graphic drawing requests.

    Once created, the bitmap is applied to the graphics context through the routine XSetClipMask().

  • Create a Clip Rectangle. The rectangle specifies a boundary such that any attempt to draw outside the confines of the rectangle are ignored. Multiple rectangles can be specified for more complex clipping.

    Once specified, the rectangles are applied to the graphics context through the routine XSetClipRectangles().

  • Create a Clip Region. This is roughly similar to the specification of a set of clip rectangles above, except that it is often slightly more convenient when performing clipping operations because it is possible to perform union and intersection operations on the region in order to restrict graphical operations to the areas currently exposed.

    Once created, the Region is applied to the graphics contexts through the routine XSetClipRegion().

Which technique to adopt would depend on all kinds of circumstances, to be determined by the nature of the graphical drawing to hand. In this instance, the simplest method is going to involve a simple rectangle which describes a bounding box around the portions of text to be drawn.

The draw_clipped_string routine

The following routine draws a string such that the top clip_size pixels of the text are masked off. The graphics context is pre-created with suitable styles, and the routine to perform this is available in the example codes which can be downloaded below.

    static void draw_clipped_string(Widget       w,         /* The drawable           */
				    GC           gc,        /* The graphics context   */
				    char        *string,    /* The string to draw     */
				    XFontStruct *the_font,  /* The font to draw in    */
				    int          x,         /* X coordinate of string */
				    int          y,         /* Y coordinate of string */
				    int          clip_size) /* Top pixels to hide     */
    {
	XRectangle  rectangle ;
	int         ascent ;
	int         descent ;
	int         direction ;
	XCharStruct overall ;
	int         length = strlen(string) ;

	/* Calculate the bounding box around the text to be drawn */
	XTextExtents(the_font, string, length, &direction, &ascent, &descent, &overall) ;

	/* Construct a rectangle with the top clip_size pixels masked off */
	/* This uses the font metrics in order to calculate the clip rectangle   */
	rectangle.x      = x ;
	rectangle.y      = y - overall.ascent + clip_size ;
	rectangle.width  = (overall.rbearing - overall.lbearing) ;
	rectangle.height = (overall.ascent + overall.descent - clip_size) ;

	/* Set the clip rectangle */
	XSetClipRectangles(XtDisplay(w), gc, 0, 0, &rectangle, 1, Unsorted) ;

	/* Now draw the string */
	XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, y, string, length) ;
    }

We would invoke the routine something along the lines of the following:

    extern GC           gc ;
    extern XFontStruct *the_font ;
    extern Widget       drawable ;

    draw_clipped_string(drawable, gc, "Clipped text", the_font, 50, 50, 5) ;

The effect of the routine can be seen in the following screen shot.

Example Code for the clipped text program

The sources consist of:

  • cliptext.c - the generated source code for the interface
  • cliptext_stubs.c - the event handler, action code for the drawing area
  • cliptext.h - a header file with the extern widget declarations
  • cliptext.res - an X resource file with external font/color specifications
  • Makefile - a general purpose Makefile for the application. Its configured for Solaris, but at the top of the file are rules for various platforms: simply comment out the Solaris section, and uncomment your platform as required.
  • cliptext.xd - the X-Designer design save file. Feel free to ignore this.

Alternatively download a tar archive, cliptext.tar, of all the above source files. If you are using Netscape Navigator you may have to hold down the Shift key when you click on the file name in order to ensure that you are prompted to save the file.

As an example of where this could be used for interesting effects, consider the following two-tone output from another example program:

For this to work, we only need to modify the drawing routine very slightly. We draw the string twice in different colors, each time masking off either the top or bottom half of the image string.

    static void draw_twotone_string(Widget       w,      /* The drawable           */
				    GC           gc,     /* The graphics context   */
				    char        *string, /* The string to draw     */
				    XFontStruct *font,   /* The font to draw in    */
				    Pixel        top,    /* The top font color     */
				    Pixel        bottom, /* The bottom font color  */
				    int          x,      /* X coordinate of string */
				    int          y)      /* Y coordinate of string */
    {
	XRectangle  rectangle ;
	int         ascent ;
	int         descent ;
	int         direction ;
	XCharStruct overall ;
	XGCValues   values ;
	int         length = strlen(string) ;

	/* Calculate the bounding box around the text to be drawn */
	XTextExtents(font, string, length, &direction, &ascent, &descent, &overall) ;

	/* Construct a rectangle to draw the top half of the string */
	rectangle.x      = x ;
	rectangle.y      = y - overall.ascent ;
	rectangle.width  = (overall.rbearing - overall.lbearing) ;
	rectangle.height = (overall.ascent + overall.descent) / 2 ;

	XSetClipRectangles(XtDisplay(w), gc, 0, 0, &rectangle, 1, Unsorted) ;
	values.foreground = top ;
	XChangeGC(XtDisplay(w), gc, GCForeground, &values) ;
	XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, y, string, length) ;

	/* Construct a rectangle to draw the bottom half of the string */
	rectangle.y      = y - overall.ascent + ((overall.ascent + overall.descent) / 2) ;
	rectangle.height = (overall.ascent + overall.descent) / 2 ;

	XSetClipRectangles(XtDisplay(w), gc, 0, 0, &rectangle, 1, Unsorted) ;
	values.foreground = bottom ;
	XChangeGC(XtDisplay(w), gc, GCForeground, &values) ;
	XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, y, string, length) ;
    }

We would invoke this routine something along the following lines:

    extern GC           gc ;
    extern XFontStruct *the_font ;
    extern Widget       drawable ;
    extern Pixel        top_color ;
    extern Pixel        bottom_color ;

    draw_twotone_string(w, gc, "Two-tone Text", the_font, top_color, bottom_color, 50, 50);

Example Code for the two-tone text program

The sources consist of:

  • halffont.c - the generated source code for the interface
  • halffont_stubs.c - the drawing code
  • halffont.h - a header file with the extern widget declarations
  • halffont.res - an X resource file with external font/color specifications
  • Makefile - a general purpose Makefile for the application. It is configured for Solaris, but at the top of the file are rules for various platforms: simply comment out the Solaris section, and uncomment your platform as required.
  • halffont.xd - the X-Designer design save file. Feel free to ignore this.

Alternatively download a tar archive, halffont.tar, of all the above source files. If you are using Netscape Navigator you may have to hold down the Shift key when you click on the file name in order to ensure that you are prompted to save the file.

Assumptions.

The above code assumes that a constant font has been applied into the graphics context, although the routines do pass the XFontStruct through so that metrics can be calculated. A more general solution would check whether the font has changed, and thereafter modify the graphics context accordingly. This would guarantee that the metrics and the graphics context are in step.

Optimizations

There are several places where optimizations can be effective. In particular, the routine XChangeGC() is relatively expensive, involving as it does a round trip to the X server. There may be some money in caching multiple application contexts in each of the relevant color/fonts required, rather than dynamically modifying the single graphics contexts every time the string is drawn in a distinct color or font. This is left as an exercise for the reader.

Bibliography

The routines described above are all listed in the Xlib Reference library. The following is considered to be the amongst the very best material on the subject:

    Xlib Reference Manual,
    Volume 2,
    O'Reilly and Associates,
    ISBN 1-56592-006-6
    Buy it from Amazon.com or Amazon.co.uk

    Xlib Programming Manual,
    Volume 1,
    O'Reilly and Associates,
    ISBN 1-56592-002-3
    Buy it from Amazon.com or Amazon.co.uk

The definitive single volume tome on Xlib programming is:

    X Window System,
    The Complete Reference to Xlib, X Protocol, ICCCM, XLFD,
    Robert W. Scheifler and James Gettys,
    ISBN 1-55558-088-2
    Buy it from Amazon.com or Amazon.co.uk

 



Sponsored by X-Designer - The Leading X/Motif GUI Builder - Click to download a FREE evaluation

 

Goto top of page

 

[IST Limited]
IST Limited is the
proud sponsor of motifdeveloper.com.
 

Thanks to all the contributors to these pages.

Privacy Policy

 
"Motif" is a registered trademark of The Open Group. All other trademarks are the property of their respective owners.

Some articles/papers here have their own copyright notice. All other information is copyright ©1999-2008 IST Limited

[CommerceOne] MW3 site originally by Ken Sall of Commerce One (formerly Century Computing).