/* * VF_Hbf.c * * Programmmed by Werner Lemberg * E-Mail: a7621gac@awiuni11.bitnet * * Edition History * 1 Apr 1996 First version. */ /* * Use bitmap font in HBF format. * This font driver also generates outline data from bitmaps. * Quality is poor since the source is a bitmap font, but * you can get the font files for free! * * This module assumes that all characters in a font file have the * same size; variable width fonts are not supported. * * This code is heavily based on VF_Bdf.c . */ /* This file is part of VFlib * * Copyright (C) 1995-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 HBF objects: "ff" (str) -- Font file path (THIS IS NECESSARY) "en" (str) -- Font encoding (optional). If defined, encoding must be identical with the value in the HBF header file. "cs" (str) -- Font character set (optional). If defined, character set must be identical with the value in the HBF header file. "dz" (num) -- Dot size factor for each dot. 0(small)...100(full) "ds" (str) -- Shape of dots. "square" (default) or "diamond" "ro" (num) -- Rotate the char 90*n degrees in clockwise direction "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 (will be subtracted) "oy" (num) -- Offset for y-axis for vector font data (will be subtracted) "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. subtraction of `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" #include "VFenc.h" #include "hbf.h" #define DOT_SHAPE_SQUARE 0 #define DOT_SHAPE_DIAMOND 1 #define HBF_SUFFIX ".hbf" struct s_font { int hbf_id; /* capabilities */ char *Filename; /* ff */ int Encoding; /* en */ int CharSet; /* cs */ int Rotate; /* ro */ int DotSizeFactor; /* dz */ int DotShape; /* ds */ int XReflect; /* rx */ int YReflect; /* ry */ int Slant; /* sl */ int Xoffset; /* xo */ int Yoffset; /* yo */ int Xfactor; /* xf */ int Yfactor; /* yf */ }; typedef struct s_font Font; #define OL_RANGE 32768 #define OL_SIZE 8192 #define OL_OFFSET ((OL_RANGE - OL_SIZE) / 2) struct s_hbf { int link_count; HBF *port; int hbf_enc; int hbf_chset; int hbf_width; int hbf_height; char *hbf_filename; unsigned char *hbf_bmbuf; /* will be allocated by hbfGetBitmap() */ int hbf_bmrast; int hbf_nchar; }; typedef struct s_hbf hbf; Private hbf *hbf_table[VF_MAX_HBF_FONTS]; Private int OpenFont(); Private void Transformation(); Private int CloseFont(); Private int GetBitmap(); Private long* GetOutline(); Private long* GetOutline2(); Private int DrawOutline(); Private int FreeOutline(); Private int Link(); Private int Unlink(); Private int GetEnc(); Private int GetCharSet(); Private int ReadCapa(); int VF_Draw(); Private int HBF_Open(); Private int HBF_Close(); Private unsigned char* HBF_ReadBitmap(); Private long *HBF_GetOutline(); Public FontObj* CreateFont_Hbf(ent) char *ent; { Font *font; FontObj *fobj; if ((font = (Font*) malloc(sizeof(Font))) == NULL) return NULL; /* ERR: malloc err */ if (ReadCapa(font, ent) < 0){ free(font); return NULL; } fobj = (FontObj*) malloc(sizeof(FontObj)); fobj->ClassID = VF_FONT_HBF; 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->Link = Link; fobj->Unlink = Unlink; fobj->GetEnc = GetEnc; fobj->GetCharSet = GetCharSet; fobj->Locals = (long) font; return fobj; } Private int OpenFont(obj) FontObj *obj; { int id; Font *fobj; fobj = (Font*) obj->Locals; if ((id = HBF_Open(fobj->Filename)) < 0) return -1; /* check whether the character set value in vfontcap is the same as the value in the HBF header file. The encoding value of vfontcap (if specified) will always override the default value derived from the character set in the HBF header since the HBF format don't specify an extra encoding parameter. */ if (fobj->Encoding == 0) fobj->Encoding = hbf_table[id]->hbf_enc; if (fobj->CharSet == 0) fobj->CharSet = hbf_table[id]->hbf_chset; else if (fobj->CharSet != hbf_table[id]->hbf_chset) return -1; /* ERR: character set mismatch */ fobj->hbf_id = id; return 0; } Private int CloseFont(obj, fid) FontObj *obj; int fid; { int id; Font *fobj; fobj = (Font*) obj->Locals; if ((id = HBF_Close(fobj->hbf_id)) < 0) return -1; return 0; } Private int GetBitmap(obj, CJKcode, w, h, bw, bo, bm_buf) FontObj *obj; int CJKcode; int w; int h; int bw; int bo; char *bm_buf; { int val; long *vfdata; if ((vfdata = GetOutline(obj, CJKcode)) == NULL) return -1; val = DrawOutline(obj, vfdata, w, h, bw, bo, bm_buf); FreeOutline(obj, vfdata); return val; } Private long* GetOutline(obj, CJKcode) FontObj *obj; int CJKcode; { long *outline; Font *fobj; fobj = (Font*) obj->Locals; if ((outline = HBF_GetOutline(fobj, fobj->hbf_id, CJKcode)) == NULL) return NULL; Transformation(&outline[2], fobj); return outline; } Private long* GetOutline2(obj, CJKcode) FontObj *obj; int CJKcode; { return GetOutline(obj, CJKcode); } Private void Transformation(vfdata, fobj) long *vfdata; Font *fobj; { double t1, t2, t3, t4, t5, t6, sl; double tmp_x, tmp_y, xfact, yfact; int x, y, x2, y2, xoffset, yoffset; long *vfp; if (vfdata == NULL){ fprintf(stderr, "NULL OUTLINE DATA [in Transformation() / VF_Hbf.c]\n"); abort(); } /* Slant */ sl = fobj->Slant/100.0; if (sl < 0.0){ t1 = 1.0+sl; t2 = -sl; t3 =0.0; t4 = 0.0; t5 = 1.0; t6 = 0.0; } else { t1 = 1.0-sl; t2 = -sl; t3 = sl; t4 = 0.0; t5 = 1.0; t6 = 0.0; } xfact = (double)(fobj->Xfactor)/100.0; yfact = (double)(fobj->Yfactor)/100.0; xoffset = OL_OFFSET + fobj->Xoffset; yoffset = OL_OFFSET + fobj->Yoffset; for (vfp = vfdata; *vfp != (long)0; vfp++){ if ((*vfp & VFD_TOKEN) == (long)0){ tmp_x = xfact * (double)(VFD_GET_X(*vfp) - xoffset); tmp_y = yfact * (double)(VFD_GET_Y(*vfp) - yoffset); /* slant */ x = (int)(t1 * tmp_x + t2 * tmp_y + t3 * OL_SIZE); y = (int)(t4 * tmp_x + t5 * tmp_y + t6 * OL_SIZE); /* rotate */ switch (fobj->Rotate % 4){ default: case 0: x2 = x; y2 = y; break; case 1: x2 = OL_SIZE-y; y2 = x; break; case 2: x2 = OL_SIZE-x; y2 = OL_SIZE-y; break; case 3: x2 = y; y2 = OL_SIZE-x; break; } if (x2 < 0) x2 = 0; if (x2 >= OL_SIZE) x2 = OL_SIZE; if (y2 < 0) y2 = 0; if (y2 >= OL_SIZE) y2 = OL_SIZE; x2 += OL_OFFSET; y2 += OL_OFFSET; /* reflect x, y */ if (fobj->XReflect == 1) x2 = OL_RANGE - x2; if (fobj->YReflect == 1) y2 = OL_RANGE - y2; *vfp = VFD_MAKE_XY(x2, y2); } } } 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; { unsigned char *buff, d; int rast, x, y, yy1, yy2, val; rast = (w+7)/8; if ((buff = (unsigned char*) malloc(h*rast)) == NULL) return -1; /* ERR: malloc err */ bzero(buff, rast*h); if ((val = VF_Draw(vfdata, w, h, rast, buff, 0, 0)) < 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 val; } Private int FreeOutline(obj, vfdata) FontObj *obj; long* vfdata; { if (vfdata != NULL) free(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 GetEnc(obj) FontObj *obj; { Font *fobj; fobj = (Font*) obj->Locals; return fobj->Encoding; } Private int GetCharSet(obj) FontObj *obj; { Font *fobj; fobj = (Font*) obj->Locals; return fobj->CharSet; } static int ReadCapa(font, ent) Font *font; char *ent; { char *p; font->Encoding = 0; font->CharSet = 0; font->DotSizeFactor = 100; font->DotShape = DOT_SHAPE_SQUARE; 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); /* encoding and character set values will be checked with values from HBF header file in OpenFont() */ if ((p = VFC_GetString(VFCE_ENCODING)) != NULL) if ((font->Encoding = VFE_SearchEncoding(p)) < 0) return -1; /* ERR: unknown encoding */ if ((p = VFC_GetString(VFCE_CHARSET)) != NULL) if ((font->CharSet = VFE_SearchCharSet(p)) < 0) return -1; /* ERR: unknown character set */ if ((font->DotSizeFactor = VFC_GetNumber(VFCE_DOTSIZEFACT)) == -1) font->DotSizeFactor = 100; if (font->DotSizeFactor < 0) font->DotSizeFactor = 0; if ((p = VFC_GetString(VFCE_DOTSHAPE)) == NULL) font->DotShape = DOT_SHAPE_SQUARE; else { if (strcmp(p, "diamond") == 0){ font->DotShape = DOT_SHAPE_DIAMOND; } else { font->DotShape = DOT_SHAPE_SQUARE; } } if ((font->Slant = VFC_GetNumber(VFCE_SLANT)) == -1) font->Slant = 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; if ((p = VFC_GetString(VFCE_FONT_FILE)) == NULL) return -1; if ((font->Filename = malloc(strlen(p)+1)) == NULL) return -1; /* ERR: malloc err */ strcpy(font->Filename, p); return 0; } /*-- HBF INTERFACE -----------------*/ /* uses the HBF API (in the files hbf.c and hbf.h) written by Ross Paterson (rap@doc.ic.ac.uk) */ Private int HBF_Open(fname) char *fname; { int hbf_id; static int inited = 0; HBF_BBOX *hbf_bbox; const char *charset; int i; if (inited == 0){ /* initialize the table */ for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++) hbf_table[hbf_id] = NULL; inited = 1; } /* Check if the same HBF file is opened */ for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++){ if (hbf_table[hbf_id] == NULL) continue; if (strcmp(fname, hbf_table[hbf_id]->hbf_filename) == 0){ hbf_table[hbf_id]->link_count++; /*printf("FOUND\n");*/ return hbf_id; } } /* Find a free slot */ for (hbf_id = 0; hbf_id < VF_MAX_HBF_FONTS; hbf_id++){ if (hbf_table[hbf_id] == NULL) break; } if (hbf_id == VF_MAX_HBF_FONTS) return -1; /* no free slots */ /* Allocate hbf structure and initialize it */ /*printf("OPEN %d (%s)\n", hbf_id, fname);*/ if ((hbf_table[hbf_id] = (hbf*)malloc(sizeof(hbf))) == NULL) return -1; hbf_table[hbf_id]->link_count = 1; hbf_table[hbf_id]->hbf_nchar = -1; hbf_table[hbf_id]->hbf_width = 0; hbf_table[hbf_id]->hbf_height = 0; hbf_table[hbf_id]->hbf_filename = malloc(strlen(fname)+strlen(HBF_SUFFIX)+1); if (hbf_table[hbf_id]->hbf_filename == NULL) goto Err4; strcpy(hbf_table[hbf_id]->hbf_filename, fname); strcat(hbf_table[hbf_id]->hbf_filename, HBF_SUFFIX); /* Open HBF font and fill hbf structure */ hbf_table[hbf_id]->port = hbfOpen(hbf_table[hbf_id]->hbf_filename); if (hbf_table[hbf_id]->port == NULL) goto Err3; hbf_bbox = hbfBitmapBBox(hbf_table[hbf_id]->port); hbf_table[hbf_id]->hbf_width = hbf_bbox->hbf_width; hbf_table[hbf_id]->hbf_height = hbf_bbox->hbf_height; hbf_table[hbf_id]->hbf_nchar = (int) hbfChars(hbf_table[hbf_id]->port); hbf_table[hbf_id]->hbf_bmrast = HBF_RowSize(hbf_table[hbf_id]->port); charset = hbfProperty(hbf_table[hbf_id]->port, "HBF_CODE_SCHEME"); if ((hbf_table[hbf_id]->hbf_chset = VFE_SearchCharSet(charset)) < 0) goto Err3; /* ilegal character set */ for (i = 0; ChSetTable[i].CharSetValue != hbf_table[hbf_id]->hbf_chset; i++) ; hbf_table[hbf_id]->hbf_enc = ChSetTable[i].DefEncValue; return hbf_id; Err3: free(hbf_table[hbf_id]->hbf_filename); Err4: free(hbf_table[hbf_id]); hbf_table[hbf_id] = NULL; return -1; } Private int HBF_Close(hbf_id) int hbf_id; { if (hbf_table[hbf_id] == NULL){ printf("VFLIB: HBF - ILLEGAL TO CLOSE\n"); return -1; } /* Decrement the link count */ --hbf_table[hbf_id]->link_count; if (hbf_table[hbf_id]->link_count == 0){ /* release it since the slot is no longer used. */ hbfClose(hbf_table[hbf_id]->port); free(hbf_table[hbf_id]->hbf_filename); free(hbf_table[hbf_id]); hbf_table[hbf_id] = NULL; } return 0; } Private unsigned char* HBF_ReadBitmap(hbf_id, CJKcode) int hbf_id; int CJKcode; { hbf_table[hbf_id]->hbf_bmbuf = (unsigned char *) hbfGetBitmap(hbf_table[hbf_id]->port, (HBF_CHAR) CJKcode); return hbf_table[hbf_id]->hbf_bmbuf; } Private long* HBF_GetOutline(fobj, hbf_id, CJKcode) Font *fobj; int hbf_id; int CJKcode; { int x, y, ry, xx, nbits, size, ol_index; int ol_xl, ol_xr, ol_yu, ol_yl, ol_xc, ol_yc; int ol_xl2, ol_xr2, ol_yu2, ol_yl2; long *outline; unsigned char bmch; static char bit_tbl[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static int nbits_tbl[] = { 0, 1, 1, 2, /* 0, 1, 2, 3 */ 1, 2, 2, 3, /* 4, 5, 6, 7 */ 1, 2, 2, 3, /* 8, 9, A, B */ 2, 3, 3, 4, /* C, D, E, F */ }; if (HBF_ReadBitmap(hbf_id, CJKcode) == NULL) return NULL; /* count # of single bits */ nbits = 0; ry = 0; for (y = 0; y < hbf_table[hbf_id]->hbf_height; y++){ for (x = 0; x < hbf_table[hbf_id]->hbf_bmrast; x++){ nbits += nbits_tbl[(hbf_table[hbf_id]->hbf_bmbuf[ry+x]) >> 4]; nbits += nbits_tbl[(hbf_table[hbf_id]->hbf_bmbuf[ry+x]) & 0x0F]; } ry += hbf_table[hbf_id]->hbf_bmrast; } /* allocate outline data area */ switch (fobj->DotShape){ case DOT_SHAPE_SQUARE: case DOT_SHAPE_DIAMOND: default: size = 2 + 5*nbits + 1; break; } if ((outline = (long*)malloc(size*sizeof(long))) == NULL) return NULL; /* make outline data from bitmap */ ol_index = 0; /* header */ outline[ol_index++] = CJKcode; outline[ol_index++] = VF_SONY_COORDINATES; /* a set of black squares */ ry = 0; for (y = 0; y < hbf_table[hbf_id]->hbf_height; y++){ for (x = 0; x < hbf_table[hbf_id]->hbf_bmrast; x++){ bmch = hbf_table[hbf_id]->hbf_bmbuf[ry+x]; if (bmch == 0x00) continue; ol_yu = (y+0)*OL_SIZE/hbf_table[hbf_id]->hbf_width + OL_OFFSET; ol_yl = (y+1)*OL_SIZE/hbf_table[hbf_id]->hbf_width + OL_OFFSET - 1; ol_yc = (ol_yu+ol_yl)/2; ol_yu2 = fobj->DotSizeFactor*(ol_yu-ol_yc)/100+ol_yc; ol_yl2 = fobj->DotSizeFactor*(ol_yl-ol_yc)/100+ol_yc; for (xx = 0; xx <= 7; xx++){ /* if ((bit_tbl[xx] & bmch) != 0x00) printf("x"); * else printf(" "); */ if ((bit_tbl[xx] & bmch) != 0x00){ ol_xl = (8*x+xx+0)*OL_SIZE/hbf_table[hbf_id]->hbf_width+OL_OFFSET; ol_xr = (8*x+xx+1)*OL_SIZE/hbf_table[hbf_id]->hbf_width+OL_OFFSET-1; ol_xc = (ol_xl+ol_xr)/2; ol_xl2 = fobj->DotSizeFactor*(ol_xl-ol_xc)/100+ol_xc; ol_xr2 = fobj->DotSizeFactor*(ol_xr-ol_xc)/100+ol_xc; if (fobj->DotShape == DOT_SHAPE_SQUARE){ outline[ol_index++] = VFD_TOKEN|VFD_CHAR|VFD_CWCURV|VFD_LINE; outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yu2); outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yl2); outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yl2); outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yu2); } else { /* (fobj->DotShape == DOT_SHAPE_DIAMOND) */ outline[ol_index++] = VFD_TOKEN|VFD_CHAR|VFD_CWCURV|VFD_LINE; outline[ol_index++] = VFD_MAKE_XY(ol_xl2, ol_yc); outline[ol_index++] = VFD_MAKE_XY(ol_xc, ol_yl2); outline[ol_index++] = VFD_MAKE_XY(ol_xr2, ol_yc); outline[ol_index++] = VFD_MAKE_XY(ol_xc, ol_yu2); } } } } /*printf("\n");*/ ry += hbf_table[hbf_id]->hbf_bmrast; } /* end of outline */ outline[ol_index] = 0L; return outline; } /*EOF*/