📄 xftacs.c
字号:
/*-----------------------------------*-C-*-------------------------------------* * File : xftacs.c * Created : Tue 27 Dec 2005 09:59:55 PM CST * Modified : Wed 12 Apr 2006 01:33:43 AM CDT * Author : Gautam Iyer <gi1242@users.sourceforge.net> *-----------------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * * Copyright 2005-2006 Gautam Iyer <gi1242@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 675 Mass * Ave, Cambridge, MA 02139, USA. *-----------------------------------------------------------------------------* * * DESCRIPTION * * Functions to draw VT100 / ACS graphics charecters. Xft functions do not * draw text graphic charecters (like XDrawText), so we have to do it * ourself. Partly plagurized with thanks from Thomas Dicky's xterm-204: * * http://invisible-island.net/xterm/xterm.html * * This file has nothing specific to rxvt. Instead of using XftDrawString, * use xftDrawACSString. Draws the non-graphics chars using a regular Xft * function, and graphics chars using XftGlyphs (if available) or line * segments. * * Before your first call to xftDrawACSString, call xftInitACS(). After * your last call to xftDrawACSString, call xftCloseACS(). * * See the comments before each function definition for details. * * BUGS * * 1. Complex chars are drawn using a glyph from the Xft font. Not all * fonts have these glyphs. Some have them in a different location than * we expect. * * The fonts "Andale Mono", "Bitstream Vera Sans Mono" and "Courier New" * HAVE the required glyphs at the positions below. The fonts "Courier", * "Luxi Mono" and "Nimbus Mono L" DO NOT have the required glyphs. * *----------------------------------------------------------------------------*/#include "../config.h"#include "rxvt.h"#include <xftacs.h>/* * Maximum number of glyphs to be drawn per call to XftDrawGlyphs. */#define MAX_GLYPHS (32)/* * Global variables that need to be inited on startup. */GC acsGc=0; /* GC used for all drawing requests */Pixmap sPmap=0; /* Stippled pixmap used for tiling *//* * The grid is arbitrary, enough resolution that nothing's lost in * initialization. */#define BOX_HIGH 60#define BOX_WIDE 60#define MID_HIGH (BOX_HIGH/2)#define MID_WIDE (BOX_WIDE/2)#define CHR_WIDE ((9*BOX_WIDE)/10)#define CHR_HIGH ((9*BOX_HIGH)/10)/* * ...since we'll scale the values anyway. */#define SCALE_X(n) n = (n * (font_width-1)) / (BOX_WIDE-1)#define SCALE_Y(n) n = (n * (font_height-1)) / (BOX_HIGH-1)#define SEG(x0,y0,x1,y1) x0,y0, x1,y1/* * XError handler for xftInitACS. This only sets sPmap to 0, and complains. */intacsXErrorHandler( __attribute__((unused)) Display *dpy, __attribute__((unused)) XErrorEvent *event){ sPmap = 0; rxvt_dbgmsg ((DBG_VERBOSE, DBG_XFTACS, "Could not create pixmap\n")); return 0;}/* * Initialize sPmap. Call this before calling xftDrawACSString(). If d or depth * are 0, then default values are used. * * You will probabaly get a BadMatch error if you try using xftDrawACSString on * a drawable of a different depth. */voidxftInitACS( Display *dpy, Drawable d, unsigned depth){ int (*oldXerrorHandler)( Display *, XErrorEvent *); rxvt_dbgmsg ((DBG_DEBUG, DBG_XFTACS, "Initing sPmap\n")); if(d == 0) d = DefaultRootWindow( dpy); if(depth == 0) depth=DefaultDepth( dpy, DefaultScreen( dpy));#ifdef DEBUG if( sPmap != 0) rxvt_dbgmsg ((DBG_DEBUG, DBG_XFTACS, "sPmap not null in xftInitACS"));#endif acsGc = XCreateGC( dpy, d, 0, NULL); oldXerrorHandler = XSetErrorHandler( (XErrorHandler) acsXErrorHandler); sPmap = XCreatePixmap( dpy, d, 2, 2, depth); XSetErrorHandler( oldXerrorHandler); XSetTile( dpy, acsGc, sPmap);}/* * Free sPmap. Call this after your last call to xftDrawACSString, or you WILL * have a memory leak. */voidxftCloseACS( Display *dpy){ if( sPmap ) { rxvt_dbgmsg ((DBG_DEBUG, DBG_XFTACS, "freeing sPmap\n")); XFreePixmap( dpy, sPmap); sPmap = 0; }#ifdef DEBUG else rxvt_dbgmsg ((DBG_DEBUG, DBG_XFTACS, "sPmap already null in xftCloseACS"));#endif XFreeGC( dpy, acsGc);}/* * INTERNAL USE ONLY. Draw a ACS graphics character on screen at x,y. Like XFT * functions, we do not clear the background before drawing. * * (x,y) is the bottom left corner of the character to draw. * * WARNING: If any char in *str has ascii value >= 32, then this function will * get stuck in an infinite loop. */voidxftDrawACSChars( Display *dpy, Drawable d, GC gc, XftDraw *draw, const XftColor *color, XftFont *pub, int x, int y, const unsigned char *str, int len){ /* * Line segments to draw line like chars. */ static const short glyph_ht[] = { SEG( 0, 0, 0, 5*MID_HIGH/6), /* H */ SEG(6*BOX_WIDE/10, 0, 6*BOX_WIDE/10,5*MID_HIGH/6), SEG( 0, 5*MID_HIGH/12,6*BOX_WIDE/10,5*MID_HIGH/12), SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), -1 }, glyph_ff[] = { SEG( 0, 0, 6*BOX_WIDE/10, 0), /* F */ SEG( 0, 5*MID_HIGH/12,6*CHR_WIDE/12,5*MID_HIGH/12), SEG( 0, 0, 0*BOX_WIDE/3, 5*MID_HIGH/6), SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), -1 }, glyph_lf[] = { SEG( 0, 0, 0, 5*MID_HIGH/6), /* L */ SEG( 0, 5*MID_HIGH/6, 6*BOX_WIDE/10,5*MID_HIGH/6), SEG(1*BOX_WIDE/3, MID_HIGH, CHR_WIDE, MID_HIGH), /* F */ SEG(1*BOX_WIDE/3, 8*MID_HIGH/6,10*CHR_WIDE/12,8*MID_HIGH/6), SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), -1 }, glyph_nl[] = { SEG( 0, 5*MID_HIGH/6, 0, 0), /* N */ SEG( 0, 0, 5*BOX_WIDE/6, 5*MID_HIGH/6), SEG(5*BOX_WIDE/6, 5*MID_HIGH/6, 5*BOX_WIDE/6, 0), SEG(1*BOX_WIDE/3, MID_HIGH, 1*BOX_WIDE/3, CHR_HIGH), /* L */ SEG(1*BOX_WIDE/3, CHR_HIGH, CHR_WIDE, CHR_HIGH), -1 }, glyph_vt[] = { SEG( 0, 0, 5*BOX_WIDE/12,5*MID_HIGH/6), /* V */ SEG(5*BOX_WIDE/12,5*MID_HIGH/6, 5*BOX_WIDE/6, 0), SEG(2*BOX_WIDE/10, MID_HIGH, CHR_WIDE, MID_HIGH), /* T */ SEG(6*BOX_WIDE/10, MID_HIGH, 6*BOX_WIDE/10, CHR_HIGH), -1 }, lower_right_corner[] = { SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), SEG( MID_WIDE, MID_HIGH, MID_WIDE, 0), -1 }, upper_right_corner[] = { SEG( 0, MID_HIGH, MID_WIDE, MID_HIGH), SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), -1 }, upper_left_corner[] = { SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), -1 }, lower_left_corner[] = { SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), SEG( MID_WIDE, MID_WIDE, BOX_WIDE, MID_HIGH), -1 }, cross[] = { SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), -1 }, left_tee[] = { SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), SEG( MID_WIDE, MID_HIGH, BOX_WIDE, MID_HIGH), -1 }, right_tee[] = { SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), SEG( MID_WIDE, MID_HIGH, 0, MID_HIGH), -1 }, bottom_tee[] = { SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), SEG( MID_WIDE, 0, MID_WIDE, MID_HIGH), -1 }, top_tee[] = { SEG( 0, MID_HIGH, BOX_WIDE, MID_HIGH), SEG( MID_WIDE, MID_HIGH, MID_WIDE, BOX_HIGH), -1 }, vertical_line[] = { SEG( MID_WIDE, 0, MID_WIDE, BOX_HIGH), -1 }; /* * Pointer to line-segment structure. */ static const short *lines[] = { NULL, /* 00 (unused) */ NULL, /* 01 diamond */ NULL, /* 02 box */ glyph_ht, /* 03 HT */ glyph_ff, /* 04 FF */ NULL, /* 05 CR (not drawn) */ glyph_lf, /* 06 LF */ NULL, /* 07 degrees (small circle) */ NULL, /* 08 plus or minus*/ glyph_nl, /* 09 */ glyph_vt, /* 0A */ lower_right_corner, /* 0B */ upper_right_corner, /* 0C */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -