Mercurial > kinput2.yaz
diff lib/fontbank.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 5a32b68b627d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fontbank.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,323 @@ +#ifndef lint +static char *rcsid = "$Id: fontbank.c,v 1.4 1994/05/17 10:52:15 ishisone Rel $"; +#endif +/* + * Copyright (c) 1991, 1994 Software Research Associates, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Software Research + * Associates makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * Author: Makoto Ishisone, Software Research Associates, Inc., Japan + */ + +#include <X11/Xos.h> +#include <X11/Intrinsic.h> +#include "CachedFont.h" +#include "KIFontSet.h" +#include "FontBank.h" + +#define DEBUG_VAR debug_fontbank +#include "DebugPrint.h" + +#define FC_HASH_SIZE 8 + +typedef struct _font_cache_ { + int sum; + char *name; + XFontStruct **fonts; + int num_fonts; + struct _font_cache_ *next; +} FontCache; + +typedef struct _fb_info_ { + char *language; + KICharSet *charsets; + int num_charsets; +} FBInfo; + +typedef struct _fb_rec_ { + Display *dpy; + struct _fb_rec_ *next; + FBInfo *info; + int reference_count; + FontCache *hash[FC_HASH_SIZE]; +} FBRec; + +static FontBank fontBankList = NULL; + +/* + * Language information: + * The FBInfo structure holds information about the character sets + * required for a specific language. Currently, this infomation + * is provided only for Japanese. + */ + +static KICharSetSpec asciiCharSets[] = { + { "iso8859-1", NULL }, /* preferable */ + { "jisx0201.1976-0", NULL }, /* alternative */ + { "iso8859-*", NULL }, /* alternative */ +}; +static KICharSetSpec kanaCharSets[] = { + { "jisx0201.1976-0", NULL }, +}; +static KICharSetSpec kanjiCharSets[] = { + { "jisx0208.1983-0", NULL }, + { "jisx0208.1983-1", NULL }, + { "jisx0208.1990-0", NULL }, + { "jisx0208.1990-1", NULL }, + { "jisx0208.1976-0", NULL }, + { "jisx0208.1976-1", NULL }, +}; +static KICharSet jpCharSets[3] = { + { asciiCharSets, XtNumber(asciiCharSets) }, + { kanaCharSets, XtNumber(kanaCharSets) }, + { kanjiCharSets, XtNumber(kanjiCharSets) }, +}; + +static FBInfo fontBankInfo[] = { + { "ja_JP", jpCharSets, XtNumber(jpCharSets) }, + { NULL } +}; + +static int +getsum(s) +char *s; +{ + unsigned char *p = (unsigned char *)s; + int sum = 0; + + while (*p != '\0') sum += *p++; + return sum; +} + +static FBInfo * +getInfo(lang) +char *lang; +{ + FBInfo *fip; + + for (fip = fontBankInfo; fip->language != NULL; fip++) { + if (!strcmp(fip->language, lang)) return fip; + } + DPRINT(("fonbank: language %s not supported\n", lang)); + return NULL; +} + +static XFontStruct ** +lookupCacheFonts(bank, fontset, num_fontsp) +FontBank bank; +char *fontset; +int *num_fontsp; +{ + FontCache *fc; + int i; + int sum; + + sum = getsum(fontset); + fc = bank->hash[sum % FC_HASH_SIZE]; + + /* lookup cache */ + while (fc != NULL) { + if (fc->sum == sum && !strcmp(fc->name, fontset)) { + /* found */ + *num_fontsp = fc->num_fonts; + for (i = 0; i < *num_fontsp; i++) { + (void)CachedLoadFontByFontStruct(bank->dpy, fc->fonts[i]); + } + return fc->fonts; + } + fc = fc->next; + } + *num_fontsp = 0; + return NULL; +} + +static void +cacheFonts(bank, fontset, fonts, num_fonts) +FontBank bank; +char *fontset; +XFontStruct **fonts; +int num_fonts; +{ + FontCache *fc; + int sum; + + fc = XtNew(FontCache); + fontset = XtNewString(fontset); + sum = getsum(fontset); + + fc->sum = sum; + fc->name = fontset; + fc->fonts = fonts; + fc->num_fonts = num_fonts; + fc->next = bank->hash[sum % FC_HASH_SIZE]; + bank->hash[sum % FC_HASH_SIZE] = fc; +} + +static XFontStruct ** +extractFonts(dpy, fontset, charsets, ncharsets, nfontsp) +Display *dpy; +char *fontset; +KICharSet *charsets; +int ncharsets; +int *nfontsp; +{ + KICharSetFont *kifonts; + KICharSetFont buf[10]; + XFontStruct **fonts, **fp; + + if (ncharsets > 10) { + kifonts = (KICharSetFont *)XtMalloc(ncharsets * sizeof(KICharSetFont)); + } else { + kifonts = buf; + } + *nfontsp = ExtractFontsFromFontSet(dpy, fontset, charsets, + kifonts, ncharsets); + fonts = NULL; + if (*nfontsp > 0) { + int i; + + fonts = (XFontStruct **)XtMalloc(*nfontsp * sizeof(XFontStruct *)); + for (i = 0, fp = fonts; i < ncharsets; i++) { + if (kifonts[i].font != NULL) *fp++ = kifonts[i].font; + } + } + if (kifonts != buf) XtFree((char *)kifonts); + return fonts; +} + +static void +freeCache(bank) +FontBank bank; +{ + FontCache *fc; + int i; + + for (i = 0; i < FC_HASH_SIZE; i++) { + fc = bank->hash[i]; + while (fc != NULL) { + FontCache *next = fc->next; + + XtFree(fc->name); + XtFree((char *)fc->fonts); + XtFree((char *)fc); + fc = next; + } + } +} + + +/* + * Public functions + */ + +FontBank +FontBankCreate(dpy, language) +Display *dpy; +char *language; +{ + FontBank fb; + FBInfo *info; + int i; + + TRACE(("FontBankCreate(language:%s)\n", language)); + + if ((info = getInfo(language)) == NULL) return NULL; + + for (fb = fontBankList; fb != NULL; fb = fb->next) { + if (fb->dpy == dpy && fb->info == info) { + TRACE(("\tfontbank for %s already exists\n", language)); + fb->reference_count++; + return fb; + } + } + + TRACE(("\tcreate fontbank for %s...\n", language)); + fb = XtNew(FBRec); + fb->dpy = dpy; + fb->info = info; + fb->reference_count = 1; + for (i = 0; i < FC_HASH_SIZE; i++) { + fb->hash[i] = NULL; + } + fb->next = fontBankList; + fontBankList = fb; + return fb; +} + +void +FontBankDestroy(bank) +FontBank bank; +{ + TRACE(("FontBankDestroy()\n")); + + if (--(bank->reference_count) <= 0) { + FontBank fb, fb0; + + TRACE(("\tfreeing fontbank...\n")); + fb = fontBankList; + fb0 = NULL; + while (fb != NULL) { + if (fb == bank) { + if (fb0 == NULL) { + fontBankList = fb->next; + } else { + fb0->next = fb->next; + } + freeCache(fb); + XtFree((char *)fb); + return; + } + fb0 = fb; + fb = fb->next; + } + } +} + +XFontStruct ** +FontBankGet(bank, fontset, num_fontsp) +FontBank bank; +char *fontset; +int *num_fontsp; +{ + XFontStruct **fpp; + + TRACE(("FontBankGet(fontset:%s)\n", fontset)); + + if ((fpp = lookupCacheFonts(bank, fontset, num_fontsp)) != NULL) { + TRACE(("\tfontset found in fontbank (numfonts=%d)\n", + *num_fontsp)); + return fpp; + } + + fpp = extractFonts(bank->dpy, fontset, bank->info->charsets, + bank->info->num_charsets, num_fontsp); + + /* enter cache */ + TRACE(("\tcaching fontset (numfonts=%d)\n", *num_fontsp)); + cacheFonts(bank, fontset, fpp, *num_fontsp); + return fpp; +} + +void +FontBankFreeFonts(bank, fonts, num_fonts) +FontBank bank; +XFontStruct **fonts; +int num_fonts; +{ + int i; + + TRACE(("FontBankFreeFonts()\n")); + + for (i = 0; i < num_fonts; i++) { + CachedFreeFont(bank->dpy, fonts[i]); + } +}