summaryrefslogtreecommitdiffstats
path: root/contrib/groff/src/libs/libgroff/font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/groff/src/libs/libgroff/font.cc')
-rw-r--r--contrib/groff/src/libs/libgroff/font.cc158
1 files changed, 127 insertions, 31 deletions
diff --git a/contrib/groff/src/libs/libgroff/font.cc b/contrib/groff/src/libs/libgroff/font.cc
index aa602b4..69e46e1 100644
--- a/contrib/groff/src/libs/libgroff/font.cc
+++ b/contrib/groff/src/libs/libgroff/font.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
@@ -19,8 +19,8 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-#include <string.h>
+#include "lib.h"
+
#include <ctype.h>
#include <assert.h>
#include <math.h>
@@ -29,7 +29,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "error.h"
#include "cset.h"
#include "font.h"
-#include "lib.h"
+#include "paper.h"
const char *const WS = " \t\n\r";
@@ -94,13 +94,12 @@ text_file::~text_file()
fclose(fp);
}
-
int text_file::next()
{
if (fp == 0)
return 0;
if (buf == 0) {
- buf = new char [128];
+ buf = new char[128];
size = 128;
}
for (;;) {
@@ -109,8 +108,8 @@ int text_file::next()
int c = getc(fp);
if (c == EOF)
break;
- if (illegal_input_char(c))
- error("illegal input character code `%1'", int(c));
+ if (invalid_input_char(c))
+ error("invalid input character code `%1'", int(c));
else {
if (i + 1 >= size) {
char *old_buf = buf;
@@ -161,6 +160,9 @@ font::font(const char *s)
font::~font()
{
+ for (int i = 0; i < ch_used; i++)
+ if (ch[i].special_device_coding)
+ a_delete ch[i].special_device_coding;
a_delete ch;
a_delete ch_index;
if (kern_hash_table) {
@@ -206,6 +208,34 @@ inline int font::scale(int w, int sz)
return sz == unitwidth ? w : scale_round(w, sz, unitwidth);
}
+int font::unit_scale(double *value, char unit)
+{
+ // we scale everything to inch
+ double divisor = 0;
+ switch (unit) {
+ case 'i':
+ divisor = 1;
+ break;
+ case 'p':
+ divisor = 72;
+ break;
+ case 'P':
+ divisor = 6;
+ break;
+ case 'c':
+ divisor = 2.54;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (divisor) {
+ *value /= divisor;
+ return 1;
+ }
+ return 0;
+}
+
int font::get_skew(int c, int point_size, int sl)
{
int h = get_height(c, point_size);
@@ -303,7 +333,7 @@ int font::get_space_width(int 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)
+: i1(c1), i2(c2), amount(n), next(p)
{
}
@@ -472,6 +502,58 @@ static char *trim_arg(char *p)
return p;
}
+int font::scan_papersize(const char *p,
+ const char **size, double *length, double *width)
+{
+ double l, w;
+ char lu[2], wu[2];
+ const char *pp = p;
+ int test_file = 1;
+ char line[255];
+again:
+ if (csdigit(*pp)) {
+ if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4
+ && l > 0 && w > 0
+ && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) {
+ if (length)
+ *length = l;
+ if (width)
+ *width = w;
+ if (size)
+ *size = "custom";
+ return 1;
+ }
+ }
+ else {
+ int i;
+ for (i = 0; i < NUM_PAPERSIZES; i++)
+ if (strcasecmp(papersizes[i].name, pp) == 0) {
+ if (length)
+ *length = papersizes[i].length;
+ if (width)
+ *width = papersizes[i].width;
+ if (size)
+ *size = papersizes[i].name;
+ return 1;
+ }
+ if (test_file) {
+ FILE *f = fopen(p, "r");
+ if (f) {
+ fgets(line, 254, f);
+ fclose(f);
+ test_file = 0;
+ char *linep = strchr(line, '\0');
+ // skip final newline, if any
+ if (*(--linep) == '\n')
+ *linep = '\0';
+ pp = line;
+ goto again;
+ }
+ }
+ }
+ return 0;
+}
+
// If the font can't be found, then if not_found is non-NULL, it will be set
// to 1 otherwise a message will be printed.
@@ -586,12 +668,12 @@ int font::load(int *not_found)
}
int i1 = name_to_index(c1);
if (i1 < 0) {
- t.error("illegal character `%1'", c1);
+ t.error("invalid character `%1'", c1);
return 0;
}
int i2 = name_to_index(c2);
if (i2 < 0) {
- t.error("illegal character `%1'", c2);
+ t.error("invalid character `%1'", c2);
return 0;
}
add_kern(i1, i2, n);
@@ -624,7 +706,7 @@ int font::load(int *not_found)
}
int index = name_to_index(nm);
if (index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
copy_entry(index, last_index);
@@ -671,20 +753,15 @@ int font::load(int *not_found)
t.error("bad code `%1' for character `%2'", p, nm);
return 0;
}
-
p = strtok(0, WS);
if ((p == NULL) || (strcmp(p, "--") == 0)) {
metric.special_device_coding = NULL;
- } else {
- char *name=(char *)malloc(strlen(p)+1);
-
- if (name == NULL) {
- fatal("malloc failed while reading character encoding");
- }
+ }
+ else {
+ char *name = new char[strlen(p) + 1];
strcpy(name, p);
metric.special_device_coding = name;
}
-
if (strcmp(nm, "---") == 0) {
last_index = number_to_index(metric.code);
add_entry(last_index, metric);
@@ -692,7 +769,7 @@ int font::load(int *not_found)
else {
last_index = name_to_index(nm);
if (last_index < 0) {
- t.error("illegal character `%1'", nm);
+ t.error("invalid character `%1'", nm);
return 0;
}
add_entry(last_index, metric);
@@ -736,7 +813,6 @@ static struct {
{ "sizescale", &font::sizescale }
};
-
int font::load_desc()
{
int nfonts = 0;
@@ -769,15 +845,6 @@ int font::load_desc()
return 0;
}
}
- else if (strcmp("tcommand", p) == 0) {
- tcommand = 1;
- }
- else if (strcmp("pass_filenames", p) == 0) {
- pass_filenames = 1;
- }
- else if (strcmp("use_charnames_in_special", p) == 0) {
- use_charnames_in_special = 1;
- }
else if (strcmp("family", p) == 0) {
p = strtok(0, WS);
if (!p) {
@@ -815,6 +882,31 @@ int font::load_desc()
}
font_name_table[nfonts] = 0;
}
+ else if (strcmp("papersize", p) == 0) {
+ p = strtok(0, WS);
+ if (!p) {
+ t.error("papersize command requires an argument");
+ return 0;
+ }
+ int found_paper = 0;
+ while (p) {
+ double unscaled_paperwidth, unscaled_paperlength;
+ if (scan_papersize(p, &papersize, &unscaled_paperlength,
+ &unscaled_paperwidth)) {
+ paperwidth = int(unscaled_paperwidth * res + 0.5);
+ paperlength = int(unscaled_paperlength * res + 0.5);
+ found_paper = 1;
+ break;
+ }
+ p = strtok(0, WS);
+ }
+ if (!found_paper) {
+ t.error("bad paper size");
+ return 0;
+ }
+ }
+ else if (strcmp("pass_filenames", p) == 0)
+ pass_filenames = 1;
else if (strcmp("sizes", p) == 0) {
int n = 16;
sizes = new int[n];
@@ -885,6 +977,10 @@ int font::load_desc()
style_table[i++] = tem;
}
}
+ else if (strcmp("tcommand", p) == 0)
+ tcommand = 1;
+ else if (strcmp("use_charnames_in_special", p) == 0)
+ use_charnames_in_special = 1;
else if (strcmp("charset", p) == 0)
break;
else if (unknown_desc_command_handler) {
OpenPOWER on IntegriCloud