/* * VF_Comp.c * * Programmmed by Hirotsugu Kakugawa, Hiroshima University * E-Mail: h.kakugawa@computer.org * * Edition History * 5 Nov 1993 * 20 Jan 1994 Added GetOutline2(). * 8 Mar 1994 Fixed small bugs and removed dead code */ /* This file is 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 compound font objects:: "kn" (str) -- Kana Font Entry "kj" (str) -- Kanji Font Entry "sy" (str) -- Symbol Font Entry */ #include #include #include #include "config.h" #include "defs.h" #include "_VF.h" #include "VF.h" #include "VFcap.h" #ifndef MAX #define MAX(a, b) ( ((a)>(b)) ? (a) : (b) ) #endif #ifndef MIN #define MIN(a, b) ( ((a)<(b)) ? (a) : (b) ) #endif #define RANGE_SET_MAX 32 #define P_FONT_MAX 16 struct s_range { int start; int end; }; typedef struct s_range Range; typedef struct s_range* RangeSet; static Range NULL_Range = { -1, -1 }; static RangeSet NULL_RangeSet = { &NULL_Range }; struct s_p_font { char *name; int FD; RangeSet range_set; }; typedef struct s_p_font P_FONT; struct s_font { int fd; P_FONT p_font_set[P_FONT_MAX]; }; 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(); Private int ReadCapa(); Private RangeSet parse_range_set(); Private int is_in(); Public FontObj* CreateFont_Comp2(ent) char *ent; { Font *font; FontObj *fobj; if ((font = (Font*) malloc(sizeof(Font))) == NULL) return NULL; /* ERR: malloc err */ font->fd = -1; if (ReadCapa(font, ent) < 0) return NULL; fobj = (FontObj*) malloc(sizeof(FontObj)); fobj->ClassID = VF_FONT_COMPOUND2; 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(obj) FontObj* obj; { Font *font; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (font->p_font_set[i].name != NULL) font->p_font_set[i].FD = VF_OpenFont(font->p_font_set[i].name); } return 0; } Private int CloseFont(obj, fid) FontObj *obj; int fid; { Font *font; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (font->p_font_set[i].name != NULL) font->p_font_set[i].FD = VF_CloseFont(font->p_font_set[i].FD); } return 0; } 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 = -1; Font *font; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (is_in(font->p_font_set[i].range_set, jiscode)) { if (font->p_font_set[i].name != NULL) { val = VF_GetBitmap(jiscode, font->p_font_set[i].FD, w, h, bw, bo, bm_buf); } break; } } return val; } Private long* GetOutline(obj, jiscode) FontObj *obj; int jiscode; { long *outline = NULL; Font *font; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (is_in(font->p_font_set[i].range_set, jiscode)) { if (font->p_font_set[i].name != NULL) { outline = VF_GetOutline(jiscode, font->p_font_set[i].FD); } break; } } return outline; } Private long* GetOutline2(obj, jiscode) FontObj *obj; int jiscode; { long *outline = NULL; Font *font; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (is_in(font->p_font_set[i].range_set, jiscode)) { if (font->p_font_set[i].name != NULL) { outline = VF_GetOutline2(jiscode, font->p_font_set[i].FD); } break; } } 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; { int jiscode; Font *font; int val = -1; int i; font = (Font*) obj->Locals; jiscode = vfdata[0]; for (i = 0; i < P_FONT_MAX; i++) { if (is_in(font->p_font_set[i].range_set, jiscode)) { if (font->p_font_set[i].name != NULL) { val = VF_DrawOutline(vfdata, font->p_font_set[i].FD, w, h, bw, bo, bm_buf); } break; } } return val; } Private int FreeOutline(obj, vfdata) FontObj *obj; long* vfdata; { Font *font; int val = -1; int i; font = (Font*) obj->Locals; for (i = 0; i < P_FONT_MAX; i++) { if (is_in(font->p_font_set[i].range_set, vfdata[0])) { if (font->p_font_set[i].name != NULL) { val = VF_FreeOutline(vfdata, font->p_font_set[i].FD); } break; } } return val; } 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; } static int ReadCapa(font, ent) Font *font; char *ent; { char *p; int i; RangeSet range_set; static char f_ent_str[] = "f?"; static char r_ent_str[] = "r?"; VFC_GetEntry(ent); for (i = 0; i < P_FONT_MAX; i++) { f_ent_str[1] = ('A' + i); r_ent_str[1] = ('A' + i); if ((p = VFC_GetString(f_ent_str)) == NULL) font->p_font_set[i].name = NULL; else { if ((font->p_font_set[i].name = malloc(strlen(p)+1)) == NULL) return -1; /* ERR: malloc err */ strcpy(font->p_font_set[i].name, p); } if ((p = VFC_GetString(r_ent_str)) == NULL) font->p_font_set[i].range_set = NULL_RangeSet; else { if ((range_set = parse_range_set(p)) == (RangeSet)NULL) font->p_font_set[i].range_set = NULL_RangeSet; else font->p_font_set[i].range_set = range_set; } } return 0; } /* * is_in() * * val が RangeSet の範囲にあるかを調べる関数 * * 範囲にあれば、 TRUE を返す * 無ければ FALSE を返す * */ Private int is_in(range_set, val) RangeSet range_set; int val; { int start, end; while ((range_set->start >= 0) && (range_set->end >= 0)) { start = range_set->start; end = range_set->end; if ((start <= val) && (val <= end)) return TRUE; range_set++; } return FALSE; } /* * parse_range_set() * * 文字列が下の文法に従っていれば、RangeSet を返す。 * そうでなければ、(RangeSet)NULL を返す * * (注) malloc() でメモリを割り当てるので、呼出した側で解放すること * * rangeset: range * | rangeset COMMA range * range: num * | num BAR num * num: XDIGIT+ * XDIGIT: [0-9a-fA-F] * COMMA: ',' * BAR: '-' * * example * "1,b-9,1af-25" "ff-5,a,7" --- OK * "3.5-to" "-2" "2-" "1-2, 3-5" --- BAD * ^ ^^ ^ ^ ^ */ Private RangeSet parse_range_set(str) char *str; { int i; char *p, *p2; int val1, val2; Range tmp_set[RANGE_SET_MAX]; RangeSet set; int range_no; int str_len; str_len = strlen(str); for (i = 0; i < str_len; i++) { p = (str+i); if (*p == ',') *p = '\0'; else if (!isxdigit((char)*p) && (*p != '-')) { /* printf("warning: wrong char '%c' found.\n", *p); */ return (RangeSet)NULL; } } range_no = 0; i = 0; while (i < str_len) { if (range_no > RANGE_SET_MAX) { /* printf("warning: too many range.\n"); */ return (RangeSet)NULL; } p = (str+i); if (*p == '\0') { i++; continue; } if (*p == '-') { /* printf("warning: no start number.\n"); */ return (RangeSet)NULL; } val1 = strtol(p, &p2, 16); if (*p2 != '-') { val2 = val1; } else { if (*(p2+1) == '\0') { /* printf("warning: no last number.\n"); */ return (RangeSet)NULL; } val2 = strtol((p2+1), &p2, 16); } if (*p2 != '\0') { /* printf("warning: wrong format.\n"); */ return (RangeSet)NULL; } tmp_set[range_no].start = MIN(val1, val2); tmp_set[range_no].end = MAX(val1, val2); range_no++; i = i + strlen(p); } tmp_set[range_no].start = -1; tmp_set[range_no].end = -1; if (range_no < 1) return (RangeSet)NULL; set = (RangeSet)malloc((sizeof(Range) * (range_no+1))); if (!set) return (RangeSet)NULL; memcpy(set, tmp_set, (sizeof(Range) * (range_no+1))); return set; }