Files
freetype/contrib/ttf2pk/subfont.c
2023-08-27 18:03:45 +02:00

265 lines
5.4 KiB
C

/*
* subfont.c
*
* This file is part of the ttf2pk package.
*
* Copyright 1997-1999 by
* Frederic Loyer <loyer@ensta.fr>
* Werner Lemberg <wl@gnu.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h> /* for size_t */
#include <ctype.h>
#include <string.h>
#include "filesrch.h"
#include "subfont.h"
#include "newobj.h"
#include "errormsg.h"
static char *real_sfd_name;
static FILE *sfd;
/*
* Initialize subfont functionality. The argument is the subfont
* definition file name. If `fatal' is `True', the routine exits
* with an error. If `fatal' is `False', a warning message is emitted
* and `False' returned if an error occurs; in case of success `True'
* will be returned.
*/
Boolean
init_sfd(Font *fnt, Boolean fatal)
{
real_sfd_name = TeX_search_sfd_file(&(fnt->sfdname));
if (!real_sfd_name)
{
if (fatal)
oops("Cannot find subfont definition file `%s'.", fnt->sfdname);
else
{
warning("Cannot find subfont definition file `%s'.", fnt->sfdname);
return False;
}
}
sfd = fopen(real_sfd_name, "rt");
if (sfd == NULL)
{
if (fatal)
oops("Cannot open subfont definition file `%s'.", fnt->sfdname);
else
{
warning("Cannot open subfont definition file `%s'.", fnt->sfdname);
return False;
}
}
return True;
}
/*
* This function fills the font structure sequentially with subfont
* entries; it returns `False' if no more subfont entries are available,
* `True' otherwise.
*
* fnt->subfont_name must be set to NULL before the first call.
*
* The subset parser was inspired by ttf2bdf.c .
*/
Boolean
get_sfd(Font *fnt)
{
long i, offset;
long begin, end = -1;
char *buffer, *oldbuffer, *bufp, *bufp2, *bufp3;
for (i = 0; i < 256; i++)
fnt->sf_code[i] = -1;
again:
buffer = get_line(sfd);
if (!buffer)
oops("Error reading subfont definition file `%s'.", real_sfd_name);
if (!*buffer)
return False;
oldbuffer = newstring(buffer);
bufp = buffer;
offset = 0;
while (*bufp) /* remove comment */
{
if (*bufp == '#')
{
bufp++;
break;
}
bufp++;
}
*(--bufp) = '\0'; /* remove final newline character */
bufp = buffer;
while (isspace(*bufp))
bufp++;
if (*bufp == '\0') /* empty line? */
{
free(buffer);
free(oldbuffer);
goto again;
}
while (*bufp && !isspace(*bufp)) /* subfont name */
bufp++;
*(bufp++) = '\0';
while (isspace(*bufp))
bufp++;
if (*bufp == '\0')
oops("Invalid subfont entry in `%s'.", real_sfd_name);
if (fnt->subfont_name)
free(fnt->subfont_name);
fnt->subfont_name = newstring(buffer);
while (1)
{
bufp3 = bufp;
begin = strtol(bufp, &bufp2, 0);
if (bufp == bufp2 || begin < 0 || begin > 0xFFFF)
boops(oldbuffer, bufp - buffer,
"Invalid subfont range or offset entry.");
if (*bufp2 == ':') /* offset */
{
offset = begin;
if (offset > 0xFF)
boops(oldbuffer, bufp - buffer, "Invalid subfont offset.");
bufp = bufp2 + 1;
while (isspace(*bufp))
bufp++;
continue;
}
else if (*bufp2 == '_') /* range */
{
bufp = bufp2 + 1;
if (!isdigit(*bufp))
boops(oldbuffer, bufp - buffer, "Invalid subfont range entry.");
end = strtol(bufp, &bufp2, 0);
if (bufp == bufp2 || end < 0 || end > 0xFFFFL)
boops(oldbuffer, bufp - buffer, "Invalid subfont range entry.");
if (*bufp2 && !isspace(*bufp2))
boops(oldbuffer, bufp2 - buffer, "Invalid subfont range entry.");
if (end < begin)
boops(oldbuffer, bufp - buffer, "End of subfont range too small.");
if (offset + (end - begin) > 255)
boops(oldbuffer, bufp3 - buffer,
"Subfont range too large for current offset (%i).", offset);
}
else if (isspace(*bufp2) || !*bufp2) /* single value */
end = begin;
else
boops(oldbuffer, bufp2 - buffer, "Invalid subfont range entry.");
for (i = begin; i <= end; i++)
{
if (fnt->sf_code[offset] != -1)
boops(oldbuffer, bufp3 - buffer, "Overlapping subfont ranges.");
fnt->sf_code[offset++] = i;
}
bufp = bufp2;
while (isspace(*bufp))
bufp++;
if (!*bufp)
break;
}
free(buffer);
free(oldbuffer);
return True;
}
void
close_sfd(void)
{
if (sfd)
fclose(sfd);
}
/*
* We extract the subfont definition file name. The name must
* be embedded between two `@' characters. If there is no sfd file,
* `sfd_begin' is set to -1.
*
* The `@' characters will be replaced with null characters.
*/
void
handle_sfd(char *s, int *sfd_begin, int *postfix_begin)
{
size_t len;
int i;
Boolean have_atsign;
have_atsign = False;
len = strlen(s);
*sfd_begin = -1;
*postfix_begin = -1;
for (i = 0; s[i]; i++)
{
if (s[i] == '@')
{
if (have_atsign)
{
*postfix_begin = i + 1;
s[i] = '\0';
break;
}
have_atsign = True;
*sfd_begin = i + 1;
s[i] = '\0';
}
}
if (*sfd_begin != -1 &&
(*postfix_begin == -1 || *postfix_begin < *sfd_begin + 2))
oops("Invalid subfont definition file name.");
if (*postfix_begin > -1)
for (i = *postfix_begin; s[i]; i++)
if (s[i] == '/' || s[i] == ':' || s[i] == '\\' || s[i] == '@')
oops("`/', `:', `\\', and `@' not allowed after second `@'.");
}
/* end */