/* * VF_Zeit.c * * Programmmed by Hirotsugu Kakugawa, Hiroshima University * E-Mail: h.kakugawa@computer.org * * Edition History * 2 Nov 1993 * 3 Nov 1993 Added sl, rx, ry, ox, oy, fx, fy capabilities. * 4 Nov 1993 Added ro capability. * 29 Dec 1993 Added VF_GetOutline(), VF_FreeOutline(). * 16 Jan 1994 New implementation of Syotai Club Font access routines. * 17 Jan 1994 New implementation of GetBitmap(),GetOutline(),DrawOutline() * 20 Jan 1994 Added GetOutline2(). * 21 Jan 1994 Modified low level interface routines to syotai club font. * 22 Jan 1994 Improved TraceOutline() and FillEdges(). * 8 Mar 1994 Fixed small bugs and removed dead code * 11 Mar 1994 Changed draw routine. * 3 Sep 1994 Changed type declaration of ConvXY() * 3 Feb 1995 Bug fix to the (0,0) point in asiya24 font by Ito Tadashi * 3 Feb 1995 Bug fix for left slant conversion. * 3 Apr 1995 Fixed memory leak. * 6 May 1995 Dynamic Opening/Closing font file feature by H.Kakugawa. * 23 May 1995 Added range checking of char code. * 20 Nov 1995 Added return value checking of ZeitOpenFont() in OpenFont(). */ /* This is a part of VFlib * * Copyright (C) 1993-1998 Hirotsugu KAKUGAWA. All rights reserved. * * This file is part of the VFlib Library. This library is free * software; you can redistribute it and/or modify it under the terms of * the GNU Library General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your * option) any later version. This library 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 Library General Public License for more details. * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Capabilities interpretable by zeit font objects: "ff" (str) -- Font file path (THIS IS NECESSARY) "fr" (bool) -- Frame font if defined "th" (bool) -- Thicken the char if defined "ro" (num) -- Rotate the char 90*n degree in clockwise "rx" (bool) -- Reflect about x-axis if defined "ry" (bool) -- Reflect about y-axis if defined "sl" (num) -- Slant the char n/100 Corrrection Factors: "ox" (num) -- Offset for x-axis for vector font data (moved negative dir) "oy" (num) -- Offset for y-axis for vector font data (moved negative dir) "fx" (num) -- Factor for x-axis for vector font data "fy" (num) -- Factor for x-axis for vector font data Each point p0=(x0,y0) of vector font data is transformed in the following order: 1. adding `offset' : (x1,y1)=(x0-x_offset, y0-y_offset) 2. magnification by `factor': (x2,y2)=(x1*x_factor, y2*y_factor) 3. computation of the slant 3. rotation in clockwise direction 4. reflection about x-axis 5. reflection about y-axis */ #include #include #include #include #include "config.h" #include "defs.h" #include "_VF.h" #include "VF.h" #include "VFcap.h" #define ZEIT_MAX_VALUE 0x0400 #define ZEIT_CODE_SIZE 0x1142 #define ZEIT_HEADER_SIZE (2+4*ZEIT_CODE_SIZE) #define CONV_X(x) \ ((unsigned int)(OUTLINE_OFFSET+((long)(x)*OUTLINE_SIZE)/ZEIT_MAX_VALUE)) #define CONV_Y(y) \ ((unsigned int)(OUTLINE_OFFSET+((long)(y)*OUTLINE_SIZE)/ZEIT_MAX_VALUE)) #define UNCONV_X(x) \ ((unsigned int)(ZEIT_MAX_VALUE*((long)(x)-OUTLINE_OFFSET))/OUTLINE_SIZE) #define UNCONV_Y(y) \ ((unsigned int)(ZEIT_MAX_VALUE*((long)(y)-OUTLINE_OFFSET))/OUTLINE_SIZE) #define END_XY VFD_MAKE_XY(1023, 1023) #define STATIC static /* Font */ struct s_font { int PrimFont; char *FontFileName; /* ff */ int Frame; /* fr */ int Thicken; /* th */ int Rotate; /* ro */ int XReflect; /* rx */ int YReflect; /* ry */ int Slant; /* sl */ int Xoffset; /* zxo */ int Yoffset; /* zyo */ int Xfactor; /* zxf */ int Yfactor; /* zyf */ double MatT1, MatT2, MatT3, MatT4, MatT5, MatT6; }; typedef struct s_font Font; Private int OpenFont(); Private int CloseFont(); Private int GetBitmap(); Private long *GetOutline(); Private long *GetOutline2(); Private int DrawOutline(); Private int FreeOutline(); Private int Link(); Private int Unlink(); int VF_Draw(); Private int ReadCapa(); Private int ZeitOpenFont(); Private int ZeitCloseFont(); Private long* ZeitReadOutline(); Private long* ZeitReadOutline(); Private int jis2c(); Private void ConvXY(); Private int ReadHeader(); Private void InitBitStream(); Private unsigned long Read4Bytes(); Private int Read1Byte(); Private int Read10Bits(); Private int CorrectSize(); Private void Seek(); Private long CurrentPos(); Public FontObj* CreateFont_Zeit(ent) char *ent; { Font *font; FontObj *fobj; if ((font = (Font*) malloc(sizeof(Font))) == NULL) return NULL; /* ERR: malloc err */ font->PrimFont = -1; if (ReadCapa(font, ent) < 0){ free(font); return NULL; } fobj = (FontObj*) malloc(sizeof(FontObj)); fobj->ClassID = VF_FONT_ZEIT; fobj->Self = fobj; fobj->LinkCount = 0; fobj->OpenFont = OpenFont; fobj->CloseFont = CloseFont; fobj->GetBitmap = GetBitmap; fobj->GetOutline = GetOutline; fobj->GetOutline2 = GetOutline2; fobj->DrawOutline = DrawOutline; fobj->FreeOutline = FreeOutline; fobj->GetCharSet = NULL; fobj->GetEnc = NULL; fobj->Link = Link; fobj->Unlink = Unlink; fobj->Locals = (long) font; return fobj; } Private int OpenFont(fobj) FontObj *fobj; { Font *font; font = (Font*) fobj->Locals; font->PrimFont = ZeitOpenFont(font->FontFileName); if (font->PrimFont < 0) return -1; return 0; } Private int CloseFont(fobj) FontObj *fobj; { int val; Font *font; font = (Font*) fobj->Locals; val = ZeitCloseFont(font->PrimFont); free(font->FontFileName); free((char*)fobj->Locals); free(fobj); return val; } Private int GetBitmap(obj, jiscode, w, h, bw, bo, bm_buf) FontObj *obj; int jiscode; int w; int h; int bw; int bo; char *bm_buf; { int val; long *vfdata; if ((vfdata = GetOutline(obj, jiscode)) == NULL) return -1; val = DrawOutline(obj, vfdata, w, h, bw, bo, bm_buf); FreeOutline(obj, vfdata); return val; } Private long* GetOutline(obj, jiscode) FontObj *obj; int jiscode; { Font *font; int id, x, y; long *outline, *ptr; font = (Font*) obj->Locals; id = font->PrimFont; if ((outline = ZeitReadOutline(2, jiscode, id)) == NULL) return NULL; outline[0] = jiscode; outline[1] = VF_SONY_COORDINATES; for (ptr = &outline[2]; *ptr != END_XY; ptr++){ if ((*ptr & VFD_TOKEN) == VFD_TOKEN) continue; ConvXY(&x, &y, (int)VFD_GET_X(*ptr), (int)VFD_GET_Y(*ptr), font); *ptr = VFD_MAKE_XY(CONV_X(x), CONV_Y(y)); } *ptr = 0L; return outline; } Private long* GetOutline2(obj, jiscode) FontObj *obj; int jiscode; { Font *font; int id, x, y; long *outline, *ptr; font = (Font*) obj->Locals; id = font->PrimFont; if ((outline = (long*) ZeitReadOutline(2, jiscode, id)) == NULL) return NULL; outline[0] = jiscode; outline[1] = VF_ZEIT_COORDINATES; for (ptr = &outline[2]; *ptr != END_XY; ptr++){ if ((*ptr & VFD_TOKEN) == VFD_TOKEN) continue; ConvXY(&x, &y, (int)VFD_GET_X(*ptr), (int)VFD_GET_Y(*ptr), font); *ptr = VFD_MAKE_XY(x, y); } *ptr = 0L; return outline; } Private int DrawOutline(obj, vfdata, w, h, bw, bo, bm_buf) FontObj *obj; long *vfdata; int w; int h; int bw; int bo; char *bm_buf; { Font *font; unsigned char *buff, d; int rast, x, y, yy1, yy2, val, frame; int thin; font = (Font*) obj->Locals; rast = (w+7)/8; if ((buff = (unsigned char*) malloc(h*rast)) == NULL) return -1; /* ERR: malloc err */ bzero(buff, rast*h); switch (font->Thicken){ case 1: thin = 30; break; case 0: default: thin = 0; break; } switch (font->Frame){ case 1: frame = 1; break; case 0: default: frame = 0; break; } if ((val = VF_Draw(vfdata, w, h, rast, buff, thin, frame)) < 0){ free(buff); return -1; } yy1 = 0; yy2 = 0; for (y = 0; y < h; y++){ for (x = 0; x < rast; x++){ d = buff[yy2 + x]; bm_buf[yy1 + x] |= d >> bo; bm_buf[yy1 + x+1] |= d << (8-bo); } yy1 += bw; yy2 += rast; } free(buff); return 0; } Private int FreeOutline(obj, vfdata) FontObj *obj; long *vfdata; { free((char*) vfdata); return 0; } Private int Link(obj) FontObj *obj; { obj->LinkCount = obj->LinkCount + 1; return obj->LinkCount; } Private int Unlink(obj) FontObj *obj; { obj->LinkCount = obj->LinkCount - 1; return obj->LinkCount; } Private int ReadCapa(font, ent) Font *font; char *ent; { char *p; double sl; font->Thicken = 0; font->Frame = 0; font->Slant = 0; font->Rotate = 0; font->XReflect = 0; font->YReflect = 0; font->Xoffset = 0; font->Yoffset = 0; font->Xfactor = 100; font->Yfactor = 100; VFC_GetEntry(ent); if (VFC_IsDefined(VFCE_THICKEN)) font->Thicken = 1; if (VFC_IsDefined(VFCE_FRAME)) font->Frame = 1; if ((font->Slant = VFC_GetNumber(VFCE_SLANT)) == -1) font->Slant = 0; sl = font->Slant/100.0; if (sl < 0.0){ font->MatT1 = 1.0+sl; font->MatT2 = -sl; font->MatT3 = 0.0; /*font->MatT1 = 1.0+sl; font->MatT2 = -sl; font->MatT3 = sl;*/ font->MatT4 = 0.0; font->MatT5 = 1.0; font->MatT6 = 0.0; } else { font->MatT1 = 1.0-sl; font->MatT2 = -sl; font->MatT3 = sl; font->MatT4 = 0.0; font->MatT5 = 1.0; font->MatT6 = 0.0; } if ((font->Rotate = VFC_GetNumber(VFCE_ROTATE)) == -1) font->Rotate = 0; if (VFC_IsDefined(VFCE_REF_X)) font->XReflect = 1; if (VFC_IsDefined(VFCE_REF_Y)) font->YReflect = 1; if ((font->Xoffset = VFC_GetNumber(VFCE_XOFFSET)) == -1) font->Xoffset = 0; if ((font->Yoffset = VFC_GetNumber(VFCE_YOFFSET)) == -1) font->Yoffset = 0; if ((font->Xfactor = VFC_GetNumber(VFCE_XFACTOR)) == -1) font->Xfactor = 100; if ((font->Yfactor = VFC_GetNumber(VFCE_YFACTOR)) == -1) font->Yfactor = 100; font->FontFileName = NULL; if ((p = VFC_GetString(VFCE_FONT_FILE)) == NULL) return -1; if ((font->FontFileName = malloc(strlen(p)+1)) == NULL) return -1; /* ERR: malloc err */ strcpy(font->FontFileName, p); return 0; } Private void ConvXY(xp, yp, x, y, fobj) int *xp, *yp, x, y; Font *fobj; { double tmp_x, tmp_y, xfact, yfact; int xx, yy, xxx, yyy; xfact = (double)(fobj->Xfactor)/100.0; yfact = (double)(fobj->Yfactor)/100.0; tmp_x = (double) (xfact*(x-(fobj->Xoffset))); tmp_y = (double) (yfact*(y-(fobj->Yoffset))); tmp_x = (((double)tmp_x*(fobj->MatT1)) + ((double)tmp_y*(fobj->MatT2)) + ((double) ZEIT_MAX_VALUE)*(fobj->MatT3)); tmp_y = (((double)tmp_x*(fobj->MatT4)) + ((double)tmp_y*(fobj->MatT5)) + ((double) ZEIT_MAX_VALUE)*(fobj->MatT6)); xxx = (int) tmp_x; yyy = (int) tmp_y; switch (fobj->Rotate % 4){ default: case 0: xx = xxx; yy = yyy; break; case 1: xx = ZEIT_MAX_VALUE-1 - yyy; yy = xxx; break; case 2: xx = ZEIT_MAX_VALUE-1 - xxx; yy = ZEIT_MAX_VALUE-1 - yyy; break; case 3: xx = yyy; yy = ZEIT_MAX_VALUE-1 - xxx; break; } if (fobj->XReflect != 0) xx = ZEIT_MAX_VALUE-1 - xx; if (fobj->YReflect != 0) yy = ZEIT_MAX_VALUE-1 - yy; if (xx < 0) xx = 0; if (yy < 0) yy = 0; if (xx >= ZEIT_MAX_VALUE) xx = ZEIT_MAX_VALUE-1; if (yy >= ZEIT_MAX_VALUE) yy = ZEIT_MAX_VALUE-1; *xp = xx; *yp = yy; } /*** *** LOW LEVEL INTERFACE ROUTINES FOR SYOTAI CLUB FONTS *** BY HIROTSUGU KAKUGAWA 1994 ***/ typedef struct { long Offset[ZEIT_CODE_SIZE]; long Size[ZEIT_CODE_SIZE]; } Header; struct prim_font { FILE_Port Fd1; /* Free if NULL_PORT */ Header *Header1; FILE_Port Fd2; Header *Header2; int LinkCount; char *FontFileName; /* ff */ }; typedef struct prim_font PrimFont; static PrimFont PrimFontTable[VF_MAX_ZEIT_FONTS]; #define THRESHOLD_SIZE 0x1000 /* OPEN THE FONT */ Private int ZeitOpenFont(font) char *font; { int id; char *fn; Private int inited = 0; if (inited == 0){ for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){ PrimFontTable[id].Fd1 = NULL_PORT; PrimFontTable[id].Header1 = NULL; PrimFontTable[id].Fd2 = NULL_PORT; PrimFontTable[id].Header2 = NULL; PrimFontTable[id].LinkCount = 0; PrimFontTable[id].FontFileName = NULL; } inited = 1; } for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){ /* linear search is sufficient since # of items is small */ if ((PrimFontTable[id].Fd1 != NULL_PORT) && (strcmp(PrimFontTable[id].FontFileName, font) == 0)){ PrimFontTable[id].LinkCount++; return id; } } for (id = 0; id < VF_MAX_ZEIT_FONTS; id++){ if (PrimFontTable[id].Fd1 == NULL_PORT) break; } if (id == VF_MAX_ZEIT_FONTS) return -1; /* full */ if ((PrimFontTable[id].FontFileName = malloc(strlen(font)+1)) == NULL) return -1; /* ERR: malloc err */ strcpy(PrimFontTable[id].FontFileName, font); fn = malloc(strlen(font)+5); if (fn == NULL) exit(1); sprintf(fn, "%s.vf1", font); if ((PrimFontTable[id].Fd1 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT) return -1; PrimFontTable[id].Header1 = (Header*) malloc(sizeof(Header)); if (PrimFontTable[id].Header1 == NULL) exit(1); ReadHeader(PrimFontTable[id].Fd1, PrimFontTable[id].Header1, 0); sprintf(fn, "%s.vf2", font); if ((PrimFontTable[id].Fd2 = VFFM_Intern(fn, NULL, NULL)) == NULL_PORT) return -1; PrimFontTable[id].Header2 = (Header*) malloc(sizeof(Header)); if (PrimFontTable[id].Header2 == NULL) exit(1); ReadHeader(PrimFontTable[id].Fd2, PrimFontTable[id].Header2, 1); free(fn); return id; } /* CLOSE THE FONT */ Private int ZeitCloseFont(id) int id; { if ((--PrimFontTable[id].LinkCount) <= 0){ VFFM_UnIntern(PrimFontTable[id].Fd1); PrimFontTable[id].Fd1 = NULL_PORT; VFFM_UnIntern(PrimFontTable[id].Fd2); PrimFontTable[id].Fd2 = NULL_PORT; free(PrimFontTable[id].Header1); free(PrimFontTable[id].Header2); free(PrimFontTable[id].FontFileName); } return PrimFontTable[id].LinkCount; } /* READ FONT HEADER */ Private int ReadHeader(port, hd, b) FILE_Port port; Header *hd; int b; { int i, j; FILE *fp; fp = VFFM_FStream(port); fseek(fp, 0L, 0); (void) Read1Byte(fp); (void) Read1Byte(fp); for (i = 0; i < ZEIT_CODE_SIZE; i++){ hd->Offset[i] = Read4Bytes(fp); /*printf("Ch %04x Offs %04x\n", c2jis(b, i), hd->Offset[i]);*/ } for (i = 0; i < ZEIT_CODE_SIZE-1; i++){ if (hd->Offset[i] == 0xffffffff){ hd->Size[i] = 0; } else { for (j = i+1; ; j++){ if (j >= ZEIT_CODE_SIZE){ hd->Size[i] = -(THRESHOLD_SIZE+1); break; } if (hd->Offset[j] != 0xffffffff){ hd->Size[i] = -(hd->Offset[j] - hd->Offset[i]); break; } } if (-(hd->Size[i]) > THRESHOLD_SIZE) CorrectSize(i, fp, hd); /* TOO LARGE. IS THE SIZE CORRECT? */ /*printf("Ch %04x Offs %04x Size %04x\n", c2jis(b, i), hd->Offset[i], -(hd->Size[i]));*/ } } if (hd->Offset[ZEIT_CODE_SIZE-1] == 0xffffffff){ hd->Size[ZEIT_CODE_SIZE-1] = 0; } else { hd->Size[ZEIT_CODE_SIZE-1] = -(THRESHOLD_SIZE+1); CorrectSize(ZEIT_CODE_SIZE-1, fp, hd); } return 0; } /* CORRECT THE SIZE OF FONT DATA */ Private int CorrectSize(i, fp, hd) int i; FILE *fp; Header *hd; { int x, y; /*printf("Too Large for %04x\n Size:%04x \n", i, -(hd->Size[i]));*/ Seek(fp, hd->Offset[i]); InitBitStream(fp); for (;;){ x = Read10Bits(fp); y = Read10Bits(fp); /*printf(" x,y = %04d, %04d\n", x, y);*/ if ((x == 1023) && (y == 1023)) break; for (;;){ x = Read10Bits(fp); y = Read10Bits(fp); /*printf(" x,y = %04d, %04d\n", x, y);*/ if ((x == 1023) && (y == 1023)) break; } } hd->Size[i] = -(CurrentPos(fp) - hd->Offset[i]); /*printf("--> %04x\n", -(hd->Size[i]));*/ return hd->Size[i]; } /* GET OUTLINE DATA (IN ZEIT COORDINATES) */ Private long* ZeitReadOutline(offset, jiscode, id) int offset, jiscode, id; { FILE_Port port; FILE *fp; int cnt, idx, x, y; long *outline, *sizep, size, chd; unsigned int scode; long offs; if (jiscode == 0x2121){ if ((outline = (long*) malloc((int)(1+offset)*sizeof(long))) == NULL) return NULL; outline[offset] = END_XY; return outline; } if ((0x2122 <= jiscode) && (jiscode <= 0x7424)){ scode = jis2c(jiscode); if (jiscode < 0x5000){ port = PrimFontTable[id].Fd1; offs = PrimFontTable[id].Header1->Offset[scode]; sizep = &PrimFontTable[id].Header1->Size[scode]; } else { port = PrimFontTable[id].Fd2; offs = PrimFontTable[id].Header2->Offset[scode]; sizep = &PrimFontTable[id].Header2->Size[scode]; } } else { return NULL; } if (*sizep == 0L) return NULL; if (*sizep < 0L) size = -2*(*sizep) + 2; /* this is enough ... */ else size = *sizep; /* printf(" OUTLINE SIZE %5Ld\n", *sizep); printf(" ALLOCED %5Ld\n", size); */ if ((outline = (long*) malloc((int)(size+offset)*sizeof(long))) == NULL) return NULL; cnt = 0; idx = offset; fp = VFFM_FStream(port); Seek(fp, offs); InitBitStream(fp); chd = VFD_CHAR; for (;;){ x = Read10Bits(fp); y = Read10Bits(fp); if ((x == 1023) && (y == 1023)){ outline[idx++] = END_XY; /* END */ cnt++; break; } else { outline[idx++] = (chd | VFD_CWCURV | VFD_LINE); /* START */ outline[idx++] = VFD_MAKE_XY(x, y); /* X,Y */ cnt += 2; chd = 0L; } for (;;){ x = Read10Bits(fp); y = Read10Bits(fp); if ((x == 1023) && (y == 1023)) break; else { outline[idx++] = VFD_MAKE_XY(x, y); /* POINT */ cnt++; } } } if (*sizep < 0) *sizep = (long) cnt; /* printf(" SIZE %5Ld\n", *sizep); */ return outline; } Private int jis2c(jis) int jis; { if (jis < 0x5000) return (((jis >> 8) & 0xff) - 0x21) * 0x5e + (jis & 0xff) - 0x21; else return (((jis >> 8) & 0xff) - 0x50) * 0x5e + (jis & 0xff) - 0x21; } /* READ 1 BYTE INTEGER */ Private int Read1Byte(fp) FILE *fp; { return fgetc(fp); } /* READ 4 BYTE INTEGER */ Private unsigned long Read4Bytes(fp) FILE *fp; { unsigned long i1, i2, i3, i4; i1 = (unsigned long) Read1Byte(fp); i2 = (unsigned long) Read1Byte(fp); i3 = (unsigned long) Read1Byte(fp); i4 = (unsigned long) Read1Byte(fp); return i1 + i2*0x100 + i3*0x10000 + i4*0x1000000; } Private unsigned int LeftBits = 0; Private unsigned long BitStream = 0; Private unsigned long Power2Tbl[] = { 0x000001,0x000002,0x000004,0x000008,0x000010,0x000020,0x000040,0x000080, 0x000100,0x000200,0x000400,0x000800,0x001000,0x002000,0x004000,0x008000, 0x010000,0x020000,0x040000,0x080000,0x100000,0x200000,0x400000,0x800000 }; /* INIT BIT STREAM */ Private void InitBitStream(fp) FILE *fp; { BitStream = 0; LeftBits = 0; } /* READ 10 BITS INTEGER FROM BIT STREAM */ Private int Read10Bits(fp) FILE *fp; { if (LeftBits < 10){ BitStream *= 0x10000; BitStream += (unsigned int) Read1Byte(fp); BitStream += (unsigned int) Read1Byte(fp) * 0x0100; LeftBits += 16; } LeftBits -= 10; return (BitStream/Power2Tbl[LeftBits]) % ZEIT_MAX_VALUE; } /* SEEK TO THE OFFSET FOR FONT DATA */ Private void Seek(fp, l) FILE *fp; long l; { fseek(fp, l + ZEIT_HEADER_SIZE, 0); } /* RETURN CURRENT OFFSET FOR FONT DATA */ Private long CurrentPos(fp) FILE *fp; { return ftell(fp) - ZEIT_HEADER_SIZE; } /* EOF */