📄 aafont.c
字号:
/* aafont.c - generic library for drawing anti-aliased fonts Copyright (C) 1996-2000 Paul Sheer 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include <stdlib.h>#include <stdio.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include "aafont.h"#include "mad.h"/* * list management * --------------- * * Situation is a list of aa fonts: * Each font is uniquified by a fg colour, a bg colour and a fontid. * Each font has 65536 pixmap glyphs. * The 65536 pixmaps are divided into 256 blocks. * Each block is allocated on demand only. * We *ImageString* only i.e. no DrawString - since requires knowledge * of the background which is complicated. */Display *aa_display;int aa_depth;Window aa_root;Visual *aa_visual;int option_rgb_order = RedFirst;int option_interchar_spacing = 0;void XAaInit (Display * display, Visual * visual, int depth, Window root){ aa_display = display; aa_depth = depth; aa_root = root; aa_visual = visual;}struct aa_glyph_cache { Pixmap pixmap; int width;};struct aa_font_cache { XFontStruct *font_struct; GC gc; unsigned long fg; unsigned long bg; struct aa_glyph_cache *glyph[256]; int num_pixmaps; struct aa_font_cache *next;} *font_cache_list = 0;static void aa_insert (void){ struct aa_font_cache *p; p = malloc (sizeof (*font_cache_list)); memset (p, 0, sizeof (*font_cache_list)); if (!font_cache_list) { font_cache_list = p; } else { p->next = font_cache_list; font_cache_list = p; }}static void aa_free (struct aa_font_cache *f){ int i, j; XFreeFontInfo (0, f->font_struct, 0); for (i = 0; i < 256; i++) { if (f->glyph[i]) { for (j = 0; j < 256; j++) if (f->glyph[i][j].pixmap) XFreePixmap (aa_display, f->glyph[i][j].pixmap); memset (f->glyph[i], 0, 256 * sizeof (struct aa_glyph_cache)); free (f->glyph[i]); } } memset (f, 0, sizeof (*f)); free (f);}/* passing fg == bg == 0 finds any fid */static struct aa_font_cache *aa_find (Font fid, unsigned long fg, unsigned long bg){ struct aa_font_cache *p; for (p = font_cache_list; p; p = p->next) if (fid && p->font_struct->fid == fid && p->fg == fg && p->bg == bg) return p; return 0;}/* returns zero on not found */static int _aa_remove (Font fid){ struct aa_font_cache *p, *q = 0; for (p = font_cache_list; p; p = p->next) { if (fid && p->font_struct->fid == fid) { if (p == font_cache_list) { struct aa_font_cache *t; t = font_cache_list->next; aa_free (font_cache_list); font_cache_list = t; return 1; } else { q->next = p->next; aa_free (p); return 1; } } q = p; } return 0;}static void aa_remove (Font fid){ while (_aa_remove (fid));}/* fifth level *//* 5 by 9/3 guassian convolution */static unsigned long aa_convolve (int i, int j, unsigned char *source, int source_bytes_per_line, int byte_order, int bytes_per_pixel, int rgb_order, int red_shift, int green_shift, int blue_shift, int red_mask, int green_mask, int blue_mask){ unsigned long red, green, blue;#include "conv.c" red /= (256 * 3); green /= (256 * 3); blue /= (256 * 3); return (red << red_shift) | (green << green_shift) | (blue << blue_shift);}/* fourth level */static Pixmap aa_shrink_pixmap (struct aa_font_cache *f, Pixmap pixmap, int width, int height, int *width_return){ XImage *image, *shrunk; int i, j, w, h, bytes_per_pixel; int red_shift, green_shift, blue_shift; unsigned long red_mask, green_mask, blue_mask;/* create an image to put the enlarged glyph into - make it slightly large to hold the diameter of the 5x9 guassian as well as a one pixel enlargement and rounding error */ image = XCreateImage (aa_display, aa_visual, aa_depth, ZPixmap, 0, 0, width + 4 + X_ENLARGEMENT + option_interchar_spacing * 3, height + 8 + Y_ENLARGEMENT, 8, 0); bytes_per_pixel = image->bytes_per_line / image->width; image->data = (char *) malloc (image->bytes_per_line * image->height); for (i = 0; i < width + 4 + X_ENLARGEMENT + option_interchar_spacing; i++) XPutPixel (image, i, 0, f->bg); for (j = 0; j < height + 8 + Y_ENLARGEMENT; j++) memcpy (image->data + image->bytes_per_line * j, image->data, image->bytes_per_line);/* create an image to put the reduced glyph into. round w and h up */ *width_return = w = SHRINK_WIDTH (width); h = SHRINK_HEIGHT (height); shrunk = XCreateImage (aa_display, aa_visual, aa_depth, ZPixmap, 0, 0, w, h, 8, 0); shrunk->data = (char *) malloc (shrunk->bytes_per_line * h); for (red_mask = image->red_mask, red_shift = 0; red_shift < 32 && !(red_mask & 1); red_shift++, red_mask >>= 1); for (green_mask = image->green_mask, green_shift = 0; green_shift < 32 && !(green_mask & 1); green_shift++, green_mask >>= 1); for (blue_mask = image->blue_mask, blue_shift = 0; blue_shift < 32 && !(blue_mask & 1); blue_shift++, blue_mask >>= 1); XGetSubImage (aa_display, pixmap, 0, 0, width, height, image->red_mask | image->green_mask | image->blue_mask, ZPixmap, image, 2, 4); for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { unsigned long pixel; pixel = aa_convolve (i * 3, j * 3, (unsigned char *) image->data + bytes_per_pixel * 2 + image->bytes_per_line * 4, image->bytes_per_line, image->byte_order, bytes_per_pixel, option_rgb_order, red_shift, green_shift, blue_shift, red_mask, green_mask, blue_mask); XPutPixel (shrunk, i, j, pixel); } } pixmap = XCreatePixmap (aa_display, aa_root, w, h, aa_depth); XPutImage (aa_display, pixmap, f->gc, shrunk, 0, 0, 0, 0, w, h); free (image->data); image->data = 0; XDestroyImage (image); free (shrunk->data); shrunk->data = 0; XDestroyImage (shrunk); return pixmap;}/* third level */static Pixmap aa_create_pixmap (struct aa_font_cache *f, int j, int i, int *width){ Pixmap w, r; int direction, ascent, descent, height; XCharStruct ch; XChar2b c; c.byte1 = j; c.byte2 = i; XTextExtents16 (f->font_struct, &c, 1, &direction, &ascent, &descent, &ch); height = f->font_struct->ascent + f->font_struct->descent; w = XCreatePixmap (aa_display, aa_root, ch.width, height, aa_depth);/* cheapest way to clear the background */ XDrawImageString (aa_display, w, f->gc, 0, f->font_struct->ascent, " ", 5);/* needed to clear the background if the function fails on non-existing chars */ XDrawImageString16 (aa_display, w, f->gc, 0, f->font_struct->ascent, &c, 1); r = aa_shrink_pixmap (f, w, ch.width, height, width); XFreePixmap (aa_display, w); return r;}/* second level */static void aa_create_pixmap_ (struct aa_font_cache *f, int j, int i){ if (!f->glyph[j]) { f->glyph[j] = malloc (sizeof (struct aa_glyph_cache) * 256); memset (f->glyph[j], 0, sizeof (struct aa_glyph_cache) * 256); } if (!f->glyph[j][i].pixmap) f->glyph[j][i].pixmap = aa_create_pixmap (f, j, i, &f->glyph[j][i].width);}/* top level */static void aa_create_pixmaps (struct aa_font_cache *f, XChar2b * wc, unsigned char *c, int n){ int i; if (aa_visual->class != TrueColor) { fprintf (stderr, "%s:%d: Can't do anti-aliasing without TrueColor visual.\nTry setting your X server to non-8-bits-per-pixel display.\n", __FILE__, __LINE__); exit (1); } if (wc) { for (i = 0; i < n; i++) aa_create_pixmap_ (f, wc[i].byte1, wc[i].byte2); } else { for (i = 0; i < n; i++) aa_create_pixmap_ (f, 0, c[i]); }}int _XAaDrawImageStringWC (Display * display, Drawable d, GC gc, int x, int y, char *s, XChar2b * wc, int length){ int i, x_start = x; struct aa_font_cache *f; XGCValues values_return; XGetGCValues (display, gc, GCForeground | GCBackground | GCFont, &values_return); f = aa_find (values_return.font, values_return.foreground, values_return.background); if (!f) { aa_insert (); f = font_cache_list; f->font_struct = XQueryFont (display, values_return.font); f->gc = gc; f->fg = values_return.foreground; f->bg = values_return.background; aa_display = display; } aa_create_pixmaps (f, wc, (unsigned char *) s, length); if (wc) { for (i = 0; i < length; i++) { int width = f->glyph[wc[i].byte1][wc[i].byte2].width; int height = SHRINK_HEIGHT (f->font_struct->ascent + f->font_struct->descent); XCopyArea (display, f->glyph[wc[i].byte1][wc[i].byte2].pixmap, d, gc, 0, 0, width, height, x, y - f->font_struct->ascent / 3); x += width; } } else { for (i = 0; i < length; i++) { int width = f->glyph[0][(unsigned char) s[i]].width; int height = SHRINK_HEIGHT (f->font_struct->ascent + f->font_struct->descent); XCopyArea (display, f->glyph[0][(unsigned char) s[i]].pixmap, d, gc, 0, 0, width, height, x, y - f->font_struct->ascent / 3); x += width; } } return x - x_start;}int XAaTextWidth (XFontStruct * font_struct, char *s, int length){ int w = 0, i; int direction, ascent, descent; for (i = 0; i < length; i++) { XCharStruct ch; XTextExtents (font_struct, s + i, 1, &direction, &ascent, &descent, &ch); w += SHRINK_WIDTH (ch.width); } return w;}int XAaTextWidth16 (XFontStruct * font_struct, XChar2b * s, int length){ int w = 0, i; int direction, ascent, descent; for (i = 0; i < length; i++) { XCharStruct ch; XTextExtents16 (font_struct, s + i, 1, &direction, &ascent, &descent, &ch); w += SHRINK_WIDTH (ch.width); } return w;}int XAaDrawImageString16 (Display * display, Drawable d, GC gc, int x, int y, XChar2b * wc, int length){ return _XAaDrawImageStringWC (display, d, gc, x, y, 0, wc, length);}int XAaDrawImageString (Display * display, Drawable d, GC gc, int x, int y, char *s, int length){ return _XAaDrawImageStringWC (display, d, gc, x, y, s, 0, length);}void XAaFree (Font fid){ aa_remove (fid);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -