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