⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ft2string.c

📁 《Linux程序设计权威指南》源代码
💻 C
字号:
// ft2string.c//      本程序利用 FreeType 2 函数库把一串文本用 TrueType 字库显示在//      一个 X 窗口里。//// 标准头文件#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <locale.h>// X11 头文件#include <X11/Xlib.h>#include <X11/Xutil.h>// FreeType 2 头文件#include <freetype/freetype.h>// X 窗口的宽度和高度#define WINDOW_WIDTH 600#define WINDOW_HEIGHT 400// 最多只显示 256 个字符#define MAX_GLYPHS 256Display *display;Window win;			// 窗口IDGC gc;				// 图形环境XVisualInfo vis;		// Visual 信息XColor rgb[256];// 定义将用于 X 窗口显示的字形图象结构typedef struct{  XImage *img;			// 字形的 X 图象  int left;			// 字形图象的左边轴距  int top;			// 字形图象的顶边轴距  int advance_x;		// 字形的水平步幅  int advance_y;		// 字形的垂直步幅}Glyph_Image;Glyph_Image gi[MAX_GLYPHS];	// 最多 MAX_GLYPHS 个字形 X 图象FT_Library library;		// FreeType 库FT_Face face;			// 字体对象FT_Error error;			// FreeType 错误代码char *prog;			// 程序名unsigned char *text = "欢迎进入 Linux 的奇妙世界!";					// 将显示的文本,缺省文本如上wchar_t unicode_text[MAX_GLYPHS];	// 文本的 Unicode 编码int num_glyphs;			// 字形数目int pixel_size = 50;		// 显示字体象素大小,缺省为 50int resolution = 72;		// 分辨率,缺省为 72int grayscale = 0;		// 是否使用灰度显示,缺省为不使用灰度显示char *font_filename = NULL;	// 字库文件名,用户必须提供void parse_args ();		// 处理命令行参数void text_to_unicode ();	// 把文本转换为 Unicode 编码void init_display ();		// 初始化 X 窗口void render_glyph ();		// 生成字形图象的位图(单色图或灰度图)void render_image ();		// 生成字形的 X 图象(XImage)void draw_image ();		// 在 X 窗口里画出文本图象void event_loop ();		// X 事件循环void usage ();			// 使用说明void fatal_error (const char *msg, ...);	// FreeType 函数返回致命错误intmain (int argc, char **argv){  int i;  // 处理命令行参数,获取下列信息  //    字库文件名  //    显示字体象素大小  //    分辨率  //    是否使用灰度显示  //    将显示的文本  parse_args (argc, argv);  // 初始化一个新的 FreeType 库对象 library  error = FT_Init_FreeType (&library);  if (error)    fatal_error ("couldn't initialize FreeType library.");  // 为字库文件 font_filename 中的第一种字体创建一个新的字体对象 face  error = FT_New_Face (library, font_filename, 0, &face);  if (error == FT_Err_Unknown_File_Format)    fatal_error ("unsupported font format in file '%s'.", font_filename);  else if (error)    fatal_error ("unable to open input file '%s'.", font_filename);  // 选择字体对象 face 中的 Unicode 字符码表为缺省码表  error = FT_Select_Charmap (face, ft_encoding_unicode);  if (error)    fatal_error ("couldn't select Unicode charmap.");  // 设置字体 face 的字符宽度和高度都为 pixel_size 个象素  // 水平和垂直分辨率都为 resolution dpi  error = FT_Set_Char_Size (face,			    pixel_size * 64, pixel_size * 64,			    resolution, resolution);  if (error)    fatal_error ("couldn't set character size: pixel size %d, resolution %d.",		 pixel_size, resolution);  // 把将显示的文本转换为 Unicode 编码  text_to_unicode ();  // 初始化 X 窗口  init_display ();  // 对以 Unicode 编码的文本中所有字符进行逐一处理  for (i = 0; i < num_glyphs; i++)    {      // 生成第 i 个 Unicode 字符的字形图象的位图(单色图或灰度图)      render_glyph (unicode_text[i], grayscale);      // 生成第 i 个字形的 X 图象(XImage),并保存下列信息:      //        字形位图的左边轴距      //        字形位图的顶边轴距      //        字形的水平步幅      //        字形的垂直步幅      render_image (i, face->glyph->bitmap.buffer,		    face->glyph->bitmap.rows, face->glyph->bitmap.pitch,		    face->glyph->bitmap_left, face->glyph->bitmap_top,		    face->glyph->advance.x / 64, face->glyph->advance.y / 64,		    grayscale);    }  // 在 X 窗口中,从位置 x = 0,y = pixel_size * resolution / 72  // 开始画出文本的所有字符的图象  draw_image (0, pixel_size * resolution / 72);  // X 事件循环  event_loop ();  // 销毁字体对象 face 及它的所有子对象  FT_Done_Face (face);  // 销毁 FreeType 库对象 library 及它的所有后代  FT_Done_FreeType (library);  return 0;}// 处理命令行参数voidparse_args (int argc, char **argv){  int i;  prog = argv[0];  if (argc == 1)    usage ();  for (i = 1; i < argc; i++)    {      switch (argv[i][0])	{	case '-':	  switch (argv[i][1])	    {	    case 'p':	      if (i + 1 < argc && argv[i + 1][0] != '-')		pixel_size = strtol (argv[++i], (char **) NULL, 10);	      break;	    case 'r':	      if (i + 1 < argc && argv[i + 1][0] != '-')		resolution = strtol (argv[++i], (char **) NULL, 10);	      break;	    case 'f':	      if (i + 1 < argc && argv[i + 1][0] != '-')		font_filename = argv[++i];	      break;	    case 'g':	      grayscale = 1;	      break;	    default:	      break;	    }	  break;	default:	  text = argv[i];	  break;	}    }  if (font_filename == NULL)    {      fprintf (stderr,	       "ERROR: You must provide a TrueType font file name!\n");      exit (1);    }  if (pixel_size == 0 || pixel_size == LONG_MAX)    {      fprintf (stderr, "ERROR: Illegal pixel size: %d.\n", pixel_size);      exit (1);    }  if (resolution == 0 || resolution == LONG_MAX)    {      fprintf (stderr, "ERROR: Illegal resolution: %d.\n", resolution);      exit (1);    }  // 打印程序运行参数  printf ("font_filename: %s\n", font_filename);  printf ("pixel_size: %d\n", pixel_size);  printf ("resolution: %d\n", resolution);  printf ("grayscale: %d\n", grayscale);  printf ("text: %s\n", text);}// 利用 locale 和 mbstowcs() 函数把文本转换为 Unicode 编码voidtext_to_unicode (){  char *old_locale, *saved_locale;  int length;  int i;  // 获取当前 locale 的 LC_CTYPE 类的设定  old_locale = setlocale (LC_CTYPE, NULL);  // 保存当前 locale 的 LC_CTYPE 类的设定  saved_locale = strdup (old_locale);  // 设置 LC_CTYPE 为一种简体中文 locale  setlocale (LC_CTYPE, "zh_CN");  length = strlen (text);  if (length > 256)    length = 256;  // 把输入文本转换为 Unicode 编码  // 返回转换后的 Unicode 字符总数,即将要处理的字形总数,最多只取 256 个  num_glyphs = mbstowcs (unicode_text, text, length);  // 打印字形总数  printf ("number of glyphs: %d\n", num_glyphs);  // 打印所有字符的 Unicode 编码  printf ("unicode text:");  for (i = 0; i < num_glyphs; i++)    {      printf (" %x", (unsigned int) unicode_text[i]);    }  printf ("\n");  // 恢复对 locale 类 LC_CTYPE 的设置  setlocale (LC_CTYPE, saved_locale);  free (saved_locale);}// 生成 Unicode 编码为 charcode 的字符的字形图象和位图(单色图或灰度图)voidrender_glyph (unsigned long charcode, int gray){  int glyph_index;		// 字体中的字形索引号  // 把 Unicode 编码 charcode 转换为字体 face 中对应的字形索引号  glyph_index = FT_Get_Char_Index (face, charcode);  if (glyph_index != 0)    {      int flags;      // 定义使用缺省模式载入字形,即,内嵌位图优先于轮廓,      // 矢量总是被缩放并符合格点      flags = FT_LOAD_DEFAULT;      // 在使用灰度显示时,不载入可缩放字体的内嵌点阵字体位图,      // 而载入轮廓线字形图象      if (gray)	flags |= FT_LOAD_NO_BITMAP;      // 从字体 face 中按 flags 设定的模式载入字形索引号为 glyph_index      // 的字形图象      error = FT_Load_Glyph (face, glyph_index, flags);      if (error)	fatal_error ("couldn't load glyph.");      // 把字形图象 face->glyph 转换为灰度位图或单色位图      if (gray)	error = FT_Render_Glyph (face->glyph, ft_render_mode_normal);      else	error = FT_Render_Glyph (face->glyph, ft_render_mode_mono);      if (error)	fatal_error ("couldn't render glyph.");    }}// 生成 Unicode 编码文本中第 num 个字符位图 bit_data 的 X 图象(XImage),// 并保存下列信息://      字形位图的左边轴距 left//      字形位图的顶边轴距 top//      字形的水平步幅 advance_x//      字形的垂直步幅 advance_yvoidrender_image (int num, unsigned char *bit_data,	      int rows, int cols,	      int left, int top, int advance_x, int advance_y, int gray){  int i, j;  int img_width;		// 位图宽度  int img_size;			// 位图尺寸  unsigned char *bitmap;	// 用于 XImage 中的位图  if (gray)    img_width = cols;  else    img_width = ((cols + 1) & -2) * 8;  // 给位图 bitmap 分配内存空间  img_size = cols * rows * 2;  bitmap = (unsigned char *) malloc (img_size);  // 把位图 bitmap 初始化为全零  memset (bitmap, 0, img_size);  // 保存位图及字形相关数据  gi[num].left = left;  gi[num].top = top;  gi[num].advance_x = advance_x;  gi[num].advance_y = advance_y;  // 创建 XImage  gi[num].img = XCreateImage (display,			      vis.visual,			      gray ? vis.depth : 1,			      gray ? ZPixmap : XYBitmap,			      0, bitmap, img_width, rows, 8, 0);  // 在单色位图数据中,最左侧的象素用最高标志位(Most Significant Bit)表示  if (!gray)    {      gi[num].img->byte_order = MSBFirst;      gi[num].img->bitmap_bit_order = MSBFirst;    }  // 根据字形位图给 XImage 赋值  for (j = 0; j < rows; j++)    for (i = 0; i < cols; i++)      {	unsigned char c = bit_data[i + j * cols];	if (gray)	  gi[num].img->f.put_pixel (gi[num].img, i, j, rgb[c].pixel);	else	  bitmap[i + j * img_width / 8] = c;      }}// 在 X 窗口中,从位置 x = start_x,y = start_y 开始画出文本的所有字符的图象voiddraw_image (int start_x, int start_y){  int i;  for (i = 0; i < num_glyphs; i++)    {      // 如果将要到达窗口右边界,“另起一行”开始书写      if (start_x + gi[i].img->width >= WINDOW_WIDTH)	{	  start_x = 0;	  start_y += pixel_size * resolution / 72;	}      // 画出当前的字形图象,根据字形左边轴距和顶边轴距调整字形图象的位置      XPutImage (display, win, gc, gi[i].img, 0, 0,		 start_x + gi[i].left, start_y - gi[i].top,		 gi[i].img->width, gi[i].img->height);      // 根据当前字形的步幅调整画下一个字形图象的起始位置      start_x += gi[i].advance_x;      start_y += gi[i].advance_y;    }}// 初始化 X 窗口voidinit_display (){  int i;  int screen_num;  unsigned int win_width, win_height;	// 窗口尺寸  unsigned int border_width = 4;	// 边界空白  char *display_name = NULL;  Colormap default_cmap;	// 颜色表  XVisualInfo *vlist;		// Visual 信息  int depth;			// 窗口颜色深度  int match;			// 所符合的 Visual 结构  // 与 X 服务器连接  if ((display = XOpenDisplay (display_name)) == NULL)    {      printf ("Cannot connect to X server %s\n", XDisplayName (display_name));      exit (-1);    }  // 获得缺省的 screen_num  screen_num = DefaultScreen (display);  // 建立图形环境  gc = DefaultGC (display, screen_num);  // 获得颜色深度  depth = DefaultDepthOfScreen (DefaultScreenOfDisplay (display));  // 获取缺省的颜色表  default_cmap = DefaultColormap (display, screen_num);  // 获得Visual信息  vis.screen = screen_num;  vlist = XGetVisualInfo (display, VisualScreenMask,	// 掩码			  &vis,	// 返回visual			  &match);	// 所符合的Visual结构  if (!vlist)    {      printf ("No matched visuals\n");      exit (1);    }  vis = vlist[0];  XFree (vlist);  // 设置灰度级颜色表  for (i = 0; i < 256; i++)    {      rgb[i].red = rgb[i].green = rgb[i].blue = 65535 - (i * 65535) / 256;      rgb[i].flags = DoRed | DoGreen | DoBlue;      XAllocColor (display, default_cmap, &rgb[i]);    }  win_width = WINDOW_WIDTH;	// 窗口宽度  win_height = WINDOW_HEIGHT;	// 窗口高度  // 建立窗口  win = XCreateSimpleWindow (display, RootWindow (display, screen_num),	//父窗口			     0, 0, win_width, win_height,	//位置和大小			     border_width,	//边界宽度			     BlackPixel (display, screen_num),	//前景色			     WhitePixel (display, screen_num));	//背景色  // 选择窗口感兴趣的事件掩码  XSelectInput (display, win, ExposureMask | KeyPressMask | ButtonPressMask);  // 显示窗口  XMapWindow (display, win);}// X 事件循环voidevent_loop (){  int i;  int is_exit = 0;		// 退出标志  XEvent report;  // 进入事件循环  while (!is_exit)    {      // 取得队列中的事件      XNextEvent (display, &report);      switch (report.type)	{	  // 曝光事件, 窗口应重绘	case Expose:	  // 取得最后一个曝光事件	  if (report.xexpose.count != 0)	    break;	  // 重画图像	  draw_image (0, pixel_size * resolution / 72);	  break;	  // 鼠标点击或有按键, 释放资源后返回主程序	case ButtonPress:	case KeyPress:	  for (i = 0; i < num_glyphs; i++)	    XDestroyImage (gi[i].img);	  XFreeGC (display, gc);	  is_exit = 1;	default:	  break;	}    }}// FreeType 函数返回致命错误voidfatal_error (const char *msg, ...){  va_list ap;  va_start (ap, msg);  fprintf (stderr, "%s: error code 0x%04lx: ", prog, (long unsigned) error);  vfprintf (stderr, msg, ap);  fprintf (stderr, "\n");  va_end (ap);  exit (-1);}// 使用说明voidusage (){  fprintf (stderr, "\n");  fprintf (stderr, "Usage:\n");  fprintf (stderr, "\n");  fprintf (stderr,	   "%s -f font_filename [-p pixel_size] [-r resolution] [-g] [text_to_display]\n",	   prog);  fprintf (stderr, "\n");  fprintf (stderr, "\t-g\tUse grayscale to render text.\n");  fprintf (stderr, "\n");  fprintf (stderr, "\tDefault pixel size is 50.\n");  fprintf (stderr, "\tDefault resolution is 72.\n");  fprintf (stderr, "\tDefault is not using grayscale.\n");  fprintf (stderr, "\tDefault text string is \"%s\"\n", text);  fprintf (stderr, "\n");  exit (1);}// 这是 ft2string.c 的最后一行。This is the end of ft2string.c.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -