[xpert] Re: How to Get 90 degree Rotated Fonts? (code)
Mark Leisher
mleisher at nmsu.edu
Tue Oct 9 01:13:13 AEST 1990
Archive-name: xrot/07-Oct-90
Original-posting-by: mleisher at nmsu.edu (Mark Leisher)
Original-subject: Re: How to Get 90 degree Rotated Fonts? (code)
Reposted-by: emv at math.lsa.umich.edu (Edward Vielmetti)
[Reposted from comp.windows.x.
Comments on this service to emv at math.lsa.umich.edu (Edward Vielmetti).]
Below is some code I pulled off of this very group(some time ago). I
think I played with it a little, but never seriously.
------------ Cut Here ----------------------
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/07/1990 18:43 UTC by mleisher at aigyptos
# Source directory /tmp_mnt/home/thrinakia1/mleisher/x_stuff
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 8067 -rw-rw-r-- rotate-text90.c
#
# ============= rotate-text90.c ==============
if test -f 'rotate-text90.c' -a X"$1" != X"-c"; then
echo 'x - skipping rotate-text90.c (File already exists)'
else
echo 'x - extracting rotate-text90.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'rotate-text90.c' &&
/* Notes :
X * Text90() draws a text string rotated by 90 degrees on the given
X * drawable and given gc. The gc is not modified. Text90() respects
X * the Foreground, ClipMask, and ClipOrigin components of the
X * gc. You must pass the Fontstruct separately because Text90()
X * needs to determine text extents from the gc alone.
X *
X * The general scheme is as follows. First make a 1 bit deep pixmap
X * and render the text using the usual XDrawString() function.
X * Then use XGetImage() to pull that back to the client, XCreateImage()
X * another XImage and put the rotated points from the gotten image
X * into it. XPutImage() the rotated image back to another 1 bit
X * deep pixmap on the server. Now, if there were not a ClipMask
X * set in the gc, we could use this pixmap with the rotated image
X * ('rot_pm') as a ClipMask in gc and use FillRectangle on the
X * given drawable. But this would ignore and destroy the ClipMask
X * in the given gc. So we make another pixmap ('deep_pm'), as deep
X * as the given drawable, XCopyArea() the relevant stuff in the
X * drawable into deep_pm, then using 'rot_pm' as a ClipMask
X * call XFillRectangle to bleed the rotated text onto 'deep_pm',
X * then XCopyArea 'deep_pm' back onto the given drawable, using
X * the given 'gc' so its ClipMask is respected. Whew.
X *
X * The XImage structure needs a Visual when you create it with
X * XCreateImage. I am making an XImage which should be identical
X * except in shape to the that I got from XGetImage but the gotten
X * one contains no information about the Visual. I punt and use
X * the default Visual of the default Screen -- I am only making
X * a 1 bit deep pixmap so what difference can it make?.
X *
X * I need to pass a drawable_depth to Text90 because there is no
X * way to ask a drawable how deep it is.
X *
X * If we knew that there were no ClipMask in the given gc we could
X * skip the 2 CopyArea()s, but there is no way to determine this
X * without passing yet another argument to Text90 (an argument whose
X * value is probably not known by the caller).
X *
X * Text90 allocates and frees quite a few X objects. If your server
X * has memory leaks you will find out about them using this. Perhaps
X * one could cache these things as statics to Text90.
X *
X * I have included a test main() program. To use it :
X * cc -o xrot xrot.c -lX11 -lm
X * xrot xpos ypos
X * where xpos and ypos give the position of the string.
X *
X * If any one has a better way of doing this, please tell me about it.
X *
X * Bill Dunlap
X * Dept. of Statistics, GN-22
X * University of Washington
X * Seattle, WA 98195
X * bill at stat.washington.edu
X */
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
X
void Text90() ;
static void BailOut() ;
static Display *dpy ;
static Window win ;
static XFontStruct *fontstruct ;
static GC win_gc ;
static XGCValues xgcv ;
extern char *malloc() ;
X
/* ARGSUSED */
main(argc, argv)
int argc ;
char **argv ;
{
X unsigned long fg, bg ;
X int x, y ;
X if (!(--argc>0 && sscanf(*++argv, "%d", &x)==1))
X x = 20 ;
X if (!(--argc>0 && sscanf(*++argv, "%d", &y)==1))
X y = 20 ;
X dpy = XOpenDisplay((char *)NULL) ;
X if (!dpy) BailOut("XOpenDisplay") ;
X fg = BlackPixel(dpy, DefaultScreen(dpy)) ;
X bg = WhitePixel(dpy, DefaultScreen(dpy)) ;
#define WIN_WIDTH 500
#define WIN_HEIGHT 100
X win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
X 200, 200, /* position */
X WIN_WIDTH, WIN_HEIGHT, /* size */
X 2, /* border width */
X fg, /* border color */
X bg) ; /* background color */
X if (!win) BailOut("XCreateSimpleWindow") ;
#define STRING "This is a test"
X fontstruct = XLoadQueryFont(dpy, "fixed") ;
X if (!fontstruct) BailOut("XLoadQueryFont") ;
X xgcv.foreground = fg ;
X xgcv.background = bg ;
X xgcv.line_width = 4 ;
X win_gc = XCreateGC(dpy, win,
X GCForeground|GCBackground|GCLineWidth,
X &xgcv) ;
X if (!win_gc) BailOut("XCreateGC(win_gc)") ;
X XSelectInput(dpy, win, ExposureMask) ;
X XMapWindow(dpy, win) ;
X while (1) {
X XRectangle rect ;
X XEvent event ;
X XWindowAttributes xwa ;
X XNextEvent(dpy, &event) ;
X if (!(event.type == Expose && ((XExposeEvent *)&event)->count == 0))
X continue ;
X if (!XGetWindowAttributes(dpy, win, &xwa))
X break ;
X XClearWindow(dpy, win) ;
#define MARGIN 5
X rect.x = MARGIN ; rect.y = MARGIN ;
X rect.width = xwa.width - 2 * MARGIN ;
X rect.height = xwa.height - 2 * MARGIN ;
X XSetClipRectangles(dpy, win_gc, 0, 0, &rect, 1, Unsorted) ;
X XDrawLine(dpy, win, win_gc, 0, 0, xwa.width, xwa.height) ;
X XDrawLine(dpy, win, win_gc, xwa.width, 0, 0, xwa.height) ;
X Text90(dpy, win, xwa.depth, win_gc, x, y, STRING, strlen(STRING), fontstruct) ;
X }
X exit(0) ;
}
X
static void
BailOut(msg)
char *msg ;
{
X fprintf(stderr, "Error in %s -- bailing out\n", msg) ;
X exit(1) ;
}
X
void
Text90(dpy, drawable, drawable_depth, gc, x, y, string, length, fontstruct)
Display *dpy ;
Drawable drawable ;
int drawable_depth ;
GC gc ;
int x, y ;
char *string ;
int length ;
XXFontStruct *fontstruct ;
{
X Pixmap pm, rot_pm, deep_pm ;
X GC pm_gc, deep_gc ;
X XImage *image, *rot_image ;
X int row, col ;
X char *d ;
X int rot_bytes_per_line ;
X XCharStruct xcs ;
X int width, height ;
X int direction, font_ascent, font_descent ;
X XTextExtents(fontstruct, string, length,
X &direction, &font_ascent, &font_descent,
X &xcs) ;
X width = xcs.width ;
X height = font_ascent + font_descent ;
X pm = XCreatePixmap(dpy, win, width, height, 1) ;
X if (!pm) BailOut("XCreatePixmap") ;
X rot_pm = XCreatePixmap(dpy, drawable, height, width, 1) ;
X if (!rot_pm) BailOut("XCreatePixmap") ;
X xgcv.foreground = 1 ; /* yes, 1, this will be a mask */
X xgcv.background = 0 ;
X xgcv.font = fontstruct->fid ;
X pm_gc = XCreateGC(dpy, pm,
X GCForeground|GCBackground|GCFont,
X &xgcv) ;
X if (!pm_gc) BailOut("XCreateGC(pm_gc)") ;
X XDrawString(dpy, pm, pm_gc, 0, font_ascent, string, length) ;
X image = XGetImage(dpy, pm, 0, 0, width, height, AllPlanes, XYPixmap) ;
X if (!image) BailOut("XGetImage") ;
#define roundup(n, mod) ( (n)%(mod) ? (1+(n)/(mod))*mod : n )
X rot_bytes_per_line = roundup(image->height, image->bitmap_pad)/(image->bitmap_pad/8) ;
X d = (char *)malloc(rot_bytes_per_line * image->width) ;
X if (!d) BailOut("malloc") ;
X rot_image = XCreateImage(dpy,
X DefaultVisual(dpy, 0), /* I want the same as is in image */
X image->depth,
X image->format,
X image->xoffset,
X d,
X image->height, image->width, /* yes, reverse these */
X image->bitmap_pad,
X rot_bytes_per_line) ;
X if (!rot_image) BailOut("XCreateImage") ;
X /* rotate image 90 degrees clockwise */
X for(row=0 ; row<image->height ; row++) {
X for(col=0 ; col<image->width ; col++) {
X (void)XPutPixel(rot_image, row, rot_image->height-1-col,
X XGetPixel(image, col, row)) ;
X }
X }
X XPutImage(dpy, rot_pm, pm_gc, rot_image,
X 0, 0, /* source origin */
X 0, 0, /* dest origin */
X rot_image->width, rot_image->height) ;
X /* Now the pixmap rot_pm contains a mask of the rotated text */
X
X deep_pm = XCreatePixmap(dpy, drawable,
X rot_image->width, rot_image->height, drawable_depth) ;
X if (!deep_pm) BailOut("XCreatePixmap(deep_pm)") ;
X deep_gc = XCreateGC(dpy, deep_pm, 0L, &xgcv) ;
X if (!deep_gc) BailOut("XCreateGC(deep_gc)") ;
X XCopyArea(dpy, drawable, deep_pm, deep_gc,
X x, y, /* source origin */
X rot_image->width, rot_image->height, /* size */
X 0, 0) ; /* destination origin */
X XCopyGC(dpy, gc, GCForeground, deep_gc) ;
X XSetClipMask(dpy, deep_gc, rot_pm) ;
X XFillRectangle(dpy, deep_pm, deep_gc, 0, 0,
X rot_image->width, rot_image->height) ;
X XCopyArea(dpy, deep_pm, drawable, gc,
X 0, 0, /* source origin */
X rot_image->width, rot_image->height, /* size */
X x, y) ; /* destination origin */
X
X /* I set these things to NULL after freeing to prepare for
X * caching them */
X free(d) ; d = (char *)NULL ;
X XFreeGC(dpy, pm_gc) ; pm_gc = (GC)NULL ;
X XFreeGC(dpy, deep_gc) ; deep_gc = (GC)NULL ;
X XFreePixmap(dpy, pm) ; pm = (Pixmap)NULL ;
X XFreePixmap(dpy, deep_pm) ; deep_pm = (Pixmap)NULL ;
X XFreePixmap(dpy, rot_pm) ; rot_pm = (Pixmap)NULL ;
X XDestroyImage(image) ; image = (XImage *)NULL ;
X XDestroyImage(rot_image) ; rot_image = (XImage *)NULL ;
X /* did I free everything? */
X return ;
}
SHAR_EOF
chmod 0664 rotate-text90.c ||
echo 'restore of rotate-text90.c failed'
Wc_c="`wc -c < 'rotate-text90.c'`"
test 8067 -eq "$Wc_c" ||
echo 'rotate-text90.c: original size 8067, current size' "$Wc_c"
fi
exit 0
--
-----------------------------------------------------------------------------
mleisher at nmsu.edu "I laughed.
Mark Leisher I cried.
Computing Research Lab I fell down.
New Mexico State University It changed my life."
Las Cruces, NM - Rich [Cowboy Feng's Space Bar and Grille]
More information about the Alt.sources
mailing list