home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
g
/
gs241j11.zip
/
ZKFJTEX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-09
|
25KB
|
1,308 lines
/*
* zkfjtex.c --- Kanji font operator for JTeX PK format file
*
* Copyright (C) 1992 Norio Katayama.
* Apr. 27, 1992 Programmed by N.Katayama (katayama@nacsis.ac.jp)
*/
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "errors.h"
#include "gsmatrix.h"
#include "state.h"
#include "store.h"
#undef DEBUG
#define B_X_CL 500 /* horizontal center in BuildChar */
#define B_Y_CL 400 /* vertical center in BuildChar */
#define B_Y_RP 0 /* reference point in BuildChar */
#define B_X_EX 1000 /* horizontal extent in BuildChar */
#define FP_CACHE_SIZE 10
/* Imported procedures */
extern int kf_is_vchar(P1(int));
extern int kf_vmatrix(P5(int, floatp, floatp, gs_rect *, gs_matrix *));
extern int gs_imagebbox(P6(int width, int height, int bool,
gs_matrix *pmat, byte *image, gs_rect *));
/* Forward declaration */
private int jteximage(P9(char *, int, int *, int *, byte *, int,
gs_matrix *, floatp *, floatp *));
/*
* zkfjtex
*/
int
zkfjtex(register os_ptr op)
{
char *buffer;
int code, len, width, height, length;
int jis_code, wmode;
byte *bitmap;
floatp w0x, w0y;
gs_matrix *pmat, vmat, imat;
gs_rect bbox;
check_type(op[-4], t_integer); /* JIS Code */
check_type(op[-3], t_integer); /* WMode */
if((code = write_matrix(op - 2)) < 0) /* ImageMatrix */
return code;
check_type(op[-1], t_string); /* ImageString */
check_type(op[0], t_string); /* FileName */
len = r_size(op);
if((buffer = gs_malloc(len + 1, 1, "zkfjtex")) == 0)
return e_VMerror;
memcpy(buffer, (char *)op->value.bytes, len);
buffer[len] = 0;
jis_code = op[-4].value.intval;
wmode = op[-3].value.intval;
bitmap = op[-1].value.bytes;
length = r_size(op - 1);
pmat = (gs_matrix *)op[-2].value.refs;
if((code = jteximage(buffer, jis_code,
&width, &height, bitmap, length,
pmat, &w0x, &w0y)) < 0)
return code;
if((code = gs_imagebbox(width, height, 1, pmat, bitmap, &bbox)) < 0)
return code;
if(wmode && kf_is_vchar(jis_code)) {
kf_vmatrix(jis_code,
(floatp)B_X_CL, (floatp)B_Y_CL, &bbox, &vmat);
gs_matrix_invert(&vmat, &imat);
gs_matrix_multiply(&imat, pmat, pmat);
}
/* Push results */
/* w0x w0y llx lly urx ury width height bool matrix bitmap */
push(6);
make_real(op - 10, w0x);
make_real(op - 9, w0y);
make_real(op - 8, bbox.p.x);
make_real(op - 7, bbox.p.y);
make_real(op - 6, bbox.q.x);
make_real(op - 5, bbox.q.y);
make_int(op - 4, width);
make_int(op - 3, height);
make_bool(op - 2 , 1);
make_tasv(op - 1, t_array, a_all, 6, refs, (ref *)pmat);
make_tasv(op, t_string, a_all, length, bytes, bitmap);
gs_free(buffer, len + 1, 1, "zkfjtex");
return 0;
}
/* -------- Initialization procedure -------- */
op_def zkfjtex_op_defs[] = {
{"5kfjtex", zkfjtex},
op_def_end(0)
};
/* -------- Internal Routines -------- */
#define FIXED16(fixed) ((double)(fixed) / 0x10000)
#define FIXED20(fixed) ((double)(fixed) / 0x100000)
/*
* Preamble structure
*/
typedef struct preamble_s {
ulong i; /* identifier */
/* x[k] */
double ds; /* design size */
ulong cs; /* check sum */
double hppp; /* pixel per point */
double vppp; /* pixel per point */
} preamble;
/*
* Glyph data structure
*/
typedef struct glyph_data_s {
ulong flag;
ulong pl; /* packet length */
ulong cc; /* character code */
double tfm;
double dx;
double dy;
ulong w;
ulong h;
long hoff;
long voff;
ulong rs;
} glyph_data;
/*
* Read bits from PK file
*/
private long
fget32(FILE *fp)
{
ulong u;
u = fgetc(fp);
u = (u << 8) + fgetc(fp);
u = (u << 8) + fgetc(fp);
u = (u << 8) + fgetc(fp);
return (long)u;
}
private long
fget24(FILE *fp)
{
ulong u;
u = fgetc(fp);
u = (u << 8) + fgetc(fp);
u = (u << 8) + fgetc(fp);
return (long)(u << 8) >> 8;
}
private short
fget16(FILE *fp)
{
ulong u;
u = fgetc(fp);
u = (u << 8) + fgetc(fp);
return (short)u;
}
/*
* Skip NOP operator
*/
private int
skip_nop(FILE *fp)
{
int c;
ulong k;
for(;;) {
switch(c = fgetc(fp)) {
case 240: /* pk_xxx1 */
k = fgetc(fp);
fseek(fp, k, 1);
break;
case 241: /* pk_xxx2 */
k = fget16(fp);
fseek(fp, k, 1);
break;
case 242: /* pk_xxx3 */
k = fget24(fp);
fseek(fp, k, 1);
break;
case 243: /* pk_xxx4 */
k = fget32(fp);
fseek(fp, k, 1);
break;
case 244: /* pk_yyy */
fget32(fp);
break;
case 246: /* pk_no_op */
break;
default:
ungetc(c, fp);
return 0;
}
if(ferror(fp) || feof(fp))
return -1;
}
}
/*
* Read preamble
*/
private int
read_preamble(FILE *fp, preamble *pa)
{
int k;
if(skip_nop(fp) < 0)
return -1;
if(fgetc(fp) != 247)
return -1;
if((pa->i = fgetc(fp)) != 89)
return -1;
k = fgetc(fp);
fseek(fp, k, 1);
pa->ds = FIXED20(fget32(fp));
pa->cs = fget32(fp);
pa->hppp = FIXED16(fget32(fp));
pa->vppp = FIXED16(fget32(fp));
if(ferror(fp) || feof(fp))
return -1;
return 0;
}
/*
* Read postamble
*/
private int
read_postamble(FILE *fp)
{
int c;
if(skip_nop(fp) < 0)
return -1;
if((c = fgetc(fp)) != 245)
return -1;
return 0;
}
/*
* Glyph data
*/
private void
long_format(FILE *fp, glyph_data *data)
{
data->pl = fget32(fp);
data->cc = fget32(fp);
data->tfm = FIXED20(fget32(fp));
data->dx = FIXED16(fget32(fp));
data->dy = FIXED16(fget32(fp));
data->w = fget32(fp);
data->h = fget32(fp);
data->hoff = fget32(fp);
data->voff = fget32(fp);
data->rs = data->pl - 37 + 8;
#ifdef DEBUG
fprintf(stderr, "long format (cc = %02X).\n", data->cc);
#endif
}
private void
extended_format(FILE *fp, glyph_data *data)
{
data->pl = fget16(fp);
data->cc = fgetc(fp);
data->tfm = FIXED20(fget24(fp));
data->dx = fget16(fp);
data->dy = 0;
data->w = fget16(fp);
data->h = fget16(fp);
data->hoff = fget16(fp);
data->voff = fget16(fp);
data->rs = ((data->flag & 0x03) << 16) + data->pl - 17 + 3;
#ifdef DEBUG
fprintf(stderr, "extended format (cc = %02X).\n", data->cc);
#endif
}
private void
short_format(FILE *fp, glyph_data *data)
{
data->pl = fgetc(fp);
data->cc = fgetc(fp);
data->tfm = FIXED20(fget24(fp));
data->dx = fgetc(fp);
data->dy = 0;
data->w = fgetc(fp);
data->h = fgetc(fp);
data->hoff = (char)fgetc(fp);
data->voff = (char)fgetc(fp);
data->rs = ((data->flag & 0x03) << 8) + data->pl - 11 + 3;
#ifdef DEBUG
fprintf(stderr, "short format (cc = %02X).\n", data->cc);
#endif
}
/*
* Read glyph data
*/
private int
read_glyph_data(FILE *fp, glyph_data *data)
{
data->flag = fgetc(fp);
if((data->flag & 0xf0) == 0xf0) {
ungetc(data->flag, fp);
return EOF;
}
if((data->flag & 0x07) == 0x07)
long_format(fp, data);
else if((data->flag & 0x04) == 0x04)
extended_format(fp, data);
else
short_format(fp, data);
return data->rs;
}
/*
* Glyph index
*/
typedef struct glyph_index_s {
ulong cc;
long offset;
} glyph_index;
/*
* PK file index
*/
typedef struct pk_index_s {
preamble pa;
int num_glyphs;
glyph_index *gi;
} pk_index, *pk_index_ptr;
/*
* Make PK index
*/
#define INIT_GI_SIZE 4
private int
make_pk_index(FILE *fp, pk_index *pi)
{
int count;
glyph_data data;
static glyph_index *gi = NULL;
static int gi_size = 0;
rewind(fp);
if(read_preamble(fp, &pi->pa) < 0)
return -1;
if(gi == NULL) {
if((gi = (glyph_index *)
malloc(sizeof(glyph_data)*INIT_GI_SIZE)) == NULL)
return -1;
gi_size = INIT_GI_SIZE;
}
count = 0;
for(;;) {
if(count >= gi_size) {
if((gi = (glyph_index *)
realloc(gi, sizeof(glyph_data)*gi_size*2)) == NULL)
return -1;
gi_size *= 2;
}
gi[count].offset = ftell(fp);
if(read_glyph_data(fp, &data) < 0)
break;
gi[count].cc = data.cc;
fseek(fp, data.rs, 1);
count ++;
}
if(read_postamble(fp) < 0)
return -1;
if((pi->gi = (glyph_index *)malloc(sizeof(glyph_data)*count)) == NULL)
return -1;
memcpy(pi->gi, gi, sizeof(glyph_data)*count);
pi->num_glyphs = count;
return 0;
}
/*
* Bits Expander
*/
private struct {
byte *bitmap;
int w, h;
int x, y;
int bw;
int repeat_count;
int w8;
} bits_data;
/* Init Bits Data */
private int
init_bits(byte *bitmap, int w, int h, int bw)
{
bits_data.bitmap = bitmap;
bits_data.w = w;
bits_data.h = h;
bits_data.x = 0;
bits_data.y = 0;
bits_data.bw = bw;
bits_data.w8 = (w - 1) / 8 + 1;
return 0;
}
/* Forward Bit */
private int
forward_bit()
{
int i;
byte *src, *dst;
if(++ bits_data.x < bits_data.w)
return 0;
/* new line */
bits_data.x = 0;
bits_data.y ++;
if(bits_data.repeat_count == 0)
return 0;
/* repeat line */
src = bits_data.bitmap + bits_data.w8*(bits_data.y - 1);
for(i=0; i<bits_data.repeat_count; i++) {
dst = bits_data.bitmap + bits_data.w8*bits_data.y;
memcpy(dst, src, bits_data.w8);
bits_data.y ++;
}
bits_data.repeat_count = 0;
return 0;
}
/* Set Bits */
private int
set_bits(ulong bit_count)
{
int i, n;
for(i=0; i<bit_count; i++) {
n = bits_data.x / 8 + bits_data.w8 * bits_data.y;
if(bits_data.bw)
bits_data.bitmap[n] |= 0x80 >> (bits_data.x % 8);
else
bits_data.bitmap[n] &= ~(0x80 >> (bits_data.x % 8));
forward_bit();
}
bits_data.bw = !bits_data.bw;
return 0;
}
/* Set Repeat Count */
private int
set_repeat_count(ulong repeat_count)
{
bits_data.repeat_count = repeat_count;
return 0;
}
/* Bits Filled */
private int
bits_filled(void)
{
if(bits_data.y >= bits_data.h)
return 1;
else
return 0;
}
/*
* Unpack Glyph
*/
private int
unpack_glyph(glyph_data *data, byte *glyph, byte *bitmap)
{
byte *ptr, mask, nybble;
long value, dyn_f = (data->flag & 0xf0) >> 4;
int repeat_count;
ptr = glyph;
mask = 0xf0;
#define get_nybble() ((mask == 0xf0) ? \
(mask = 0x0f, (*ptr & 0xf0) >> 4) : \
(mask = 0xf0, (*ptr++ & 0x0f)))
init_bits(bitmap, data->w, data->h, data->flag & 0x08);
repeat_count = 0;
while(!bits_filled() && ptr < glyph + data->rs) {
if((nybble = get_nybble()) == 0) {
int count, i;
count = 1;
while((nybble = get_nybble()) == 0)
count ++;
value = nybble;
for(i = 0; i < count; i++)
value = value * 16 + get_nybble();
value += (13 - dyn_f)*16 + dyn_f - 15;
#ifdef DEBUG
fprintf(stderr, "0: {%d}, ", value);
#endif
if(repeat_count) {
set_repeat_count(value);
repeat_count = 0;
}
else
set_bits(value);
}
else if(nybble <= dyn_f) {
value = nybble;
#ifdef DEBUG
fprintf(stderr, "1: {%d}, ", value);
#endif
if(repeat_count) {
set_repeat_count(value);
repeat_count = 0;
}
else
set_bits(value);
}
else if(nybble <= 13) {
value = (nybble - dyn_f - 1)*16 +
get_nybble() + dyn_f + 1;
#ifdef DEBUG
fprintf(stderr, "2: {%d}, ", value);
#endif
if(repeat_count) {
set_repeat_count(value);
repeat_count = 0;
}
else
set_bits(value);
}
else if(nybble == 14) {
#ifdef DEBUG
fprintf(stderr, "[], ");
#endif
repeat_count = 1;
}
else {
#ifdef DEBUG
fprintf(stderr, "[1], ");
#endif
set_repeat_count(1);
repeat_count = 0;
}
}
#ifdef DEBUG
fprintf(stderr, "\n");
fprintf(stderr, "bits_data: x %d, y %d\n", bits_data.x, bits_data.y);
#endif
return 0;
}
/*
* Convert glyph into bitmap
*/
private int
glyph_to_bitmap(glyph_data *data, byte *glyph, byte *bitmap)
{
if((data->flag & 0xf0) == 0xe0) {
/* bitmap */
int x, y, bmask, gmask;
byte *bptr, *gptr;
bptr = bitmap;
gptr = glyph;
gmask = 0x80;
for(y = 0; y < data->h; y++) {
bmask = 0x80;
for(x = 0; x < data->w; x++) {
if(*gptr & gmask)
*bptr |= bmask;
if((bmask >>= 1) == 0) {
bptr ++;
*bptr = 0;
bmask = 0x80;
}
if((gmask >>= 1) == 0) {
gptr ++;
gmask = 0x80;
}
}
if(bmask != 0x80)
bptr ++;
}
return 0;
}
else
return unpack_glyph(data, glyph, bitmap);
}
/* -------- File Name Hash Index -------- */
typedef struct index_item_s {
struct index_item_s *next;
char *str;
int id;
} index_item;
private index_item *hash_index[256];
/* hash function */
private int
hash(unsigned char *str)
{
unsigned char hash;
for(hash = 0; *str != 0; str++)
hash ^= *str;
return hash;
}
/* file name id */
private int
file_name_id(char *str)
{
static int id = 0;
int key = hash((unsigned char *)str);
index_item *item;
item = hash_index[key];
while(item != 0) {
if(strcmp(item->str, str) == 0)
return item->id;
item = item->next;
}
/* Not Found */
if((item = (index_item *)malloc(sizeof(index_item))) == 0)
return -1;
if((item->str = (char *)malloc(strlen(str) + 1)) == 0)
return -1;
strcpy(item->str, str);
item->next = hash_index[key];
item->id = id ++;
hash_index[key] = item;
return item->id;
}
/* -------- FILE Pointer Cache -------- */
typedef struct cache_item_s {
int prev;
int next;
int id;
FILE *fp;
} cache_item;
private
struct {
int head;
int used;
cache_item item[FP_CACHE_SIZE];
} fp_cache;
/* store cache */
private int
store_fp(int id, FILE *fp)
{
if(fp_cache.used == 0) {
/* first */
fp_cache.item[0].prev = 0;
fp_cache.item[0].next = 0;
fp_cache.item[0].id = id;
fp_cache.item[0].fp = fp;
fp_cache.head = 0;
fp_cache.used = 1;
}
else if(fp_cache.used < FP_CACHE_SIZE) {
int free, head, tail;
free = fp_cache.used;
head = fp_cache.head;
tail = fp_cache.item[head].prev;
/* put values */
fp_cache.item[free].prev = tail;
fp_cache.item[free].next = head;
fp_cache.item[free].id = id;
fp_cache.item[free].fp = fp;
/* link to the cache chain */
fp_cache.item[head].prev = free;
fp_cache.item[tail].next = free;
fp_cache.head = free;
fp_cache.used ++;
}
else {
int tail;
/* close the LRU */
tail = fp_cache.item[fp_cache.head].prev;
fclose(fp_cache.item[tail].fp);
/* put values */
fp_cache.item[tail].id = id;
fp_cache.item[tail].fp = fp;
fp_cache.head = tail;
}
return 0;
}
/* search cache */
private int
search_fp(int id, FILE **fp)
{
int idx;
if(fp_cache.used == 0)
return 0;
idx = fp_cache.head;
do {
if(fp_cache.item[idx].id == id) {
/* move the MRU to the head */
if(idx != fp_cache.head) {
int prev, next, head, tail;
prev = fp_cache.item[idx].prev;
next = fp_cache.item[idx].next;
fp_cache.item[next].prev = prev;
fp_cache.item[prev].next = next;
head = fp_cache.head;
tail = fp_cache.item[head].prev;
fp_cache.item[head].prev = idx;
fp_cache.item[tail].next = idx;
fp_cache.item[idx].prev = tail;
fp_cache.item[idx].next = head;
fp_cache.head = idx;
}
*fp = fp_cache.item[idx].fp;
return 1;
}
} while((idx = fp_cache.item[idx].next) != fp_cache.head);
return 0;
};
/* -------- PK Index Buffer -------- */
private
struct pk_index_buffer_s {
int size;
pk_index_ptr *ptr;
} pi_buffer;
#define INIT_PI_BUFFER_SIZE 4
/* store pk index */
private int
store_pk_index(int id, pk_index *pi)
{
if(pi_buffer.size == 0) {
int size = INIT_PI_BUFFER_SIZE;
if((pi_buffer.ptr = (pk_index_ptr *)
malloc(sizeof(pk_index_ptr)*size)) == NULL)
return -1;
memset(pi_buffer.ptr, 0, sizeof(pk_index_ptr)*size);
pi_buffer.size = size;
}
if(id >= pi_buffer.size) {
int size = pi_buffer.size;
while(id >= size)
size *= 2;
if((pi_buffer.ptr = (pk_index_ptr *)
realloc(pi_buffer.ptr, sizeof(pk_index_ptr)*size)) == NULL)
return -1;
memset(pi_buffer.ptr + pi_buffer.size, 0,
sizeof(pk_index_ptr)*(size - pi_buffer.size));
pi_buffer.size = size;
}
if((pi_buffer.ptr[id] = (pk_index *)malloc(sizeof(pk_index))) == NULL)
return -1;
*pi_buffer.ptr[id] = *pi;
return 0;
}
/* search pk index */
private int
search_pk_index(int id, pk_index *pi)
{
if(id >= pi_buffer.size || pi_buffer.ptr[id] == NULL)
return 0;
*pi = *pi_buffer.ptr[id];
return 1;
}
/* -------- PK Font File Routines -------- */
typedef struct pk_file_s {
FILE *fp;
pk_index pi;
} pk_file;
/*
* Open PK File
*/
private int
open_pk_file(char *file, pk_file *pf)
{
int id;
FILE *fp;
pk_index pi;
/* Hash Index */
if((id = file_name_id(file)) < 0)
return -1;
/* FILE Pointer Cache */
if(!search_fp(id, &fp)) {
#ifdef DEBUG
fprintf(stderr, "opening `%s'\n", file);
#endif
if((fp = fopen(file, "r")) == NULL)
return -1;
store_fp(id, fp);
}
/* PK Index Buffer */
if(!search_pk_index(id, &pi)) {
if(make_pk_index(fp, &pi) < 0)
return -1;
store_pk_index(id, &pi);
}
pf->fp = fp;
pf->pi = pi;
return 0;
}
/*
* Read Bitmap from PK File
*/
#define INIT_GLYPH_SIZE 16
private int
read_pk_bitmap(pk_file *pf, ulong cc,
glyph_data *data, byte *bitmap, int length)
{
int idx;
FILE *fp = pf->fp;
pk_index *pi = &pf->pi;
static byte *glyph = NULL;
static int glyph_size = 0;
if(glyph == NULL) {
if((glyph = (byte *)malloc(INIT_GLYPH_SIZE)) == NULL)
return e_VMerror;
glyph_size = INIT_GLYPH_SIZE;
}
/* scan glyph index */
for(idx = 0; idx < pi->num_glyphs; idx++ ) {
if(pi->gi[idx].cc == cc)
break;
}
if(idx == pi->num_glyphs)
return 0;
/* seek to the glyph */
if(fseek(fp, pi->gi[idx].offset, 0) < 0)
return e_ioerror;
/* read glyph data */
if(read_glyph_data(fp, data) < 0)
return e_ioerror;
/* check the length of bitmap */
if(((data->w - 1) / 8 + 1) * data->h > length)
return e_limitcheck;
/* reallocate glyph buffer */
if(glyph_size < data->rs) {
int size = glyph_size;
while(size < data->rs)
size *= 2;
free(glyph);
if((glyph = (byte *)malloc(size)) == NULL)
return e_VMerror;
glyph_size = size;
}
#ifdef DEBUG
fprintf(stderr, "cc: %02X, offset: %08X, w: %d, h: %d\n",
data->cc, pi->gi[idx].offset, data->w, data->h);
fprintf(stderr, "ftell(fp): %08X\n", ftell(fp));
#endif
/* read glyph */
if(fread(glyph, 1, data->rs, fp) != data->rs)
return e_ioerror;
/* convert glyph to bitmap */
if(glyph_to_bitmap(data, glyph, bitmap) < 0)
return e_ioerror;
return 1;
}
/* -------- JTeX PK Font File Routines -------- */
#define SERIAL(jis_code) \
(((jis_code) >> 8) * 94 + ((jis_code) & 0xff) - 0x21)
/* JTeX PK File Name */
private int
jtex_pk_file_name(char *file_name, int jis_code, char **pk_file_name)
{
char *ptr, *bp, *tail;
int length = strlen(file_name);
static char *buffer = NULL;
static int buffer_size = 0;
static int russian = 7; /* strlen("russian") */
if(buffer == NULL) {
buffer_size = (length + russian) * 2;
if((buffer = (char *)malloc(buffer_size)) == NULL)
return e_VMerror;
}
else if(buffer_size < length + russian) {
buffer_size = (length + russian) * 2;
if((buffer = (char *)realloc(buffer, buffer_size)) == NULL)
return e_VMerror;
}
for(ptr = file_name + length - 1; ptr >= file_name; ptr --) {
if(*ptr == '\\') {
strcpy(buffer, file_name);
bp = buffer + (ptr - file_name);
*bp = 0;
tail = ptr + 1;
break;
}
}
if(ptr < file_name)
return e_rangecheck;
if(jis_code < 0x2100)
return e_rangecheck;
else if(jis_code < 0x2300)
strcpy(bp, "sy");
else if(jis_code < 0x2400)
strcpy(bp, "roma");
else if(jis_code < 0x2500)
strcpy(bp, "hira");
else if(jis_code < 0x2600)
strcpy(bp, "kata");
else if(jis_code < 0x2700)
strcpy(bp, "greek");
else if(jis_code < 0x2800)
strcpy(bp, "russian");
else if(jis_code < 0x2900)
strcpy(bp, "keisen");
else if(jis_code < 0x3000)
return e_rangecheck;
else if(jis_code < 0x5000) {
int c = 'a' + (SERIAL(jis_code) - SERIAL(0x3021)) / 256;
sprintf(bp, "k%c", c);
}
else if(jis_code < 0x8000) {
int c = 'm' + (SERIAL(jis_code) - SERIAL(0x5021)) / 256;
sprintf(bp, "k%c", c);
}
else
return e_rangecheck;
strcat(buffer, tail);
*pk_file_name = buffer;
return 0;
}
/*
* JTeX PK Character Code
*/
private int
jtex_pk_char_code(int jis_code)
{
if(jis_code < 0x2100)
return e_rangecheck;
else if(jis_code < 0x2200)
return SERIAL(jis_code) - SERIAL(0x2120);
else if(jis_code < 0x2300)
return SERIAL(jis_code) - SERIAL(0x2220) + 100;
else if(jis_code < 0x2400)
return SERIAL(jis_code) - SERIAL(0x2300);
else if(jis_code < 0x2500)
return SERIAL(jis_code) - SERIAL(0x2420);
else if(jis_code < 0x2600)
return SERIAL(jis_code) - SERIAL(0x2520);
else if(jis_code < 0x2700)
return SERIAL(jis_code) - SERIAL(0x2620);
else if(jis_code < 0x2800)
return SERIAL(jis_code) - SERIAL(0x2720);
else if(jis_code < 0x2900)
return SERIAL(jis_code) - SERIAL(0x2820);
else if(jis_code < 0x3000)
return e_rangecheck;
else if(jis_code < 0x5000)
return (SERIAL(jis_code) - SERIAL(0x3021)) % 256;
else if(jis_code < 0x8000)
return (SERIAL(jis_code) - SERIAL(0x5021)) % 256;
else
return e_rangecheck;
}
/*
* JTeX PK bitmap
*/
private int
jtex_pk_bitmap(char *file, int jis_code,
int *width, int *height, byte *bitmap, int length,
floatp *ds, floatp *hppp, floatp *vppp,
floatp *tfm, floatp *dx, floatp *dy, int *hoff, int *voff)
{
char *pk_file_name;
int code;
ulong cc;
pk_file pf;
glyph_data data;
if((code = jtex_pk_file_name(file, jis_code, &pk_file_name)) < 0)
return code;
#ifdef DEBUG
fprintf(stderr, "pk_file_name: %s\n", pk_file_name);
#endif
if((code = open_pk_file(pk_file_name, &pf)) < 0) {
fprintf(stderr,
"jtex_pk_bitmap: cannot open `%s'.\n", pk_file_name);
return e_undefinedfilename;
}
#ifdef DEBUG
{
int idx;
idx = fp_cache.head;
do {
fprintf(stderr, "%d ", fp_cache.item[idx].id);
} while((idx = fp_cache.item[idx].next) != fp_cache.head);
fprintf(stderr, "\n");
}
#endif
if((cc = jtex_pk_char_code(jis_code)) < 0)
return e_rangecheck;
if((code = read_pk_bitmap(&pf, cc, &data, bitmap, length)) < 0)
return code;
if(code == 0) {
/* undefined character */
*width = 0;
*height = 0;
*ds = pf.pi.pa.ds;
*hppp = pf.pi.pa.hppp;
*vppp = pf.pi.pa.vppp;
*tfm = 0;
*dx = 0;
*dy = 0;
*hoff = 0;
*voff = 0;
return 0;
}
*width = data.w;
*height = data.h;
*ds = pf.pi.pa.ds;
*hppp = pf.pi.pa.hppp;
*vppp = pf.pi.pa.vppp;
*tfm = data.tfm;
*dx = data.dx;
*dy = data.dy;
*hoff = data.hoff;
*voff = data.voff;
#ifdef DEBUG
{
int x, y, w8 = (data.w - 1) / 8 + 1;
for(y=0; y<data.h; y++) {
for(x=0; x<data.w; x++) {
if(bitmap[x/8 + w8*y] & (0x80 >> (x % 8)))
fprintf(stderr, "*");
else
fprintf(stderr, " ");
}
fprintf(stderr, "\n");
}
}
#endif
return 0;
}
/* -------- Ghostscript Image Routines -------- */
/*
* JTeX Kanji width
*/
#define INIT_KANJI_WIDTH_CACHE_SIZE 32
#define DUMMY_KANJI_CODE 0x3021
#define DUMMY_BITMAP_SIZE 10000
private int
jtex_kanji_width(char *file, floatp *kanji_width)
{
int id;
static floatp *cache = NULL;
static int cache_size;
if(cache == NULL) {
int size = INIT_KANJI_WIDTH_CACHE_SIZE;
if((cache = (floatp *)malloc(sizeof(floatp)*size)) == NULL)
return e_VMerror;
memset(cache, 0, sizeof(floatp)*size);
cache_size = size;
}
if((id = file_name_id(file)) < 0)
return e_undefinedfilename;
if(id >= cache_size) {
int size = cache_size;
while(id >= size)
size *= 2;
if((cache = (floatp *)
realloc(cache, sizeof(floatp)*size)) == NULL)
return e_VMerror;
memset(cache + cache_size, 0,
sizeof(floatp)*(size - cache_size));
cache_size = size;
}
if(cache[id] == 0) {
int width, height;
byte bitmap[DUMMY_BITMAP_SIZE];
int length = DUMMY_BITMAP_SIZE;
floatp ds, hppp, vppp, tfm, dx, dy;
int hoff, voff;
int code;
if((code = jtex_pk_bitmap(file, DUMMY_KANJI_CODE,
&width, &height, bitmap, length,
&ds, &hppp, &vppp,
&tfm, &dx, &dy, &hoff, &voff)) < 0)
return code;
cache[id] = dx;
}
*kanji_width = cache[id];
return 0;
}
/*
* Retrieve Font Image
*/
private int
jteximage(char *file, int jis_code,
int *width, int *height, byte *bitmap, int length,
gs_matrix *pmat, floatp *wx, floatp *wy)
{
int code;
floatp ds, hppp, vppp, tfm, dx, dy;
int hoff, voff;
floatp kanji_width;
floatp scale, tx, ty;
gs_matrix smat, tmat;
if((code = jtex_pk_bitmap(file, jis_code,
width, height, bitmap, length,
&ds, &hppp, &vppp,
&tfm, &dx, &dy, &hoff, &voff)) < 0)
return code;
#ifdef DEBUG
fprintf(stderr, "ds : %g, hppp: %g, vppp: %g\n", ds, hppp, vppp);
fprintf(stderr, "tfm: %g, dx : %g, dy : %g, hoff: %d, voff : %d\n",
tfm, dx, dy, hoff, voff);
#endif
/* Retrieve Kanji Width */
if((code = jtex_kanji_width(file, &kanji_width)) < 0)
return code;
/* Transform Image */
gs_make_identity(pmat);
scale = (floatp)B_X_EX / kanji_width;
gs_make_scaling(1.0 / scale, -1.0 / scale, &smat);
tx = hoff + dx / 2.0 - (floatp)B_X_CL / scale;
ty = voff + (floatp)B_Y_RP / scale;
gs_make_translation(tx, ty, &tmat);
gs_matrix_multiply(pmat, &smat, pmat);
gs_matrix_multiply(pmat, &tmat, pmat);
*wx = (floatp)B_X_CL * 2.0;
*wy = 0;
return 0;
}