/* vi: set sw=4 ts=4: */ /* * KON2 - Kanji ON Console - * Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp) * * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "defs.h" #include "convert.h" #include "font.h" #include "getcap.h" #include "errors.h" #ifdef HAVE_SYS_MMAN_H #include #endif #if !defined(__FONT_UTILITIES__) && defined(SUPPORT_FREETYPE_FONT) #include "ftfont.h" #endif FontRegs *dbFReg, *sbFReg; #define USE_MMAP int fontwidth, fontheight, fontbytes; /* for english chars */ int fontbytes2; /* for Chinese chars 32(16x16) or 72(24x24) */ int LoadBinFont(char *pathName); int LoadX11Font(char *pathName); static u_int GB2312(u_char ch1, u_char ch2) { ch1 &= 0x7F; /* - 0x80 */ ch2 &= 0x7F; /* - 0x80 A0A0 - 8080=2020 */ #ifdef SAVE_FONT_SPACE if (ch1 > 0x29) /* 0x2Axx-0x2Fxx not used */ return(((ch1 - 0x27) * 94 + ch2 - 0x21) * fontbytes2 ); /* 24 * 24, 72 bytes */ else return(((ch1 - 0x21) * 94 + ch2 - 0x21) * fontbytes2 ); #else return (((ch1 - 0x21) * 94 + ch2 - 0x21) * fontbytes2 ); #endif } static u_int GBK(u_char ch1, u_char ch2) { ch1 &= 0x7F; /* 0x81-0xFE */ return (( (ch1-1) * 192 + ch2 - 0x40) * fontbytes2 ); } static u_int BIG5(u_char ch1, u_char ch2) { ch1 &= 0x7F; if (ch2 < 0xA1) return(((ch1 - 0x21) * 157 + ch2 - 0x40) * fontbytes2 ); else return(((ch1 - 0x21) * 157 + 63 + ch2 - 0xA1) * fontbytes2 ); } static u_int JISX0208(u_char ch1, u_char ch2) { ch1 &= 0x7F; ch2 &= 0x7F; #ifdef SAVE_FONT_SPACE if (ch1 > 0x2A) /* 0x2Bxx-0x2Fxx not used */ return((ch2 - 0x41 + (ch1 - 0x26) * 94 /* 96 */) * fontbytes2 ); else return((ch2 - 0x21 + (ch1 - 0x21) * 94 /* 96 */) * fontbytes2 ); #else return ( ( (ch1 - 0x21) * 94 + (ch2 - 0x21) ) * fontbytes2 ); #endif } static u_int KSC5601(u_char ch1, u_char ch2) { ch1 &= 0x7F; ch2 &= 0x7F; #ifdef SAVE_FONT_SPACE if (ch1 > 0x2D) /* 0x2Exx-2Fxx not used */ return((ch2 - 0x21 + (ch1 - 0x24) * 94 /* 96 */) * fontbytes2 ); else return((ch2 - 0x21 + (ch1 - 0x21) * 94 /* 96 */) * fontbytes2 ); #else return ( ( (ch1 - 0x21) * 94 + (ch2 - 0x21) ) * fontbytes2 ); #endif } FontRegs fSRegs[] = { { NULL, 0, "ISO8859-1", NULL, 0, 0, 'B', 'A', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-2", NULL, 0, 0, 'B', 'B', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-3", NULL, 0, 0, 'B', 'C', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-4", NULL, 0, 0, 'B', 'D', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-5", NULL, 0, 0, 'B', 'L', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-6", NULL, 0, 0, 'B', 'G', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-7", NULL, 0, 0, 'B', 'F', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-8", NULL, 0, 0, 'B', 'H', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0, "ISO8859-9", NULL, 0, 0, 'B', 'M', 0, 0xFF, -1, MAP_FAILED}, { NULL, 0,"JISX0201" /*".1976-0" */, NULL, 0, 0, 'J', 'I', 0, 0xFF, -1, MAP_FAILED}, /* no 9 */ { NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, 0x0, -1, MAP_FAILED}, }; FontRegs fDRegs[] = { { GB2312 , 0, "GB2312" /* "GB2312.1980-0" */, NULL, 0, 0, 'A', 0, 0, 0x777E, -1, MAP_FAILED}, { JISX0208 , 0, "JISX0208" /* "JISX0208.1983-0" */, NULL, 0, 0, 'B', 0, 0, 0x7424, -1, MAP_FAILED}, { KSC5601 , 0, "KSC" /* "KSC5601.1987-0" */, NULL, 0, 0, 'C', 0, 0, 0x7D7E, -1, MAP_FAILED}, { JISX0208 , 0, "JISX0212" /* "JISX0212" */, NULL, 0, 0, 'D', 0, 0, 0x7424, -1, MAP_FAILED}, { BIG5, 0, "BIG5" /* "BIG5.HKU-0" */, NULL, 0, 0, '0', 0, 0, 0xFAFE, -1, MAP_FAILED}, /* Big5 is Number 4, Important ! */ { BIG5, 0, "BIG5.HKU-0", NULL, 0, 0, '1', 0, 0, 0xFAFE, -1, MAP_FAILED}, { GBK, 0, "GBK", NULL, 0, 0, '?', 0, 0, 0x7EFF, -1, MAP_FAILED}, /* GBK is number 6 */ { NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, 0x0, -1, MAP_FAILED}, }; const int Coding2FontRegDB[CODE_NUM] = { 1, 1, 1, /* ISO-JP, EUC-JP, SJIS: JISX0208 fonts */ 4, /* Big5 */ 0, /* GB */ 6, /* GBK */ 2, /* KSC */ -1, /* UHC, no font yet */ -1, /* Unicode */ }; const int Coding2FontRegSB[CODE_NUM] = { 9, 9, 9, /* JIS or should we just use 0? */ 0, 0, 0, 0, /* KSC */ 0, /* UHC */ 0, /* Unicode */ }; #if !defined(__FONT_UTILITIES__) int ConfigFont(const char *str) { char *p, *s; p = strtok((char*)str, "\n"); while(p) { p = skip_space(p); /* skip the space */ if (*p && *p != '#') { s = to_space(p); *s = '\0'; /* terminate the pathname */ #ifdef SUPPORT_X11FONT if (strstr(p, ".bdf") || strstr(p, ".pcf") || strstr(p, ".BDF") || strstr(p, ".PCF")) LoadX11Font(p); else #endif LoadBinFont(p); } p = strtok(NULL, "\n"); } return SUCCESS; } void FontInit(void) { #ifdef SUPPORT_FREETYPE_FONT if (UseTTFont) { if (FreetypeInit(TTFontPathName, TTFontSize) == SUCCESS) { int i; fontbytes = FONTBYTES(fontwidth, fontheight); /* 8x16 -> 16, 12x24, 48 bytes */ fontbytes2 = FONTBYTES(2*fontwidth, fontheight); for(i = 0; fSRegs[i].registry; i++) fSRegs[i].fd = 0; for(i = 0; fDRegs[i].registry; i++) fDRegs[i].fd = 0; return; /* Do not run ConfigFont */ } UseTTFont = 0; } #endif DefineCap("Font", ConfigFont, NULL); } void FontDetach(int remove) { int i; #ifdef SUPPORT_FREETYPE_FONT if (UseTTFont) { FreetypeCleanup(); return; /* no need to cleanup bitmap fonts */ } #endif for(i = 0; fSRegs[i].registry; i++) { if (fSRegs[i].fi != MAP_FAILED) MunmapFont(-1, &fSRegs[i]); fSRegs[i].fi = MAP_FAILED; } for(i = 0; fDRegs[i].registry; i ++) { if (fDRegs[i].fi != MAP_FAILED) MunmapFont(-1, &fDRegs[i]); fDRegs[i].fi = MAP_FAILED; } } void FontAttach(void) { int i; lInfo.sb = Coding2FontRegSB[(int)lInfo.sysCoding]; sbFReg = &fSRegs[lInfo.sb]; lInfo.db = Coding2FontRegDB[lInfo.sysCoding]; dbFReg = &fDRegs[lInfo.db]; #ifdef SUPPORT_FREETYPE_FONT if (UseTTFont) { sbFReg->width = fontwidth; dbFReg->width = 2*fontwidth; sbFReg->height = dbFReg->height = fontheight; } #endif if (sbFReg->fd < 0 || MmapFont(-1, sbFReg) ) { for(i = 0; fSRegs[i].registry; i++) if (fSRegs[i].fd >= 0 && MmapFont(-1, &fSRegs[i]) == 0 ) { lInfo.sb = i; /* use first one available */ sbFReg = &fSRegs[i]; break; } } if (sbFReg->fi == MAP_FAILED || dbFReg->fd < 0 || MmapFont(-1, dbFReg) ) { fatal("Can't find the required font for encoding!\n"); } for(i = 0; fSRegs[i].registry; i++) { if (fSRegs[i].fi == MAP_FAILED) /* not mapped */ { fSRegs[i].height = sbFReg->height; fSRegs[i].width = sbFReg->width; fSRegs[i].size = sbFReg->size; fSRegs[i].bitmap = sbFReg->bitmap; fSRegs[i].stat = FR_PROXY; } } #ifdef DEBUG fprintf(stderr, "lInfo.db=0x%x fDRegs[lInfo.db].stat=0x%x fi=%p\r\n", lInfo.db, fDRegs[lInfo.db].stat, fDRegs[lInfo.db].fi); #endif #ifdef DEBUG fprintf(stderr, "fontwidth=%d fontheight=%d fontbytes=%d fontwidth2=%d fontbytes2=%d\r\n", fontwidth, fontheight, fontbytes, dbFReg->width, fontbytes2); #endif } int MmapFont(int encoding, FontRegs *fr) { if (encoding >= 0 && fr == NULL && encoding < CODE_NUM) /* valid encoding */ fr = &fDRegs[Coding2FontRegDB[encoding]]; if (fr == NULL || fr->fd < 0) return -1; #ifdef SUPPORT_FREETYPE_FONT if (UseTTFont) { fr->stat = FR_FREETYPEFONT; fr->fi = (FontInfo *)0x0; /* make it non -1 */ return 0; } #endif if (fr->bitmap && fr->fi != MAP_FAILED) return 0; /* already mapped */ #ifdef SUPPORT_X11FONT if (fr->stat == FR_X11FONT) { fr->fi = (FontInfo *)0x0; /* make it non -1 */ #ifdef DEBUG fprintf(stderr, "Attach %dx%d X11 font for encoding %d\r\n", fr->width, fr->height, encoding); #endif } else #endif /* SUPPORT_X11FONT */ { fr->fi = (FontInfo *)mmap(0, sizeof(FontInfo) + fr->size, PROT_READ, MAP_SHARED, fr->fd, 0); if (fr->fi == MAP_FAILED) { warn("Mmap size %d font file failed.\r\n", sizeof(FontInfo) + fr->size); close(fr->fd); fr->fd = -1; /* don't want to use it again */ return -1; } fr->bitmap = ((char*)fr->fi) + sizeof(FontInfo); fr->stat = FR_ATTACH; #ifdef DEBUG fprintf(stderr, "Mmapped %dx%d font at address %p: %d Bytes\r\n", fr->width, fr->height, fr->fi, fr->size ); #endif } return 0; } int MunmapFont(int encoding, FontRegs *fr) { if (encoding >= 0 && fr == NULL && encoding < CODE_NUM) /* valid encoding */ fr = &fDRegs[Coding2FontRegDB[encoding]]; if (!fr) return -1; if (fr->fi == MAP_FAILED) return 0; /* already unmapped */ #ifdef SUPPORT_FREETYPEFONT if (fr->stat == FR_FREETYPEFONT) { #ifdef DEBUG fprintf(stderr, "Detaching Freetype Font %s.\r\n", TTFontPathName); #endif } else #endif /* SUPPORT_FREETYPEFONT */ #ifdef SUPPORT_X11FONT if (fr->stat == FR_X11FONT) { #ifdef DEBUG fprintf(stderr, "Detach %dx%d X11 font for encoding %d\r\n", fr->width, fr->height, encoding); #endif } else #endif /* SUPPORT_X11FONT */ { if (munmap(fr->fi, sizeof(FontInfo) + fr->size)) return -1; /* failed to unmapped? */ #ifdef DEBUG fprintf(stderr, "Munmapped %dx%d font at address %p: %d Bytes\r\n", fr->width, fr->height, fr->fi, fr->size ); #endif } fr->bitmap = NULL; fr->width = fr->height = fr->size = fr->stat = 0; fr->fi = MAP_FAILED; return 0; } int LoadBinFont(char *pathName) { int fd, n; char fname[CCE_PATHNAME_MAX+1]; FontInfo fi; #ifdef DEBUG fprintf(stderr, "Now loading font %s\r\n", pathName); #endif if ((fd = open(pathName, O_RDONLY | CCE_OPENFLAG)) < 0 ) { strcpy(fname, CCELIB "/"); if (strlen(fname) + strlen(pathName) >= CCE_PATHNAME_MAX) return -1; /* buffer overrun */ strcat(fname, pathName); fd = open( fname, O_RDONLY | CCE_OPENFLAG); } if (fd < 0 || read(fd, &fi, sizeof(fi)) != sizeof(fi) || (fi.size = ConvertLE32ToCPU((unsigned char *)&fi.size)) <= 0 || fi.width < 6 || fi.height < 6 || lseek(fd, sizeof(FontInfo) + fi.size, SEEK_SET) == -1 ) /* make sure it's big enough */ { if (fd >= 0) warn("Load Font File %s Error.\r\n", pathName); if (fd >= 0) close(fd); return -1; } #ifdef DEBUG fprintf(stderr, "fi.width=%d fi.height=%d fi.size=%d fi.type=0x%x fi.type & ~CHR_DFLD=%d\n", fi.width, fi.height, fi.size, fi.type, fi.type & ~CHR_DFLD); #endif if (fi.type & CHR_DBC) /* double-byte fonts */ { n = fi.type & ~CHR_DFLD; if ((fi.type & CHR_DFLD) && (u_int)(n) < sizeof(fDRegs)/sizeof(FontRegs)) { if (fontwidth == 0) /* will use first font's dimension */ { fontwidth = fi.width / 2; fontheight = fi.height; fontbytes = FONTBYTES(fontwidth, fontheight); /* 8x16 -> 16, 12x24, 48 bytes */ fontbytes2 = FONTBYTES(2*fontwidth, fontheight); } else if (fi.width != 2*fontwidth || fi.height != fontheight) { warn("Double-byte font should have same height and twice width as single-byte font.\r\n"); close(fd); return -1; } fDRegs[n].height = fi.height; fDRegs[n].width = fi.width; fDRegs[n].size = fi.size; fDRegs[n].bitmap = NULL; /* not mapped yet! */ fDRegs[n].fi = MAP_FAILED; /* not mapped yet */ fDRegs[n].fd = fd; } } else /* single byte font */ { n = fi.type & ~CHR_SFLD; if ((fi.type & CHR_SFLD) && (u_int)(n) < sizeof(fSRegs)/sizeof(FontRegs)) { if (fontwidth == 0) { fontwidth = fi.width; /* will override the old one? Normally just load one font */ fontheight = fi.height; fontbytes = FONTBYTES(fontwidth, fontheight); /* 8x16 -> 16, 12x24, 48 bytes */ fontbytes2 = FONTBYTES(2*fontwidth, fontheight); } else if (fi.width != fontwidth || fi.height != fontheight) { warn("Double-byte font should have same height and twice width as single-byte font."); close(fd); return -1; } fSRegs[n].height = fi.height; fSRegs[n].width = fi.width; fSRegs[n].size = fi.size; fSRegs[n].bitmap = NULL; /* not mapped yet! */ fSRegs[n].fi = MAP_FAILED; /* not mapped yet -1 */ fSRegs[n].fd = fd; } } return 0; } #endif /* __FONT_UTILITIES__ */ int CodingByRegistry(char *reg) { int i; i = 0; while (fSRegs[i].registry) { if (strlen(reg) >= strlen(fSRegs[i].registry) && !strncasecmp(fSRegs[i].registry, reg, strlen(fSRegs[i].registry))) return(i|CHR_SFLD); i ++; } i = 0; while (fDRegs[i].registry) { if (strlen(reg) >= strlen(fDRegs[i].registry) && !strncasecmp(fDRegs[i].registry, reg, strlen(fDRegs[i].registry))) return(i|CHR_DFLD); i ++; } if (!strncasecmp(reg, "ISO8859", 7) /*|| !strncasecmp(reg, "ISO10646", 8) */) return (0 | CHR_SFLD); /* single byte index 0 */ return(-1); }