/* psftools: Manipulate console fonts in the .PSF format Copyright (C) 2003 John Elliott 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "cnvshell.h" #include "psflib.h" /* Convert a PSF to an X11 Bitmap Distribution Format font. * */ static char helpbuf[2048]; static int first = -1; static int last = -1; static char fontname[256] = { 'p', 's', 'f', 0 }; static int descent = -1; static int def_char = 255; static int iso10646 = 0; static PSF_FILE psf; static PSF_MAPPING *codepage; /* Program name */ char *cnv_progname = "PSF2BDF"; /* ddash = 1 if option started with a double-dash; else 0 */ /* Return NULL if OK, else error string */ char *cnv_set_option(int ddash, char *variable, char *value) { if (!stricmp(variable, "first")) { first = atoi(value); return NULL; } if (!stricmp(variable, "last")) { last = atoi(value); return NULL; } if (!stricmp(variable, "descent")) { descent = atoi(value); return NULL; } if (!stricmp(variable, "defchar")) { def_char = atoi(value); return NULL; } if (!stricmp(variable, "fontname")) { strncpy(fontname, value, 255); return NULL; } if (!stricmp(variable, "256")) { first = 0; last = 255; return NULL; } if (!stricmp(variable, "iso10646")) { iso10646 = 1; return NULL; } if (!stricmp(variable, "codepage")) { codepage = psf_find_mapping(value); if (codepage == NULL) return "Code page name not recognised."; return NULL; } if (strlen(variable) > 2000) variable[2000] = 0; sprintf(helpbuf, "Unknown option: %s\n", variable); return helpbuf; } /* Return help string */ char *cnv_help(void) { sprintf(helpbuf, "Syntax: %s psffile bdffile { options }\n\n", cnv_progname); strcat (helpbuf, "Options: \n" " --first=n Start with character n\n" " --last=n Finish with character n\n" " --fontname=str Font name to use\n" " --defchar=n Set default character\n" " --descent=n Set descent (distance between baseline of \n" " characters and bottom of font)\n" " --codepage=xxx Extract characters in the specified codepage\n" " --256 Equivalent to --first=0 --last=255\n" " --iso10646 Use ISO10646 encoding\n"); return helpbuf; } char *cnv_execute(FILE *infile, FILE *outfile) { int rv, y, x, wb; psf_dword ch, f, l, glyph, codept; unsigned char *d; psf_file_new(&psf); rv = psf_file_read(&psf, infile); if (rv != PSF_E_OK) return psf_error_string(rv); if (codepage && !psf_is_unicode(&psf)) { psf_file_delete(&psf); return "Cannot extract by codepage; source file has no Unicode table"; } if (descent == -1) descent = psf.psf_height / 4; fprintf(outfile, "STARTFONT 2.1\n"); fprintf(outfile, "FONT %s\n", fontname); fprintf(outfile, "SIZE %ld 75 75\n", psf.psf_height); fprintf(outfile, "FONTBOUNDINGBOX %ld %ld 0 %d\n", psf.psf_width, psf.psf_height, -descent); fprintf(outfile, "STARTPROPERTIES 3\n"); fprintf(outfile, "FONT_DESCENT %d\n", descent); fprintf(outfile, "FONT_ASCENT %ld\n", psf.psf_height - descent); fprintf(outfile, "DEFAULT_CHAR %d\n", def_char); fprintf(outfile, "ENDPROPERTIES\n"); f = (first >= 0) ? first : 0; l = (last >= 0) ? last : (psf.psf_length - 1); if (codepage && l >= 256) l = 255; if (l >= psf.psf_length) l = psf.psf_length - 1; fprintf(outfile, "CHARS %ld\n", l + 1 - f); /* Emit header */ wb = (psf.psf_width + 7) / 8; for (ch = f; ch <= l; ch++) { if (codepage) { if (ch < 256 && !psf_unicode_lookupmap(&psf, codepage, ch, &glyph, &codept)) { d = psf.psf_data + glyph * psf.psf_charlen; } else { if (ch < 256 && !psf_unicode_banned(codepage->psfm_tokens[ch][0])) fprintf(stderr, "Warning: U+%04lx not found in font\n", codepage->psfm_tokens[ch][0]); codept = 0xFFFD; d = NULL; } } else { d = psf.psf_data + ch * psf.psf_charlen; if (psf_is_unicode(&psf)) { if (psf.psf_dir.psf_dirents_used[ch] && psf.psf_dir.psf_dirents_used[ch]->psfu_token != 0xFFFE) { codept = psf.psf_dir.psf_dirents_used[ch]->psfu_token; } else codept = 0xFFFD; } else codept = ch; } fprintf(outfile, "STARTCHAR C%04lx\n", ch); fprintf(outfile, "ENCODING %ld\n", iso10646 ? codept : ch); fprintf(outfile, "SWIDTH 666 0\n"); fprintf(outfile, "DWIDTH %ld 0\n", psf.psf_width); fprintf(outfile, "BBX %ld %ld 0 %d\n", psf.psf_width, psf.psf_height, -descent); fprintf(outfile, "BITMAP\n"); for (y = 0; y < psf.psf_height; y++) { for (x = 0; x < wb; x++) { fprintf(outfile, "%02x", d ? *d : 0); if (d) d++; } fprintf(outfile, "\n"); } fprintf(outfile, "ENDCHAR\n"); } fprintf(outfile, "ENDFONT\n"); psf_file_delete(&psf); return NULL; }