From a1d1742f2dbec6c31a16f6c5d82411898fa1a59f Mon Sep 17 00:00:00 2001 From: fluxgen <fluxgen> Date: Sun, 6 Jan 2002 11:00:13 +0000 Subject: added DrawUtil.cc/.hh --- src/DrawUtil.cc | 462 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DrawUtil.hh | 92 +++++++++++ 2 files changed, 554 insertions(+) create mode 100644 src/DrawUtil.cc create mode 100644 src/DrawUtil.hh diff --git a/src/DrawUtil.cc b/src/DrawUtil.cc new file mode 100644 index 0000000..c9527de --- /dev/null +++ b/src/DrawUtil.cc @@ -0,0 +1,462 @@ +// DrawUtil.cc for fluxbox +// Copyright (c) 2001 Henrik Kinnunen (fluxgen@linuxmail.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif //HAVE_CONFIG_H + +#include "DrawUtil.hh" +#include "StringUtil.hh" +#include "i18n.hh" + +#include <iostream> +#include <X11/Xutil.h> + +using namespace std; + +// ---------------------------------------------------------------------- +// xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) +// ---------------------------------------------------------------------- + +//------- XRotLoadFont ------------------- +// Load the rotated version of a given font +//---------------------------------------- +DrawUtil::XRotFontStruct *DrawUtil::XRotLoadFont(Display *dpy, char *fontname, float angle) { + char val; + XImage *I1, *I2; + Pixmap canvas; + Window root; + int screen; + GC font_gc; + char text[3];/*, errstr[300];*/ + XFontStruct *fontstruct; + XRotFontStruct *rotfont; + int ichar, i, j, index, boxlen = 60, dir; + 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; + + /* make angle positive ... */ + if (angle < 0) do angle += 360; while (angle < 0); + + /* get nearest vertical or horizontal direction ... */ + dir = (int)((angle+45.)/90.)%4; + + /* 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); + + /* load the font ... */ + fontstruct = XLoadQueryFont(dpy, fontname); + if (fontstruct == NULL) { + cerr<<"Fluxbox::DrawUtil: No font"<<endl; + return 0; + } + + XSetFont(dpy, font_gc, fontstruct->fid); + + /* allocate space for rotated font ... */ + rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct)); + + if (rotfont == 0) { + cerr<<"Fluxbox::DrawUtil: out of memory"<<endl; + return 0; + } + + /* determine which characters are defined in font ... */ + min_char = fontstruct->min_char_or_byte2; + max_char = fontstruct->max_char_or_byte2; + + /* we only want printing characters ... */ + if (min_char<32) min_char = 32; + if (max_char>126) max_char = 126; + + /* some overall font data ... */ + rotfont->name = StringUtil::strdup(fontname); + rotfont->dir = dir; + rotfont->min_char = min_char; + rotfont->max_char = max_char; + rotfont->max_ascent = fontstruct->max_bounds.ascent; + rotfont->max_descent = fontstruct->max_bounds.descent; + rotfont->height = rotfont->max_ascent+rotfont->max_descent; + + /* remember xfontstruct for `normal' text ... */ + if (dir == 0) + rotfont->xfontstruct = fontstruct; + else { + /* font needs rotation ... */ + /* loop through each character ... */ + for (ichar = min_char; ichar <= max_char; ichar++) { + index = ichar-fontstruct->min_char_or_byte2; + + /* per char dimensions ... */ + ascent = rotfont->per_char[ichar-32].ascent = + fontstruct->per_char[index].ascent; + descent = rotfont->per_char[ichar-32].descent = + fontstruct->per_char[index].descent; + lbearing = rotfont->per_char[ichar-32].lbearing = + fontstruct->per_char[index].lbearing; + rbearing = rotfont->per_char[ichar-32].rbearing = + fontstruct->per_char[index].rbearing; + rotfont->per_char[ichar-32].width = + fontstruct->per_char[index].width; + + /* some space chars have zero body, but a bitmap can't have ... */ + if (!ascent && !descent) + ascent = rotfont->per_char[ichar-32].ascent = 1; + if (!lbearing && !rbearing) + rbearing = rotfont->per_char[ichar-32].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) { + cerr<<"Fluxbox::DrawUtil: Cant create ximage."<<endl; + return NULL; + } + + 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-32].glyph.bit_w = bit_w; + rotfont->per_char[ichar-32].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) { + cerr<<"Font::DrawUtil: Cant create ximage!"<<endl; + return 0; + } + + 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-32].glyph.bm = + XCreatePixmap(dpy, root, bit_w, bit_h, 1); + + /* put the image into the bitmap ... */ + XPutImage(dpy, rotfont->per_char[ichar-32].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);*/ + } + XFreeFont(dpy, fontstruct); + } + + /* free pixmap and GC ... */ + XFreePixmap(dpy, canvas); + XFreeGC(dpy, font_gc); + + return rotfont; +} + +//------- XRotUnloadFont ----------------- +// Free the resources associated with a +// rotated font +//---------------------------------------- +void DrawUtil::XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont) +{ + int ichar; + + if (rotfont->dir == 0) + XFreeFont(dpy, rotfont->xfontstruct); + else { + /* loop through each character, freeing its pixmap ... */ + for (ichar = rotfont->min_char-32; ichar <= rotfont->max_char-32; + ichar++) + XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm); + } + + free((char *)rotfont->name); + free((char *)rotfont); +} + +//------- XRotTextWidth ------------------ +// Returns the width of a rotated string +//---------------------------------------- +unsigned int DrawUtil::XRotTextWidth(XRotFontStruct *rotfont, 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++) { + ichar = str[i]-32; + + /* make sure it's a printing character ... */ + if (ichar >= 0 && ichar<95) + width += rotfont->per_char[ichar].width; + } + } + return width; +} + + +//------- XRotDrawString ----------------- +// A front end to XRotDrawString : mimics XDrawString +//---------------------------------------- +void DrawUtil::XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable, + GC gc, int x, int y, char *str, int len) +{ + static GC my_gc = 0; + int i, xp, yp, dir, ichar; + + if (str == NULL || len<1) + return; + + dir = rotfont->dir; + if (my_gc == 0) + my_gc = XCreateGC(dpy, drawable, 0, 0); + + XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc); + + /* a horizontal string is easy ... */ + if (dir == 0) { + XSetFillStyle(dpy, my_gc, FillSolid); + XSetFont(dpy, my_gc, rotfont->xfontstruct->fid); + XDrawString(dpy, drawable, my_gc, x, y, str, len); + return; + } + + /* vertical or upside down ... */ + + XSetFillStyle(dpy, my_gc, FillStippled); + + /* loop through each character in string ... */ + for (i = 0; i<len; i++) { + ichar = str[i]-32; + + /* make sure it's a printing character ... */ + if (ichar >= 0 && ichar<95) { + /* 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, my_gc, rotfont->per_char[ichar].glyph.bm); + + XSetTSOrigin(dpy, my_gc, xp, yp); + + XFillRectangle(dpy, drawable, my_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; + } + } +} + + +//Draw title string +void DrawUtil::DrawString(Display *display, Window w, GC gc, DrawUtil::Font *font, + unsigned int text_w, unsigned int size_w, + unsigned int bevel_w, char *text) { + + assert(display); + assert(font); + + if (!text || text_w<1 || size_w < 1) + return; + + unsigned int l = text_w; + int dlen=strlen(text); + int dx=bevel_w*2; + + + if (text_w > size_w) { + for (; dlen >= 0; dlen--) { + if (I18n::instance()->multibyte()) { + XRectangle ink, logical; + XmbTextExtents(font->set, text, dlen, + &ink, &logical); + l = logical.width; + } else + l = XTextWidth(font->fontstruct, text, dlen); + + l += (dx * 4); + + if (l < size_w) + break; + } + } + + switch (font->justify) { + case DrawUtil::Font::RIGHT: + dx += size_w - l; + break; + + case DrawUtil::Font::CENTER: + dx += (size_w - l) / 2; + break; + default: + break; + } + + //Draw title to m_tabwin + + XClearWindow(display, w); + + if (I18n::instance()->multibyte()) { + XmbDrawString(display, w, + font->set, gc, dx, 1 - font->set_extents->max_ink_extent.y, + text, dlen); + } else { + XDrawString(display, w, + gc, dx, font->fontstruct->ascent + 1, + text, dlen); + } + +} + + +void DrawUtil::DrawRotString(Display *display, Window w, GC gc, XRotFontStruct *font, + unsigned int align, unsigned int text_w, + unsigned int size_w, unsigned int size_h, + unsigned int bevel_w, char *text) { + + assert(display); + assert(font); + + if (!text || text_w<1 || size_w < 1) + return; + + unsigned int l = text_w; + int dlen = strlen(text); + int dx = bevel_w * 2; + + if (text_w > size_w) { + for (; dlen >= 0; dlen--) { + l = XRotTextWidth(font, text, dlen); + + l += (dx * 4); + + if (l < size_h) + break; + } + } + + if (align == DrawUtil::Font::RIGHT) + size_h = l; + else if (align == DrawUtil::Font::CENTER) + size_h = (size_h + l) / 2; + else //LEFT + size_h -= (dx * 4); + + // To get it in the "center" of the tab + size_w = (size_w + XRotTextWidth(font, "/", 1)) / 2; + + //Draw title to m_tabwin + XClearWindow(display, w); + XRotDrawString(display, font, w, gc, size_w, size_h, text, dlen); +} diff --git a/src/DrawUtil.hh b/src/DrawUtil.hh new file mode 100644 index 0000000..d1ef415 --- /dev/null +++ b/src/DrawUtil.hh @@ -0,0 +1,92 @@ +// DrawUtil.hh for fluxbox +// Copyright (c) 2001 Henrik Kinnunen (fluxgen@linuxmail.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +#ifndef _DRAWUTIL_HH_ +#define _DRAWUTIL_HH_ + +#include <X11/Xlib.h> + +struct DrawUtil +{ + struct Font + { + enum FontJustify {LEFT=0, RIGHT, CENTER}; + + XFontSet set; + XFontSetExtents *set_extents; + XFontStruct *fontstruct; + FontJustify justify; + }; + +static void DrawString(Display *display, Window w, GC gc, DrawUtil::Font *font, + unsigned int text_w, unsigned int size_w, + unsigned int bevel_w, char *text); + +// ---------------------------------------------------------------------- +// xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) +// ---------------------------------------------------------------------- + + /* *** The font structures *** */ + + 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; + char *name; + + XFontStruct *xfontstruct; + + DrawUtil::XRotCharStruct per_char[95]; + }; +static unsigned int XRotTextWidth(DrawUtil::XRotFontStruct *rotfont, char *str, int len); +static void XRotDrawString(Display *dpy, DrawUtil::XRotFontStruct *rotfont, Drawable drawable, + GC gc, int x, int y, char *str, int len); + +static void DrawRotString(Display *display, Window w, GC gc, DrawUtil::XRotFontStruct *font, + unsigned int align, unsigned int text_w, + unsigned int size_w, unsigned int size_h, + unsigned int bevel_w, char *text); + +static DrawUtil::XRotFontStruct *XRotLoadFont(Display *dpy, char *fontname, float angle); +static void XRotUnloadFont(Display *dpy, DrawUtil::XRotFontStruct *rotfont); + +}; + +#endif //_DRAWUTIL_HH_ -- cgit v0.11.2