[comp.windows.x] rotated text

argv%eureka@Sun.COM (Dan Heller) (05/18/89)

Now that I'm talking about fonts, inspection of the code *appears*
to be just shy of giving XDrawString the ability to render rotated
text.  The following changes would need to happen: there needs to
be a height field in the XCharStruct data structure, and there needs
to be an ability to communicate this new information about the font
changes to the server.  The application is responsible for rotating
the glyphs of the characters, of course.

typedef struct {
    short       lbearing;       /* origin to left edge of raster */
    short       rbearing;       /* origin to right edge of raster */
    short       width;          /* advance to next char's origin */
/+  short	height;		/* advance to next y coord */ +/
    short       ascent;         /* baseline to top edge of raster */
    short       descent;        /* baseline to bottom edge of raster */
    unsigned short attributes;  /* per char flags (not predefined) */
} XCharStruct;

Here, the "width" is currently used to move the position of the
next x coord for rendering the next character.  However, the y
coord stays the same.  I don't see a requirement that this has
to be this way -- with the "height" parameter, the next char's
origin can be moved up or down as well.  If the application
chooses to not rotate the glyphs, the the characters rendered
may have a stepping stone effect.  With negative values in the
height and width fields, the text may be rendered from right
to left.

Affected called would include all the routines which would get 
the geometry of a string including the bounding boxes, text width
and height, etc...

Feedback?

dan <island!argv@sun.com>
    dan  <argv@sun.com>

clive@ixi.UUCP (Clive Feather) (05/19/89)

In article <105466@sun.Eng.Sun.COM> argv@sun (Dan Heller) writes:
>Now that I'm talking about fonts, inspection of the code *appears*
>to be just shy of giving XDrawString the ability to render rotated
>text.  The following changes would need to happen: there needs to
>be a height field in the XCharStruct data structure, and there needs
>to be an ability to communicate this new information about the font
>changes to the server.  The application is responsible for rotating
>the glyphs of the characters, of course.

Firstly, changing the XCharStruct data structure means changing the
protocol, and there's no way that the real world out there is going
to let you (yes, I know that there have been changes from R1 to R2
to R3, but they were subtle and upwards compatible - this would be
*totally* incompatible).

Next, isn't the "width" and "height" of the character going to change
as you change the angle ?

Far more important - how is the application going to rotate the
glyphs ? They're not in the XFontStruct or anything that hangs off
it. This means that to get hold of them, you need to do something on
the lines of:

    create a pixmap just big enough to hold the largest character
      in the font, and depth 1;
    create a GC for working on this pixmap;
    for (each character c in the font)
    {
        XSetForeground (GC, 0);
        XFillRectangle (the whole pixmap);
        XSetForeground (GC, 1);
        XDrawString (pixmap, an appropriate position,
                     a string of length 1 holding c);
        glyph [c] = XGetImage (the pixmap);
    }

BTW, please describe an algorithm for rotating the characters *neatly*.

Finally, there is no way to turn these rotated glyphs back into a font !
The nearest that you can do is something like:

    Rotate the glyphs.
    Write them out in BDF (Bitmap Distribution Format), wrapped
      up to form a font.
    Run bdftosnf on the font.
    Install the font in an appropriate directory.
    Run mkfontdir on that directory.
    Reboot your server (or possibly, mess around with XSetFontPath).

If you just want to write the characters at an angle, without rotating
the glyphs, then the following might be of use to you:

WARNING:
Untested (and uncompiled) code follows.

=============================== 8< ==================================
/*
    DISCLAIMER:
    I am not interested in bug fixes or any other comments on this code.
    This has been written just to make a point.
    This is not supported code of IXI Limited.

    COPYRIGHT:
    This code is in the public domain (or whatever the equivalent is in
    English law).

    DESCRIPTION:
    XDrawAngledString (display, d, gc, fs, x, y, angle, string, length)

    Arguments as XDrawString, except "fs", which is the XFontStruct for
    the font, and "angle", which is a double.

    This function draws a string, placing the glyphs along a line at
    an angle to the horizontal, spaced at the correct distance along
    that line but not rotating the glyphs.
*/

XDrawAngledString (display, d, gc, fs, x, y, angle, string, length)
Display *display;
Drawable d;
GC gc;
XFontStruct *fs;
int x, y;
double angle;
char *string;
int length;
{
    int i;
    int xx = x;
    int xx = y;
    double si = sin (angle);
    double co = cos (angle);
    char *c;

    for (i = 0, c = string; i < length; i++, c++)
    {
        int w;

        XDrawString (display, d, gc, xx, yy, c, 1);
        w = XTextWidth (fs, c, 1);
        xx += si * w;
        yy += co * w;
    }
}
=============================== 8< ==================================
-- 
Clive D.W. Feather           clive@ixi.uucp
IXI Limited                  ...!mcvax!ukc!ixi!clive (riskier)
                             +44 223 462 131

ondrejko@paul.rutgers.edu (Michael Ondrejko) (05/19/89)

We are about to start design of an application that could use rotated text
within a graphics window.  From what I have noticed Xlib (& Xtoolkit) only
provide for horizontal text. I would appreciate any information that could
be provided.

Thanks,
Michael Ondrejko (ondrejko@paul.rutgers.edu)

dheller@cory.Berkeley.EDU (Dan Heller) (05/21/89)

> In article <105466@sun.Eng.Sun.COM> argv@sun (Dan Heller) writes:
> >Now that I'm talking about fonts, inspection of the code *appears*
> >to be just shy of giving XDrawString the ability to render rotated
> >text.  The following changes would need to happen: there needs to
> >be a height field in the XCharStruct data structure, and there needs
> >to be an ability to communicate this new information about the font
> >changes to the server.  The application is responsible for rotating
> >the glyphs of the characters, of course.

In article <169@ixi.UUCP> clive@ixi.uucp (Clive Feather) writes:
> Firstly, changing the XCharStruct data structure means changing the
> protocol, and there's no way that the real world out there is going
> to let you 

This is the biggest problem, of course and for that reason, it's all a
moot point.  However, this need not be in there were an -additional-
font type which has different calling functions from the currently existing
font types.  Since for rotated text, calls such as XTextWidth doesn't make
a lot of sense (since there is another dimension involved).  A new set of
functions could be introduced to support this stuff.  I or anyone else isn't
going to go to the effort to do so if X is definitively going to stay out
of the page description aspect of graphics.

> Next, isn't the "width" and "height" of the character going to change
> as you change the angle ?
Yes -- and that's why I'd like to have the ability to send a request to
the server to modify this information.  This wouldn't apply to any arbitrary
font, it would apply only to fonts which have been "uploaded" by the
application (uploaded fonts could be flaged as read/write)..  If the
application decides to rotate text, then it could send a request to the
server to change the width/height attributes of a font.  This doesn't
necessarily require the glyphs to rotate of course.  You can have chars
which appear as steps.  Similarly, you can rotate glyphs without affecting
the way their orientation appears.  These are all concepts in the printing
industry that are not unusual.  Since great efforts were made to make X
suitable for creating a "Draw" package by supporting all sorts of geometric
shapes, line styles, end caps, and so on, why not extend the protocol to
do reasonable page description support.

> Far more important - how is the application going to rotate the
> glyphs ? They're not in the XFontStruct or anything that hangs off
> it. This means that to get hold of them, you need to do something on
> the lines of:

The X server stores the glyphs somewhere (admittedly, I don't know the
internals to this that well).  However they are stored, it would be nice
to be able to tell the server to change the glyph of a particular character.

XSetFontGlyph(fid, c, glyph)
XID fid; /* font id */
int c;   /* index into the font table */
Pixmap glyph; /* change image to use this glyph */

> BTW, please describe an algorithm for rotating the characters *neatly*.

There are many ways to store font information.  So as not to threat anyone's
technology, let's consider the most simple case -- fonts stored as bitmaps.
Here, a simple bitmap rotation method is all you need.  Again, this does not
necessarily represent characters, even tho it's likely.  The actual rotation
of glyphs can be simple or complex depending on the needs (intelligence?) of
the application.

> Finally, there is no way to turn these rotated glyphs back into a font !
A font is nothing more than a set of glyphs and information about them.
If I take an 'A' and use some magic to rotate it (again, use the bitmap
rotation analogy), then the glyph, in my font book, still represents an A.
It is still a font.  A well designed application will obviously save its
"initial" information about a font so numerous transformations don't
degenerate the image into a set of random pixels.

> The nearest that you can do is something like:
> 
>     Rotate the glyphs.
>     Write them out in BDF (Bitmap Distribution Format), wrapped
>       up to form a font.
>     Run bdftosnf on the font.
>     Install the font in an appropriate directory.
>     Run mkfontdir on that directory.

This is *precisely* what I want to avoid.  I want to be able to load a
font directly into the server from an application -- and, I want to 
modify that font from the application.  Clearly, there are restrictions
on this special font that don't apply to the other fonts -- e.g. you don't
get the font listed from xlsfonts; the font is read/write; the font is
only available to the client using the font; the font is destroyed and
all information about it is freed in case the application dies or sends
a XFreeFont type of request.  These are just issues from the top of my
head -- I haven't gone into a design phase of this.

>     Reboot your server (or possibly, mess around with XSetFontPath).
If XSetFontPath exists, then there are clearly the internal functions
available to actually load a new font or change font info at runtime.

Next, you provide a sample routine which demonstrates my point that the
need for rotated font information should exist.  first, a quick review
of your routine:

>     for (i = 0, c = string; i < length; i++, c++)
>     {
>         int w;
> 
>         XDrawString (display, d, gc, xx, yy, c, 1);
>         w = XTextWidth (fs, c, 1);
>         xx += si * w;
>         yy += co * w;
>     }

I should point out that this is just about what I *am* doing now in order
to display rotated fonts because there is no other method available.  The
routine involves two expensive operations: XDrawString and XTextWidth.  For
one thing, both of these routines involve communication with the server --
in the case of XTextWidth, the glyph is gotten from the server for inspection.
Both of these routines, when compounded by the length of the string, will
generate lots of network traffic as well as poor performance.

If the height and width information I described before were stored in the
font or character somehow, then the string can be rendered with the single
call to XDrawString and the server can handle the placement of the next
character internally.  It already does it for the width --the only change
necessary would be for its height.

Dan Heller	<island!argv@sun.com>

brown@ftms.UUCP (Vidiot) (03/20/91)

We are looking for pointers, hints or code that will allow us to put up text
in a window that isn't horizontal.

The idea is to label (for instance) a graph's left (Y) axis with text that is
rotated 90 degrees clockwise.

Does anyone have ways of doing this?  If so, please send me some e-mail.  It
will be appreciated.
-- 
harvard\
  ucbvax!uwvax!astroatc!ftms!brown
rutgers/
INTERNET: spool.cs.wisc.edu!astroatc!ftms!brown

mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (03/22/91)

> We are looking for pointers, hints or code that will allow us to put
> up text in a window that isn't horizontal.

[It's the text that's to be non-horizontal, not the window.]

From the FAQ:

----------------------------------------------------------------------
Subject: 110)  How do I render rotated text?
	
	Xlib intentionally does not provide such sophisticated graphics 
capabilities, leaving them up to server-extensions or clients-side graphics
libraries.
	Your only choice, if you want to stay within the core X protocol, is to
render the text into a pixmap, read it back via XGetImage(), rotate it "by hand"
with whatever matrices you want, and put it back to the server via XPutImage();
more specifically:
	1) create a bitmap B and write your text to it.
	2) create an XYBitmap image I from B (via XGetImage).
	3) create an XYBitmap Image I2 big enough to handle the transformation.
	4) for each x,y in I2, I2(x,y) = I(a,b) where 
		a = x * cos(theta) - y * sin(theta)
		b = x * sin(theta) + y * cos(theta)
	5) render I2
	Note that you should be careful how you implement this not to lose
bits; an algorithm based on shear transformations may in fact be better.
	The high-level server-extensions and graphics packages available for X 
also permit rendering of rotated text: Display PostScript, PEX, PHIGS, and GKS,
although most are not capable of arbitrary rotation and probably do not use the
same fonts that would be found on a printer.
	In addition, if you have enough access to the server to install a font
on it, you can create a font which consists of letters rotated at some
predefined angle. Your application can then itself figure out placement of each
glyph.

[courtesy der Mouse (mouse@larry.mcrcim.mcgill.edu), Eric Taylor 
(etaylor@wilkins.bmc.tmc.edu), and Ken Lee (klee@wsl.dec.com), 11/90;
Liam Quin (lee@sq.com), 12/90]

----------------------------------------------------------------------

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

brsmith@cs.umn.edu (Brian R. Smith) (03/23/91)

In <9103220518.AA05516@lightning.McRCIM.McGill.EDU> mouse@lightning.mcrcim.mcgill.EDU (der Mouse) writes:

>> We are looking for pointers, hints or code that will allow us to put
>> up text in a window that isn't horizontal.

>[It's the text that's to be non-horizontal, not the window.]

>From the FAQ:

>----------------------------------------------------------------------
>Subject: 110)  How do I render rotated text?
>	
>	Xlib intentionally does not provide such sophisticated
>graphics capabilities, leaving them up to server-extensions or
>clients-side graphics libraries.  	Your only choice, if you want
>to stay within the core X protocol, is to render the text into a
>pixmap, read it back via XGetImage(), rotate it "by hand" with
>whatever matrices you want, and put it back to the server via
>XPutImage(); more specifically:

On a related note:

InterViews (C++ UI toolkit, in the X contrib software) has support for
rendering rotated fonts in X.  It could be one source of example code.
(With the caveat that it is a somewhat large and complex piece of
software to go dredging through for that one specific piece of
information.)
--
Brian