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

📄 font.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- C++ -*-/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.     Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdio.h>#include <string.h>#include <ctype.h>#include <assert.h>#include <math.h>#include <stdlib.h>#include "errarg.h"#include "error.h"#include "cset.h"#include "font.h"#include "lib.h"const char *const WS = " \t\n\r";struct font_char_metric {  char type;  int code;  int width;  int height;  int depth;  int pre_math_space;  int italic_correction;  int subscript_correction;};struct font_kern_list {  int i1;  int i2;  int amount;  font_kern_list *next;  font_kern_list(int, int, int, font_kern_list * = 0);};struct font_widths_cache {  font_widths_cache *next;  int point_size;  int *width;  font_widths_cache(int, int, font_widths_cache *);  ~font_widths_cache();};/* text_file */struct text_file {  FILE *fp;  char *path;  int lineno;  int size;  int skip_comments;  char *buf;  text_file(FILE *fp, char *p);  ~text_file();  int next();  void error(const char *format, 	     const errarg &arg1 = empty_errarg,	     const errarg &arg2 = empty_errarg,	     const errarg &arg3 = empty_errarg);};text_file::text_file(FILE *p, char *s) : lineno(0), buf(0), size(0), skip_comments(1), fp(p), path(s){}text_file::~text_file(){  a_delete buf;  a_delete path;  if (fp)    fclose(fp);}int text_file::next(){  if (fp == 0)    return 0;  if (buf == 0) {    buf = new char [128];    size = 128;  }  for (;;) {    int i = 0;    for (;;) {      int c = getc(fp);      if (c == EOF)	break;      if (illegal_input_char(c))	error("illegal input character code `%1'", int(c));      else {	if (i + 1 >= size) {	  char *old_buf = buf;	  buf = new char[size*2];	  memcpy(buf, old_buf, size);	  a_delete old_buf;	  size *= 2;	}	buf[i++] = c;	if (c == '\n')	  break;      }    }    if (i == 0)      break;    buf[i] = '\0';    lineno++;    char *ptr = buf;    while (csspace(*ptr))      ptr++;    if (*ptr != 0 && (!skip_comments || *ptr != '#'))      return 1;  }  return 0;}void text_file::error(const char *format, 		      const errarg &arg1,		      const errarg &arg2,		      const errarg &arg3){  error_with_file_and_line(path, lineno, format, arg1, arg2, arg3);}/* font functions */font::font(const char *s): special(0), ligatures(0), kern_hash_table(0), space_width(0),  ch(0), ch_used(0), ch_size(0), ch_index(0), nindices(0), widths_cache(0){  name = new char[strlen(s) + 1];  strcpy(name, s);  internalname = 0;  slant = 0.0;  // load();			// for testing}font::~font(){  a_delete ch;  a_delete ch_index;  if (kern_hash_table) {    for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) {      font_kern_list *kerns = kern_hash_table[i];      while (kerns) {	font_kern_list *tem = kerns;	kerns = kerns->next;	delete tem;      }    }    a_delete kern_hash_table;  }  a_delete name;  a_delete internalname;  while (widths_cache) {    font_widths_cache *tem = widths_cache;    widths_cache = widths_cache->next;    delete tem;  }}static int scale_round(int n, int x, int y){  assert(x >= 0 && y > 0);  int y2 = y/2;  if (x == 0)    return 0;  if (n >= 0) {    if (n <= (INT_MAX - y2)/x)      return (n*x + y2)/y;    return int(n*double(x)/double(y) + .5);  }  else {    if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x)      return (n*x - y2)/y;    return int(n*double(x)/double(y) - .5);  }}inline int font::scale(int w, int sz){  return sz == unitwidth ? w : scale_round(w, sz, unitwidth);}int font::get_skew(int c, int point_size, int sl){  int h = get_height(c, point_size);  return int(h*tan((slant+sl)*M_PI/180.0) + .5);}int font::contains(int c){  return c >= 0 && c < nindices && ch_index[c] >= 0;}int font::is_special(){  return special;}font_widths_cache::font_widths_cache(int ps, int ch_size,				     font_widths_cache *p = 0): next(p), point_size(ps){  width = new int[ch_size];  for (int i = 0; i < ch_size; i++)    width[i] = -1;}font_widths_cache::~font_widths_cache(){  a_delete width;}int font::get_width(int c, int point_size){  assert(c >= 0 && c < nindices);  int i = ch_index[c];  assert(i >= 0);  if (point_size == unitwidth)    return ch[i].width;  if (!widths_cache)    widths_cache = new font_widths_cache(point_size, ch_size);  else if (widths_cache->point_size != point_size) {    for (font_widths_cache **p = &widths_cache; *p; p = &(*p)->next)      if ((*p)->point_size == point_size)	break;    if (*p) {      font_widths_cache *tem = *p;      *p = (*p)->next;      tem->next = widths_cache;      widths_cache = tem;    }    else      widths_cache = new font_widths_cache(point_size, ch_size, widths_cache);  }  int &w = widths_cache->width[i];  if (w < 0)    w = scale(ch[i].width, point_size);  return w;}int font::get_height(int c, int point_size){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return scale(ch[ch_index[c]].height, point_size);}int font::get_depth(int c, int point_size){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return scale(ch[ch_index[c]].depth, point_size);}int font::get_italic_correction(int c, int point_size){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return scale(ch[ch_index[c]].italic_correction, point_size);}int font::get_left_italic_correction(int c, int point_size){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return scale(ch[ch_index[c]].pre_math_space, point_size);}int font::get_subscript_correction(int c, int point_size){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return scale(ch[ch_index[c]].subscript_correction, point_size);}int font::get_space_width(int point_size){  return scale(space_width, point_size);}font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)     : i1(c1), i2(c2), amount(n), next(p){}inline int font::hash_kern(int i1, int i2){  int n = ((i1 << 10) + i2) % KERN_HASH_TABLE_SIZE;  return n < 0 ? -n : n;}void font::add_kern(int i1, int i2, int amount){  if (!kern_hash_table) {    kern_hash_table = new font_kern_list *[KERN_HASH_TABLE_SIZE];    for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++)      kern_hash_table[i] = 0;  }  font_kern_list **p = kern_hash_table + hash_kern(i1, i2);  *p = new font_kern_list(i1, i2, amount, *p);}int font::get_kern(int i1, int i2, int point_size){  if (kern_hash_table) {    for (font_kern_list *p = kern_hash_table[hash_kern(i1, i2)]; p; p = p->next)      if (i1 == p->i1 && i2 == p->i2)	return scale(p->amount, point_size);  }  return 0;}int font::has_ligature(int mask){  return mask & ligatures;}int font::get_character_type(int c){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return ch[ch_index[c]].type;}int font::get_code(int c){  assert(c >= 0 && c < nindices && ch_index[c] >= 0);  return ch[ch_index[c]].code;}const char *font::get_name(){  return name;}const char *font::get_internal_name(){  return internalname;}void font::alloc_ch_index(int index){  if (nindices == 0) {    nindices = 128;    if (index >= nindices)      nindices = index + 10;    ch_index = new short[nindices];    for (int i = 0; i < nindices; i++)      ch_index[i] = -1;  }  else {    int old_nindices = nindices;    nindices *= 2;    if (index >= nindices)      nindices = index + 10;    short *old_ch_index = ch_index;    ch_index = new short[nindices];    memcpy(ch_index, old_ch_index, sizeof(short)*old_nindices);    for (int i = old_nindices; i < nindices; i++)      ch_index[i] = -1;    a_delete old_ch_index;  }}void font::extend_ch(){  if (ch == 0)    ch = new font_char_metric[ch_size = 16];  else {    int old_ch_size = ch_size;    ch_size *= 2;    font_char_metric *old_ch = ch;    ch = new font_char_metric[ch_size];    memcpy(ch, old_ch, old_ch_size*sizeof(font_char_metric));    a_delete old_ch;  }}void font::compact(){  for (int i = nindices - 1; i >= 0; i--)    if (ch_index[i] >= 0)      break;  i++;  if (i < nindices) {    short *old_ch_index = ch_index;    ch_index = new short[i];    memcpy(ch_index, old_ch_index, i*sizeof(short));    a_delete old_ch_index;    nindices = i;  }  if (ch_used < ch_size) {    font_char_metric *old_ch = ch;    ch = new font_char_metric[ch_used];    memcpy(ch, old_ch, ch_used*sizeof(font_char_metric));    a_delete old_ch;    ch_size = ch_used;  }}void font::add_entry(int index, const font_char_metric &metric){  assert(index >= 0);  if (index >= nindices)    alloc_ch_index(index);  assert(index < nindices);  if (ch_used + 1 >= ch_size)    extend_ch();  assert(ch_used + 1 < ch_size);  ch_index[index] = ch_used;  ch[ch_used++] = metric;}void font::copy_entry(int new_index, int old_index){  assert(new_index >= 0 && old_index >= 0 && old_index < nindices);  if (new_index >= nindices)    alloc_ch_index(new_index);  ch_index[new_index] = ch_index[old_index];}font *font::load_font(const char *s, int *not_found){  font *f = new font(s);  if (!f->load(not_found)) {    delete f;    return 0;  }  return f;}static char *trim_arg(char *p){  if (!p)

⌨️ 快捷键说明

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