home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) Stephen Chung, 1991-1993. All rights reserved. */
-
- #include "jwp.h"
-
- #include <math.h>
-
-
- typedef struct fontcache {
- KANJIFONT *font;
- int width, height;
- int size, bmsize;
- int far *indexes;
- BYTE far *bitmaps;
- long int requests, hits, usage;
- struct fontcache far *next, far *prev;
- } FONTCACHE;
-
- static FONTCACHE far *FontCaches; /* Base font always the first */
- static BYTE far *BaseKana = NULL;
- static int BaseKanaSize;
- static long int BaseRequests = 0L, BaseHits = 0L;
-
- static BOOL CacheEnabled = TRUE;
- static BYTE far *CharBitmap = NULL;
-
- #define DEFAULTLEADING (1.0 / 8.0)
- #define DEFAULTSPACING (1.0 / 8.0)
- #define KANASTART 0x2421
- #define KANALENGTH 83
- #define SYSCACHELEN 300
- #define OTHERCACHELEN 100
-
-
-
- static int AdjustBitmapWidth(int bytes)
- {
- int bmwidth;
-
- if (bytes % sizeof(int)) {
- bmwidth = (bytes / sizeof(int)) + 1;
- bmwidth *= sizeof(int);
- } else {
- bmwidth = bytes;
- }
-
- return (bmwidth);
- }
-
-
-
- int AllignKanjiBitmap (BYTE far *buffer, BYTE far *source, int bytes, int lines)
- {
- int i, j, m, n;
- int bmwidth;
-
- bytes /= lines;
-
- bmwidth = AdjustBitmapWidth(bytes);
-
- if (bmwidth == bytes) {
- _fmemcpy(buffer, source, bytes * lines);
- } else {
- for (j = 0; j < lines; j++) {
- m = j * bytes;
- n = j * bmwidth;
-
- for (i = 0; i < bmwidth; i++)
- buffer[n + i] = (i >= bytes) ? 0 : source[m + i];
- }
- }
-
- return (bmwidth * lines);
- }
-
-
-
- int OpenFont(char *fname, KANJIFONT *f)
- {
- int fd;
- FONTHEADER fh;
-
- for (;;) {
- fd = OpenFile(fname, &(f->of), OF_READ);
- if (fd >= 0) break;
- if (!RetryMessage ("Cannot open font file '%s'!", fname)) return (-1);
- }
-
- lseek(fd, 0L, 0);
- read(fd, &fh, sizeof(FONTHEADER));
-
- f->facename = (KANJI *) MemAlloc(NAMELEN);
- kanjicpy(f->facename, fh.facename);
- f->filename = (char *) MemAlloc(strlen(fname) + 5);
- strcpy(f->filename, fname);
-
- f->width = fh.width;
- f->height = fh.height;
- f->bmsize = fh.charsize;
- f->offset = fh.offset;
- f->verticals = fh.verticals;
- f->holes = fh.holes;
-
- f->leading = (fh.leading <= 0) ? (double) f->width * DEFAULTLEADING : fh.leading;
- f->spacing = (fh.spacing <= 0) ? (double) f->height * DEFAULTSPACING : fh.spacing;
-
- return (fd);
- }
-
-
- void EnableFontCache (BOOL On)
- {
- CacheEnabled = On;
-
- if (On) {
- if (CharBitmap != NULL) FreeBlock(CharBitmap);
- CharBitmap = NULL;
- }
- }
-
-
-
- static FONTCACHE far *CreateCache (KANJIFONT *font, int size, int bmsize)
- {
- int i;
- long int block;
- FONTCACHE far *f;
-
- if (FontCaches == NULL) {
- FontCaches = f = StructAlloc(FONTCACHE);
- f->prev = f->next = NULL;
- } else {
- for (f = FontCaches; f->next != NULL; f = f->next);
- f->next = StructAlloc(FONTCACHE);
- f->next->prev = f;
- f = f->next;
- f->next = NULL;
- }
- if (f == NULL) return (NULL);
-
- block = (long int) size * sizeof(int);
- if (block > C64K) { size = C64K / bmsize; block = (long int) size * sizeof(int); }
- f->indexes = (int far *) BlockAlloc(block);
-
- block = (long int) size * (long int) bmsize;
- if (block > C64K) { size = C64K / bmsize; block = (long int) size * (long int) bmsize; }
- f->bitmaps = (BYTE far *) BlockAlloc(block);
-
-
- f->font = font;
- f->width = font->width;
- f->height = font->height;
- f->size = size;
- f->bmsize = bmsize;
- f->requests = f->hits = f->usage = 0L;
-
- for (i = 0; i < size; i++) f->indexes[i] = -1;
- return (f);
- }
-
-
-
- HFONT SelectAsciiFont (HDC hdc, char *facename, double ps, TEXTMETRIC *tmout)
- {
- int size;
- HFONT hfont, oldfont;
- TEXTMETRIC tm;
- char buffer[MAXLINELEN];
-
- size = (int) floor(ps * global.resolution.y / 72.0 + 0.5);
- hfont = CreateFont(-size, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE, facename);
-
- oldfont = SelectObject(hdc, hfont);
- GetTextMetrics(hdc, &tm);
-
- GetTextFace(hdc, MAXLINELEN, buffer);
-
-
- if (stricmp(buffer, facename)) {
- ErrorMessage(global.hwnd, "The font '%s' is not available in this size. The font "
- "'%s' will be used instead.", facename, buffer);
- }
-
- SelectObject(hdc, oldfont);
- if (tmout != NULL) *tmout = tm;
-
- return (hfont);
- }
-
-
-
- HFONT FindMatchingScreenFont (HFONT hfont, double scale, TEXTMETRIC *tmout)
- {
- int size;
- HDC hdc;
- TEXTMETRIC tm;
- HFONT screenfont;
- char buffer[MAXLINELEN];
-
- hdc = GetPrinterDC(TRUE, NULL);
- if (hdc == NULL) hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
-
- SelectObject(hdc, hfont);
- GetTextMetrics(hdc, &tm);
- GetTextFace(hdc, MAXLINELEN, buffer);
- DeleteDC(hdc);
- hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
-
- size = (int) floor((double) (tm.tmHeight - tm.tmInternalLeading) * scale + 0.5);
-
- screenfont = CreateFont(-size, 0, 0, 0, tm.tmWeight,
- tm.tmItalic, tm.tmUnderlined, tm.tmStruckOut,
- tm.tmCharSet, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
- tm.tmPitchAndFamily, buffer);
-
- SelectObject(hdc, screenfont);
- if (tmout != NULL) GetTextMetrics(hdc, tmout);
- GetTextFace(hdc, MAXLINELEN, buffer);
-
- DeleteDC(hdc);
-
- return (screenfont);
- }
-
-
-
- int InitFonts(void)
- {
- int i, fd;
- long int size, kanastart;
- HFONT hfont;
- BYTE charbuf[BUFSIZE];
-
-
- /* The system font should have been opened already */
-
- fd = OpenFile(NULL, &(SYSFONT->of), OF_READ | OF_REOPEN);
- if (fd < 0) {
- ErrorMessage(global.hwnd, "Funny! System font not opened yet!\n\n"
- "Program will die now.");
- exit(-1);
- }
-
- /* Get the adjusted size of a bitmap */
-
- BaseKanaSize = AdjustBitmapWidth(SYSFONT->bmsize / SYSFONT->height) * SYSFONT->height;
-
- /* Create the system kana cache */
-
- size = (long int) KANALENGTH * BaseKanaSize;
-
- if (size < C64K) {
- /* Allocate the kanagana font cache */
- /* #210 for 169 */
-
- BaseKana = (BYTE far *) BlockAlloc(size);
-
- kanastart = Jis2Index(KANASTART, SYSFONT->holes);
-
- for (i = 0; i < KANALENGTH; i++, kanastart++) {
- lseek(fd, kanastart * (long int) SYSFONT->bmsize + SYSFONT->offset, 0);
- read(fd, charbuf, SYSFONT->bmsize);
- AllignKanjiBitmap (&(BaseKana[i * BaseKanaSize]), charbuf, SYSFONT->bmsize, SYSFONT->height);
- }
- }
-
- close(fd);
-
- BaseRequests = BaseHits = 0L;
-
- /* Allocate the system font cache */
-
- FontCaches = NULL;
-
- size = (long int) SYSCACHELEN * BaseKanaSize;
-
- if (size > C64K) size = C64K / BaseKanaSize;
- else size = SYSCACHELEN;
-
- FontCaches = CreateCache (SYSFONT, size, BaseKanaSize);
-
- hfont = CreateFont((int) -floor(DefAsciiFont.size * global.resolution.y / 72.0 + 0.5),
- 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE, DefAsciiFont.facename);
-
- DefAsciiFont.hfont =
- FindMatchingScreenFont(hfont, global.dispscale / global.printscale,
- &(DefAsciiFont.textmetric));
- DeleteObject(hfont);
-
- FontCharWidth(0, -2); /* Load the width tables */
- return (1);
- }
-
-
- static int FontHash (int index, int bins)
- {
- return (index % bins);
- }
-
-
-
- BOOL IsSmallKana(KANJI jiscode)
- {
- BYTE hi, lo;
-
- hi = HIBYTE(jiscode) & 0x7f;
- lo = LOBYTE(jiscode) & 0x7f;
-
- if (hi == 0x24 || hi == 0x25) { /* Hiragana & Katakana */
-
- switch (lo) {
- case 0x21: /* a */
- case 0x23: /* i */
- case 0x25: /* u */
- case 0x27: /* e */
- case 0x29: /* o */
- case 0x63: /* ya */
- case 0x65: /* yu */
- case 0x67: /* yo */
- case 0x43: /* tu */
- return (TRUE);
-
- default:
- return (FALSE);
- }
-
- } else if (hi == 0x21) {
-
- switch (lo) {
- case 0x22: /* , */
- case 0x23: /* . */
- case 0x57: /* ' */
- case 0x59: /* '' */
- return (TRUE);
-
- default:
- return (FALSE);
- }
-
- }
-
- return (FALSE);
- }
-
-
- /* The following routine came from KD, the Kanji Driver program */
- /* written by Izumi Ozawa. It was reformatted and slightly */
- /* modified. Many thanks to Izumi for his donation. */
-
- int Jis2Index (KANJI jiscode, BOOL holes)
- {
- LONG hi, lo;
-
- hi = HIBYTE(jiscode) & 0x007f;
- lo = LOBYTE(jiscode) & 0x007f;
-
-
- if (lo <= 0x20 || lo >= 0x7f || hi <= 0x20 || hi >= 0x74)
- return (-1);
-
- hi = 94 * (hi - 33) + (lo - 33);
-
- if (holes) return (hi);
-
-
- /* Skip the holes */
-
- if (hi <= 107)
- return (hi); /* 0..93 $2121-$217e, 0 -93 */
- /* 94..107 $2221-$222e, 94 -107 */
- else if (hi >= 203 && hi <= 212)
- return (hi - 56); /* 203..212 0 .. 9, $2330-$2339, 147-156 */
- else if (hi >= 220 && hi <= 245)
- return (hi - 63); /* 220..245 A .. Z, $2341-$235a, 157-182 */
- else if (hi >= 252 && hi <= 277)
- return (hi - 69); /* 252..277 a .. z, $2361-$237a, 183-208 */
- else if (hi >= 282 && hi <= 364)
- return (hi - 73); /* 282..364 hiragana, $2421-$2473, 209-291 */
- else if (hi >= 376 && hi <= 461)
- return (hi - 84); /* 376..461 katakana, $2521-$2576, 292-377 */
- else if (hi >= 470 && hi <= 493)
- return (hi - 92); /* 470..493 GREEK, $2621-$2638, 378-401 */
- else if (hi >= 502 && hi <= 525)
- return (hi - 100); /* 502..525 greek, $2641-$2658, 402-425 */
- else if (hi >= 564 && hi <= 596)
- return (hi - 138); /* 564..596 RUSSIAN, $2721-$2741, 426-458 */
- else if (hi >= 612 && hi <= 644)
- return (hi - 153); /* 612..644 russian, $2751-$2771, 459-491 */
- /* n/a linedraw, n/a , 492-523 */
- else if (hi >= 1410 && hi <= 4374)
- return (hi - 886); /* 1410..4374 kanji-1, $3021-$4f53, 524-3488 */
- else if (hi >= 4418 && hi <= 7805)
- return (hi - 928); /* 4418..7805 kanji-2, $5021-$737e, 3490-6877 */
-
- /* No such kanji */
-
- return (-1);
- }
-
-
-
- int GetKanjiBitmap (KANJIFONT *font, int index, BYTE far * *bitsbuffer)
- {
- int fd, i, j, k;
- long int size, kanastart;
- FONTCACHE far *f;
- BYTE charbuf[BUFSIZE];
-
- if (BaseKana != NULL && font == SYSFONT) {
- /* Kana's? */
- kanastart = Jis2Index(KANASTART, font->holes);
- if (index >= kanastart && index < kanastart + KANALENGTH) {
- BaseRequests++;
- BaseHits++;
- *bitsbuffer = &(BaseKana[(index - kanastart) * BaseKanaSize]);
- return (BaseKanaSize);
- }
- }
-
- /* Is the font cached? */
-
- for (f = FontCaches; f != NULL; f = f->next) {
- if (f->font == font) break;
- }
- if (f != NULL) {
- i = FontHash(index, f->size);
- for (j = i; ;) {
- k = f->indexes[j]; /* The cached value */
-
- if (k < 0) break;
- //if (FontHash(k, f->size) != i) break;
-
- if (k == index) { /* Found it! */
- f->requests++;
- f->hits++;
- *bitsbuffer = &(f->bitmaps[f->bmsize * j]);
- return (f->bmsize);
- }
- if (++j >= f->size) j = 0; /* Wrap around */
- if (j == i) break; /* Complete cycle */
- }
- }
-
- if (CacheEnabled) {
- /* Put it in the cache! */
-
- if (f == NULL && CacheEnabled) {
- i = AdjustBitmapWidth(font->bmsize / font->height) * font->height;
- size = (long int) OTHERCACHELEN * i;
-
- if (size > C64K) size = C64K / i;
- else size = OTHERCACHELEN;
-
- f = CreateCache (font, size, i);
- }
-
- if (f == NULL) {
- *bitsbuffer = NULL;
- return (0);
- }
-
- i = FontHash (index, f->size);
-
- for (j = i; ;) {
- if (f->indexes[j] < 0) break;
- if (++j >= f->size) j = 0; /* Wrap around */
- if (j == i) { /* Complete cycle */
- j = rand() % f->size; /* Bump out a random one */
- break;
- }
- }
-
- if (f->indexes[j] < 0) f->usage++;
-
- f->indexes[j] = index;
-
- f->requests++;
- }
-
- fd = OpenFile(NULL, &(font->of), OF_READ | OF_REOPEN);
- lseek(fd, (long int) index * (long int) font->bmsize + font->offset, 0);
- read(fd, charbuf, font->bmsize);
- close(fd);
-
- if (CacheEnabled) {
- AllignKanjiBitmap (&(f->bitmaps[f->bmsize * j]), charbuf, font->bmsize, font->height);
-
- *bitsbuffer = &(f->bitmaps[f->bmsize * j]);
-
- return (f->bmsize);
- } else {
- if (CharBitmap == NULL) CharBitmap = (BYTE far *) BlockAlloc(BUFSIZE);
-
- i = AllignKanjiBitmap (CharBitmap, charbuf, font->bmsize, font->height);
-
- *bitsbuffer = CharBitmap;
-
- return (i);
- }
- }
-
-
- void DisplayKanjiBitmap(HDC hdc, int x, int y, int width, int height, int size,
- DWORD style, BYTE far *bits)
- {
- HDC hdcmem;
- static HANDLE hbitmap = NULL;
- static lastwidth = 0, lastheight = 0;
-
- /* size = -1 means deallocate */
-
- if (size < 0) {
- if (hbitmap != NULL) DeleteObject(hbitmap);
- return;
- }
-
-
- /* Do we need to allocate a new bitmap? */
-
- if (width != lastwidth || height != lastheight) {
- if (hbitmap != NULL) DeleteObject(hbitmap);
- hbitmap = NULL;
- lastwidth = width;
- lastheight = height;
- }
- if (hbitmap == NULL) {
- hbitmap = CreateBitmap(width, height, 1, 1, bits);
- } else {
- SetBitmapBits(hbitmap, (DWORD) size, bits);
- }
-
- hdcmem = CreateCompatibleDC(hdc);
- SelectObject(hdcmem, hbitmap);
- SetMapMode(hdcmem, GetMapMode(hdc));
- BitBlt(hdc, x, y - height, width, height, hdcmem, 0, 0, style);
- DeleteDC(hdcmem);
- }
-
-
- void FontCacheStatistics (int *num, long int *usage, long int *requests, long int *hits)
- {
- FONTCACHE far *f;
-
- *requests = 0L;
- *hits = 0L;
- *usage = 0L;
-
- for (*num = 0, f = FontCaches; f != NULL; f = f->next, (*num)++) {
- *requests += f->requests;
- *hits += f->hits;
- *usage += f->usage;
- }
- }
-