mirror of
https://git.code.sf.net/p/flwm/flwm
synced 2025-12-12 07:16:57 -05:00
Use fltk 1.3's ability to draw rotated text
This removes a huge and quite obsolete kludge that worked with X bitmap fonts only. Looks a lot nicer.
This commit is contained in:
14
Frame.C
14
Frame.C
@ -7,8 +7,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <FL/fl_draw.H>
|
#include <FL/fl_draw.H>
|
||||||
#include "Rotated.H"
|
|
||||||
|
|
||||||
|
|
||||||
static Atom wm_state = 0;
|
static Atom wm_state = 0;
|
||||||
static Atom wm_change_state;
|
static Atom wm_change_state;
|
||||||
@ -1257,6 +1255,7 @@ void Frame::draw() {
|
|||||||
fl_frame("AAAAWWJJTTNN",0,0,w(),h());
|
fl_frame("AAAAWWJJTTNN",0,0,w(),h());
|
||||||
#endif
|
#endif
|
||||||
if (!flag(THIN_BORDER) && label_h > 3) {
|
if (!flag(THIN_BORDER) && label_h > 3) {
|
||||||
|
fl_push_clip(1, label_y, left, label_h);
|
||||||
#ifdef SHOW_CLOCK
|
#ifdef SHOW_CLOCK
|
||||||
if (active()) {
|
if (active()) {
|
||||||
int clkw = int(fl_width(clock_buf));
|
int clkw = int(fl_width(clock_buf));
|
||||||
@ -1275,8 +1274,9 @@ void Frame::draw() {
|
|||||||
// and the window height is short enough. For now, we'll
|
// and the window height is short enough. For now, we'll
|
||||||
// assume this is not enough of a problem to be concerned
|
// assume this is not enough of a problem to be concerned
|
||||||
// about.
|
// about.
|
||||||
draw_rotated90(clock_buf, 1, label_y+3, left-1, label_h-6,
|
fl_draw(90, clock_buf,
|
||||||
Fl_Align(FL_ALIGN_BOTTOM|FL_ALIGN_CLIP));
|
(left + fl_height() + 1)/2 - fl_descent(),
|
||||||
|
label_y+label_h-3);
|
||||||
} else
|
} else
|
||||||
// Only show the clock on the active frame.
|
// Only show the clock on the active frame.
|
||||||
XClearArea(fl_display, fl_xid(this), 1, label_y+3,
|
XClearArea(fl_display, fl_xid(this), 1, label_y+3,
|
||||||
@ -1284,8 +1284,10 @@ void Frame::draw() {
|
|||||||
#endif
|
#endif
|
||||||
fl_color(labelcolor());
|
fl_color(labelcolor());
|
||||||
fl_font(TITLE_FONT_SLOT, TITLE_FONT_SIZE);
|
fl_font(TITLE_FONT_SLOT, TITLE_FONT_SIZE);
|
||||||
draw_rotated90(label(), 1, label_y+3, left-1, label_h-3,
|
fl_draw(90, label(),
|
||||||
Fl_Align(FL_ALIGN_TOP|FL_ALIGN_CLIP));
|
(left + fl_height() + 1)/2 - fl_descent(),
|
||||||
|
label_y+3+fl_width(label()));
|
||||||
|
fl_pop_clip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
Makefile
5
Makefile
@ -3,7 +3,7 @@ SHELL=/bin/sh
|
|||||||
PROGRAM = flwm
|
PROGRAM = flwm
|
||||||
VERSION = 1.02
|
VERSION = 1.02
|
||||||
|
|
||||||
CXXFILES = main.C Frame.C Rotated.C Menu.C FrameWindow.C Desktop.C Hotkeys.C
|
CXXFILES = main.C Frame.C Menu.C FrameWindow.C Desktop.C Hotkeys.C
|
||||||
|
|
||||||
MANPAGE = 1
|
MANPAGE = 1
|
||||||
|
|
||||||
@ -80,6 +80,3 @@ OBJECTS_D = $(CXXFILES:.C=.do) $(CFILES:.c=.do)
|
|||||||
|
|
||||||
$(PROGRAM_D) : $(OBJECTS_D)
|
$(PROGRAM_D) : $(OBJECTS_D)
|
||||||
$(CXX) $(LDFLAGS) -o $(PROGRAM_D) $(OBJECTS_D) $(LIBS)
|
$(CXX) $(LDFLAGS) -o $(PROGRAM_D) $(OBJECTS_D) $(LIBS)
|
||||||
|
|
||||||
rotated_test: Rotated.o rotated_test.C
|
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o rotated_test rotated_test.C Rotated.o $(LIBS) $(LIBS)
|
|
||||||
|
|||||||
442
Rotated.C
442
Rotated.C
@ -1,442 +0,0 @@
|
|||||||
// Rotated text drawing with X.
|
|
||||||
|
|
||||||
// Original code:
|
|
||||||
// Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) */
|
|
||||||
//
|
|
||||||
// Modifications for fltk:
|
|
||||||
// Copyright (c) 1997 Bill Spitzak (spitzak@d2.com)
|
|
||||||
// Modifications are to draw using the current fl_font. All fonts
|
|
||||||
// used are cached in local structures. This can get real expensive,
|
|
||||||
// use "
|
|
||||||
|
|
||||||
/* xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma)
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software and its
|
|
||||||
* documentation for any purpose and without fee is hereby granted, provided
|
|
||||||
* that the above copyright notice appear in all copies and that both the
|
|
||||||
* copyright notice and this permission notice appear in supporting
|
|
||||||
* documentation. All work developed as a consequence of the use of
|
|
||||||
* this program should duly acknowledge such use. No representations are
|
|
||||||
* made about the suitability of this software for any purpose. It is
|
|
||||||
* provided "as is" without express or implied warranty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// if not defined then portions not used by flwm are included:
|
|
||||||
#define FLWM 1
|
|
||||||
|
|
||||||
/* ********************************************************************** */
|
|
||||||
|
|
||||||
#define FL_INTERNALS 1
|
|
||||||
#include <FL/x.H>
|
|
||||||
#if FL_MAJOR_VERSION < 2
|
|
||||||
# define XWindow Window
|
|
||||||
#endif
|
|
||||||
#include <FL/fl_draw.H>
|
|
||||||
#include "Rotated.H"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
struct BitmapStruct {
|
|
||||||
int bit_w;
|
|
||||||
int bit_h;
|
|
||||||
Pixmap bm;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct XRotCharStruct {
|
|
||||||
int ascent;
|
|
||||||
int descent;
|
|
||||||
int lbearing;
|
|
||||||
int rbearing;
|
|
||||||
int width;
|
|
||||||
BitmapStruct glyph;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct XRotFontStruct {
|
|
||||||
int dir;
|
|
||||||
int height;
|
|
||||||
int max_ascent;
|
|
||||||
int max_descent;
|
|
||||||
int max_char;
|
|
||||||
int min_char;
|
|
||||||
XFontStruct* xfontstruct;
|
|
||||||
XRotCharStruct per_char[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* *** Load the rotated version of a given font *** */
|
|
||||||
|
|
||||||
static XRotFontStruct*
|
|
||||||
XRotLoadFont(Display *dpy, XFontStruct* fontstruct, int dir)
|
|
||||||
{
|
|
||||||
char val;
|
|
||||||
XImage *I1, *I2;
|
|
||||||
Pixmap canvas;
|
|
||||||
XWindow root;
|
|
||||||
int screen;
|
|
||||||
GC font_gc;
|
|
||||||
char text[3];/*, errstr[300];*/
|
|
||||||
|
|
||||||
XRotFontStruct *rotfont;
|
|
||||||
int ichar, i, j, index, boxlen = 60;
|
|
||||||
int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
|
|
||||||
int min_char, max_char;
|
|
||||||
unsigned char *vertdata, *bitdata;
|
|
||||||
int ascent, descent, lbearing, rbearing;
|
|
||||||
int on = 1, off = 0;
|
|
||||||
|
|
||||||
/* useful macros ... */
|
|
||||||
screen = DefaultScreen(dpy);
|
|
||||||
root = DefaultRootWindow(dpy);
|
|
||||||
|
|
||||||
/* create the depth 1 canvas bitmap ... */
|
|
||||||
canvas = XCreatePixmap(dpy, root, boxlen, boxlen, 1);
|
|
||||||
|
|
||||||
/* create a GC ... */
|
|
||||||
font_gc = XCreateGC(dpy, canvas, 0, 0);
|
|
||||||
XSetBackground(dpy, font_gc, off);
|
|
||||||
|
|
||||||
XSetFont(dpy, font_gc, fontstruct->fid);
|
|
||||||
|
|
||||||
/* allocate space for rotated font ... */
|
|
||||||
rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
|
|
||||||
|
|
||||||
/* determine which characters are defined in font ... */
|
|
||||||
min_char = fontstruct->min_char_or_byte2;
|
|
||||||
if (min_char<0) min_char = 0;
|
|
||||||
rotfont->min_char = min_char;
|
|
||||||
max_char = fontstruct->max_char_or_byte2;
|
|
||||||
if (max_char>255) max_char = 255;
|
|
||||||
rotfont->max_char = max_char;
|
|
||||||
|
|
||||||
/* some overall font data ... */
|
|
||||||
rotfont->dir = dir;
|
|
||||||
rotfont->max_ascent = fontstruct->max_bounds.ascent;
|
|
||||||
rotfont->max_descent = fontstruct->max_bounds.descent;
|
|
||||||
rotfont->height = rotfont->max_ascent+rotfont->max_descent;
|
|
||||||
|
|
||||||
rotfont->xfontstruct = fontstruct;
|
|
||||||
/* remember xfontstruct for `normal' text ... */
|
|
||||||
if (dir != 0) {
|
|
||||||
/* font needs rotation ... */
|
|
||||||
/* loop through each character ... */
|
|
||||||
for (ichar = min_char; ichar <= max_char; ichar++) {
|
|
||||||
|
|
||||||
index = ichar-fontstruct->min_char_or_byte2;
|
|
||||||
|
|
||||||
XCharStruct* charstruct;
|
|
||||||
if (fontstruct->per_char)
|
|
||||||
charstruct = fontstruct->per_char+index;
|
|
||||||
else
|
|
||||||
charstruct = &fontstruct->min_bounds;
|
|
||||||
|
|
||||||
/* per char dimensions ... */
|
|
||||||
ascent = rotfont->per_char[ichar].ascent = charstruct->ascent;
|
|
||||||
descent = rotfont->per_char[ichar].descent = charstruct->descent;
|
|
||||||
lbearing = rotfont->per_char[ichar].lbearing = charstruct->lbearing;
|
|
||||||
rbearing = rotfont->per_char[ichar].rbearing = charstruct->rbearing;
|
|
||||||
rotfont->per_char[ichar].width = charstruct->width;
|
|
||||||
|
|
||||||
/* some space chars have zero body, but a bitmap can't have ... */
|
|
||||||
if (!ascent && !descent)
|
|
||||||
ascent = rotfont->per_char[ichar].ascent = 1;
|
|
||||||
if (!lbearing && !rbearing)
|
|
||||||
rbearing = rotfont->per_char[ichar].rbearing = 1;
|
|
||||||
|
|
||||||
/* glyph width and height when vertical ... */
|
|
||||||
vert_w = rbearing-lbearing;
|
|
||||||
vert_h = ascent+descent;
|
|
||||||
|
|
||||||
/* width in bytes ... */
|
|
||||||
vert_len = (vert_w-1)/8+1;
|
|
||||||
|
|
||||||
XSetForeground(dpy, font_gc, off);
|
|
||||||
XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
|
|
||||||
|
|
||||||
/* draw the character centre top right on canvas ... */
|
|
||||||
sprintf(text, "%c", ichar);
|
|
||||||
XSetForeground(dpy, font_gc, on);
|
|
||||||
XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
|
|
||||||
boxlen/2 - descent, text, 1);
|
|
||||||
|
|
||||||
/* reserve memory for first XImage ... */
|
|
||||||
vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
|
|
||||||
|
|
||||||
/* create the XImage ... */
|
|
||||||
I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
|
|
||||||
0, (char *)vertdata, vert_w, vert_h, 8, 0);
|
|
||||||
|
|
||||||
// if (I1 == NULL) ... do something here
|
|
||||||
|
|
||||||
I1->byte_order = I1->bitmap_bit_order = MSBFirst;
|
|
||||||
|
|
||||||
/* extract character from canvas ... */
|
|
||||||
XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
|
|
||||||
vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
|
|
||||||
I1->format = XYBitmap;
|
|
||||||
|
|
||||||
/* width, height of rotated character ... */
|
|
||||||
if (dir == 2) {
|
|
||||||
bit_w = vert_w;
|
|
||||||
bit_h = vert_h;
|
|
||||||
} else {
|
|
||||||
bit_w = vert_h;
|
|
||||||
bit_h = vert_w;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* width in bytes ... */
|
|
||||||
bit_len = (bit_w-1)/8 + 1;
|
|
||||||
|
|
||||||
rotfont->per_char[ichar].glyph.bit_w = bit_w;
|
|
||||||
rotfont->per_char[ichar].glyph.bit_h = bit_h;
|
|
||||||
|
|
||||||
/* reserve memory for the rotated image ... */
|
|
||||||
bitdata = (unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
|
|
||||||
|
|
||||||
/* create the image ... */
|
|
||||||
I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
|
|
||||||
(char *)bitdata, bit_w, bit_h, 8, 0);
|
|
||||||
|
|
||||||
// if (I2 == NULL) ... error
|
|
||||||
|
|
||||||
I2->byte_order = I2->bitmap_bit_order = MSBFirst;
|
|
||||||
|
|
||||||
/* map vertical data to rotated character ... */
|
|
||||||
for (j = 0; j < bit_h; j++) {
|
|
||||||
for (i = 0; i < bit_w; i++) {
|
|
||||||
/* map bits ... */
|
|
||||||
if (dir == 1)
|
|
||||||
val = vertdata[i*vert_len + (vert_w-j-1)/8] &
|
|
||||||
(128>>((vert_w-j-1)%8));
|
|
||||||
|
|
||||||
else if (dir == 2)
|
|
||||||
val = vertdata[(vert_h-j-1)*vert_len + (vert_w-i-1)/8] &
|
|
||||||
(128>>((vert_w-i-1)%8));
|
|
||||||
|
|
||||||
else
|
|
||||||
val = vertdata[(vert_h-i-1)*vert_len + j/8] &
|
|
||||||
(128>>(j%8));
|
|
||||||
|
|
||||||
if (val)
|
|
||||||
bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
|
|
||||||
(128>>(i%8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create this character's bitmap ... */
|
|
||||||
rotfont->per_char[ichar].glyph.bm =
|
|
||||||
XCreatePixmap(dpy, root, bit_w, bit_h, 1);
|
|
||||||
|
|
||||||
/* put the image into the bitmap ... */
|
|
||||||
XPutImage(dpy, rotfont->per_char[ichar].glyph.bm,
|
|
||||||
font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
|
|
||||||
|
|
||||||
/* free the image and data ... */
|
|
||||||
XDestroyImage(I1);
|
|
||||||
XDestroyImage(I2);
|
|
||||||
/* free((char *)bitdata); -- XDestroyImage does this
|
|
||||||
free((char *)vertdata);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ichar = 0; ichar < min_char; ichar++)
|
|
||||||
rotfont->per_char[ichar] = rotfont->per_char[int('?')];
|
|
||||||
for (ichar = max_char+1; ichar < 256; ichar++)
|
|
||||||
rotfont->per_char[ichar] = rotfont->per_char[int('?')];
|
|
||||||
|
|
||||||
/* free pixmap and GC ... */
|
|
||||||
XFreePixmap(dpy, canvas);
|
|
||||||
XFreeGC(dpy, font_gc);
|
|
||||||
|
|
||||||
return rotfont;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* *** Free the resources associated with a rotated font *** */
|
|
||||||
|
|
||||||
static void XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont)
|
|
||||||
{
|
|
||||||
int ichar;
|
|
||||||
|
|
||||||
if (rotfont->dir != 0) {
|
|
||||||
/* loop through each character, freeing its pixmap ... */
|
|
||||||
for (ichar = rotfont->min_char; ichar <= rotfont->max_char; ichar++)
|
|
||||||
XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
|
|
||||||
}
|
|
||||||
/* rotfont should never be referenced again ... */
|
|
||||||
free((char *)rotfont);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/* *** A front end to XRotPaintString : mimics XDrawString *** */
|
|
||||||
|
|
||||||
static void
|
|
||||||
XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable,
|
|
||||||
GC gc, int x, int y, const char *str, int len)
|
|
||||||
{
|
|
||||||
int i, xp, yp, dir, ichar;
|
|
||||||
|
|
||||||
if (str == NULL || len<1) return;
|
|
||||||
|
|
||||||
dir = rotfont->dir;
|
|
||||||
|
|
||||||
/* a horizontal string is easy ... */
|
|
||||||
if (dir == 0) {
|
|
||||||
XSetFont(dpy, gc, rotfont->xfontstruct->fid);
|
|
||||||
XDrawString(dpy, drawable, gc, x, y, str, len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vertical or upside down ... */
|
|
||||||
|
|
||||||
XSetFillStyle(dpy, gc, FillStippled);
|
|
||||||
|
|
||||||
/* loop through each character in string ... */
|
|
||||||
for (i = 0; i<len; i++) {
|
|
||||||
ichar = ((unsigned char*)str)[i];
|
|
||||||
|
|
||||||
/* suitable offset ... */
|
|
||||||
if (dir == 1) {
|
|
||||||
xp = x-rotfont->per_char[ichar].ascent;
|
|
||||||
yp = y-rotfont->per_char[ichar].rbearing;
|
|
||||||
}
|
|
||||||
else if (dir == 2) {
|
|
||||||
xp = x-rotfont->per_char[ichar].rbearing;
|
|
||||||
yp = y-rotfont->per_char[ichar].descent+1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xp = x-rotfont->per_char[ichar].descent+1;
|
|
||||||
yp = y+rotfont->per_char[ichar].lbearing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* draw the glyph ... */
|
|
||||||
XSetStipple(dpy, gc, rotfont->per_char[ichar].glyph.bm);
|
|
||||||
|
|
||||||
XSetTSOrigin(dpy, gc, xp, yp);
|
|
||||||
|
|
||||||
XFillRectangle(dpy, drawable, gc, xp, yp,
|
|
||||||
rotfont->per_char[ichar].glyph.bit_w,
|
|
||||||
rotfont->per_char[ichar].glyph.bit_h);
|
|
||||||
|
|
||||||
/* advance position ... */
|
|
||||||
if (dir == 1)
|
|
||||||
y -= rotfont->per_char[ichar].width;
|
|
||||||
else if (dir == 2)
|
|
||||||
x -= rotfont->per_char[ichar].width;
|
|
||||||
else
|
|
||||||
y += rotfont->per_char[ichar].width;
|
|
||||||
}
|
|
||||||
XSetFillStyle(dpy, gc, FillSolid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef FLWM
|
|
||||||
/* *** Return the width of a string *** */
|
|
||||||
|
|
||||||
static int XRotTextWidth(XRotFontStruct *rotfont, const char *str, int len)
|
|
||||||
{
|
|
||||||
int i, width = 0, ichar;
|
|
||||||
|
|
||||||
if (str == NULL) return 0;
|
|
||||||
|
|
||||||
if (rotfont->dir == 0)
|
|
||||||
width = XTextWidth(rotfont->xfontstruct, str, strlen(str));
|
|
||||||
|
|
||||||
else
|
|
||||||
for (i = 0; i<len; i++) {
|
|
||||||
width += rotfont->per_char[((unsigned char*)str)[i]].width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
// the public functions use the fltk global variables for font & gc:
|
|
||||||
|
|
||||||
static XRotFontStruct* font;
|
|
||||||
|
|
||||||
static void setrotfont(int angle) {
|
|
||||||
/* make angle positive ... */
|
|
||||||
if (angle < 0) do angle += 360; while (angle < 0);
|
|
||||||
/* get nearest vertical or horizontal direction ... */
|
|
||||||
int dir = ((angle+45)/90)%4;
|
|
||||||
if (font) {
|
|
||||||
if (font->xfontstruct == fl_xfont && font->dir == dir) return;
|
|
||||||
XRotUnloadFont(fl_display, font);
|
|
||||||
}
|
|
||||||
font = XRotLoadFont(fl_display, fl_xfont, dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_rotated(const char* text, int n, int x, int y, int angle) {
|
|
||||||
if (!text || !*text) return;
|
|
||||||
setrotfont(angle);
|
|
||||||
XRotDrawString(fl_display, font, fl_window, fl_gc, x, y, text, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(FLWM) || FL_MAJOR_VERSION>=2
|
|
||||||
void draw_rotated(const char* text, int x, int y, int angle) {
|
|
||||||
if (!text || !*text) return;
|
|
||||||
draw_rotated(text, strlen(text), x, y, angle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void draw_rot90(const char* str, int n, int x, int y) {
|
|
||||||
draw_rotated(str, n, y, -x, 90);
|
|
||||||
}
|
|
||||||
void draw_rotated90(
|
|
||||||
const char* str, // the (multi-line) string
|
|
||||||
int x, int y, int w, int h, // bounding box
|
|
||||||
Fl_Align align) {
|
|
||||||
if (!str || !*str) return;
|
|
||||||
if (w && h && !fl_not_clipped(x, y, w, h)) return;
|
|
||||||
if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
|
|
||||||
#if FL_MAJOR_VERSION>1
|
|
||||||
setrotfont(90);
|
|
||||||
int a = font->xfontstruct->ascent;
|
|
||||||
int d = font->xfontstruct->descent;
|
|
||||||
XRotDrawString(fl_display, font, fl_window, fl_gc,
|
|
||||||
x+(w+a-d+1)/2, y+h, str, strlen(str));
|
|
||||||
#else
|
|
||||||
int a1 = align&(-16);
|
|
||||||
if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_TOP;
|
|
||||||
if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_BOTTOM;
|
|
||||||
if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_RIGHT;
|
|
||||||
if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_LEFT;
|
|
||||||
fl_draw(str, -(y+h), x, h, w, (Fl_Align)a1, draw_rot90);
|
|
||||||
#endif
|
|
||||||
if (align & FL_ALIGN_CLIP) fl_pop_clip();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef FLWM
|
|
||||||
static void draw_rot180(const char* str, int n, int x, int y) {
|
|
||||||
draw_rotated(str, n, -x, -y, 180);
|
|
||||||
}
|
|
||||||
void draw_rotated180(
|
|
||||||
const char* str, // the (multi-line) string
|
|
||||||
int x, int y, int w, int h, // bounding box
|
|
||||||
Fl_Align align) {
|
|
||||||
int a1 = align&(-16);
|
|
||||||
if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_RIGHT;
|
|
||||||
if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_LEFT;
|
|
||||||
if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_BOTTOM;
|
|
||||||
if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_TOP;
|
|
||||||
fl_draw(str, -(x+w), -(y+h), w, h, (Fl_Align)a1, draw_rot180);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_rot270(const char* str, int n, int x, int y) {
|
|
||||||
draw_rotated(str, n, -y, x, 270);
|
|
||||||
}
|
|
||||||
void draw_rotated270(
|
|
||||||
const char* str, // the (multi-line) string
|
|
||||||
int x, int y, int w, int h, // bounding box
|
|
||||||
Fl_Align align) {
|
|
||||||
int a1 = align&(-16);
|
|
||||||
if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_BOTTOM;
|
|
||||||
if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_TOP;
|
|
||||||
if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_LEFT;
|
|
||||||
if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_RIGHT;
|
|
||||||
fl_draw(str, y, -(x+w), h, w, (Fl_Align)a1, draw_rot270);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
18
Rotated.H
18
Rotated.H
@ -1,18 +0,0 @@
|
|||||||
// Rotated text drawing with X.
|
|
||||||
|
|
||||||
// Original code:
|
|
||||||
// Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) */
|
|
||||||
//
|
|
||||||
// Modifications for fltk:
|
|
||||||
// Copyright (c) 1997 Bill Spitzak (spitzak@d2.com)
|
|
||||||
|
|
||||||
#ifndef Rotated_H
|
|
||||||
#define Rotated_H
|
|
||||||
|
|
||||||
void draw_rotated(const char* text, int n, int x, int y, int angle);
|
|
||||||
void draw_rotated(const char* text, int x, int y, int angle);
|
|
||||||
void draw_rotated90(const char*, int x, int y, int w, int h, Fl_Align);
|
|
||||||
void draw_rotated270(const char*, int x, int y, int w, int h, Fl_Align);
|
|
||||||
void draw_rotated180(const char*, int x, int y, int w, int h, Fl_Align);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
117
rotated_test.C
117
rotated_test.C
@ -1,117 +0,0 @@
|
|||||||
// Test the xvertext routines for rotated text
|
|
||||||
|
|
||||||
#include <FL/Fl.H>
|
|
||||||
#include <FL/Fl_Double_Window.H>
|
|
||||||
#include <FL/Fl_Box.H>
|
|
||||||
#include <FL/Fl_Hor_Value_Slider.H>
|
|
||||||
#include <FL/Fl_Toggle_Button.H>
|
|
||||||
#include <FL/Fl_Input.H>
|
|
||||||
#include <FL/Fl_Choice.H>
|
|
||||||
#include <FL/fl_draw.H>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "Rotated.H"
|
|
||||||
|
|
||||||
class RotText : public Fl_Box {
|
|
||||||
void draw();
|
|
||||||
public:
|
|
||||||
RotText(int X, int Y, int W, int H, const char* L = 0) :
|
|
||||||
Fl_Box(X,Y,W,H,L) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
void RotText::draw() {
|
|
||||||
draw_box();
|
|
||||||
fl_color(FL_BLACK);
|
|
||||||
fl_font(labelfont(), labelsize());
|
|
||||||
draw_rotated90(label(), x(), y(), w(), h(), align());
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb;
|
|
||||||
RotText *text;
|
|
||||||
Fl_Input *input;
|
|
||||||
Fl_Hor_Value_Slider *fonts;
|
|
||||||
Fl_Hor_Value_Slider *sizes;
|
|
||||||
Fl_Double_Window *window;
|
|
||||||
|
|
||||||
void button_cb(Fl_Widget *,void *) {
|
|
||||||
int i = 0;
|
|
||||||
if (leftb->value()) i |= FL_ALIGN_LEFT;
|
|
||||||
if (rightb->value()) i |= FL_ALIGN_RIGHT;
|
|
||||||
if (topb->value()) i |= FL_ALIGN_TOP;
|
|
||||||
if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
|
|
||||||
if (insideb->value()) i |= FL_ALIGN_INSIDE;
|
|
||||||
if (clipb->value()) i |= FL_ALIGN_CLIP;
|
|
||||||
if (wrapb->value()) i |= FL_ALIGN_WRAP;
|
|
||||||
text->align(i);
|
|
||||||
window->redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void font_cb(Fl_Widget *,void *) {
|
|
||||||
text->labelfont(int(fonts->value()));
|
|
||||||
window->redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void size_cb(Fl_Widget *,void *) {
|
|
||||||
text->labelsize(int(sizes->value()));
|
|
||||||
window->redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void input_cb(Fl_Widget *,void *) {
|
|
||||||
text->label(input->value());
|
|
||||||
window->redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
window = new Fl_Double_Window(400,400);
|
|
||||||
|
|
||||||
input = new Fl_Input(50,0,350,25);
|
|
||||||
input->static_value("The quick brown fox jumped over the lazy dog.");
|
|
||||||
input->when(FL_WHEN_CHANGED);
|
|
||||||
input->callback(input_cb);
|
|
||||||
|
|
||||||
sizes= new Fl_Hor_Value_Slider(50,25,350,25,"Size:");
|
|
||||||
sizes->align(FL_ALIGN_LEFT);
|
|
||||||
sizes->bounds(1,64);
|
|
||||||
sizes->step(1);
|
|
||||||
sizes->value(14);
|
|
||||||
sizes->callback(size_cb);
|
|
||||||
|
|
||||||
fonts=new Fl_Hor_Value_Slider(50,50,350,25,"Font:");
|
|
||||||
fonts->align(FL_ALIGN_LEFT);
|
|
||||||
fonts->bounds(0,15);
|
|
||||||
fonts->step(1);
|
|
||||||
fonts->value(0);
|
|
||||||
fonts->callback(font_cb);
|
|
||||||
|
|
||||||
Fl_Group *g = new Fl_Group(50,75,400,25);
|
|
||||||
leftb = new Fl_Toggle_Button(50,75,50,25,"left");
|
|
||||||
leftb->callback(button_cb);
|
|
||||||
rightb = new Fl_Toggle_Button(100,75,50,25,"right");
|
|
||||||
rightb->callback(button_cb);
|
|
||||||
topb = new Fl_Toggle_Button(150,75,50,25,"top");
|
|
||||||
topb->callback(button_cb);
|
|
||||||
bottomb = new Fl_Toggle_Button(200,75,50,25,"bottom");
|
|
||||||
bottomb->callback(button_cb);
|
|
||||||
insideb = new Fl_Toggle_Button(250,75,50,25,"inside");
|
|
||||||
insideb->callback(button_cb);
|
|
||||||
wrapb = new Fl_Toggle_Button(300,75,50,25,"wrap");
|
|
||||||
wrapb->callback(button_cb);
|
|
||||||
clipb = new Fl_Toggle_Button(350,75,50,25,"clip");
|
|
||||||
clipb->callback(button_cb);
|
|
||||||
g->resizable(insideb);
|
|
||||||
g->end();
|
|
||||||
|
|
||||||
text= new RotText(100,225,200,100,input->value());
|
|
||||||
text->box(FL_FRAME_BOX);
|
|
||||||
text->align(FL_ALIGN_CENTER);
|
|
||||||
window->resizable(text);
|
|
||||||
window->show(argc,argv);
|
|
||||||
return Fl::run();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// End of "$Id$".
|
|
||||||
//
|
|
||||||
Reference in New Issue
Block a user