home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
g
/
gs241j11.zip
/
ZKFSONY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-26
|
9KB
|
450 lines
/*
* zkfsony.c --- Kanji font operator for Sony format outline font
*
* Copyright (C) 1991 Norio Katayama.
* Aug.5, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
*/
#include <ctype.h>
#include "math_.h"
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "errors.h"
#include "gspath.h"
#include "state.h"
#include "FS.h"
#undef DEBUG
#define D_X_CL (D_SIZE / 2 + D_OFFSET) /* horizontal center of data */
#define D_Y_CL (D_SIZE / 2 + D_OFFSET) /* vertical center of data */
#define D_Y_BL (D_SIZE * 0.9 + D_OFFSET) /* base line of data */
#define B_X_CL 500 /* horizontal center in BuildChar */
#define B_Y_CL 400 /* vertical center in BuildChar */
#define B_Y_BL 0 /* base line in BuildChar */
/* Forward declaration */
private floatp map_x(P1(double));
private floatp map_y(P1(double));
private int hash(P1(unsigned char *));
private int draw_font(P3(char *, int, int));
/*
* zkfsony
*/
int
zkfsony(register os_ptr op)
{
char *buffer;
int code, len, jis_code, wmode;
check_type(op[-2], t_integer); /* JIS Code */
check_type(op[-1], t_integer); /* WMode */
check_type(op[0], t_string); /* File Name */
len = r_size(op);
if((buffer = gs_malloc(len + 1, 1, "zkfsony")) == 0)
return e_VMerror;
memcpy(buffer, (char *)op->value.bytes, len);
buffer[len] = 0;
jis_code = op[-2].value.intval;
wmode = op[-1].value.intval;
if((code = draw_font(buffer, jis_code, wmode)) != 0)
return code;
pop(3);
gs_free(buffer, len + 1, 1, "zkfsony");
return 0;
}
/* -------- Initialization procedure -------- */
op_def zkfsony_op_defs[] = {
{"3kfsony", zkfsony},
op_def_end(0)
};
/* -------- Internal routines -------- */
/*
* Mapping to coordinates in BuildChar
*/
private floatp
map_x(double x)
{
static double factor =
(double)(B_Y_CL - B_Y_BL) / (double)(D_Y_CL - D_Y_BL);
return B_X_CL + (x - D_X_CL) * (factor > 0 ? factor : - factor);
}
private floatp
map_y(double y)
{
static double factor =
(double)(B_Y_CL - B_Y_BL) / (double)(D_Y_CL - D_Y_BL);
return B_Y_CL + (y - D_Y_CL) * factor;
}
/*
* Convert JIS code into serial code
*/
private unsigned int
vchars[] = {
0x2122, 0x2123, 0x2131, 0x2132, 0x213c, 0x213d, 0x213e, 0x2141,
0x2142, 0x2143, 0x2144, 0x2145, 0x214a, 0x214b, 0x214c, 0x214d,
0x214e, 0x214f, 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155,
0x2156, 0x2157, 0x2158, 0x2159, 0x215a, 0x215b, 0x222e, 0x2421,
0x2423, 0x2425, 0x2427, 0x2429, 0x2443, 0x2463, 0x2465, 0x2467,
0x246e,
0x2521,
0x2523, 0x2525, 0x2527, 0x2529, 0x2543, 0x2563, 0x2565, 0x2567,
0x256e, 0x2575, 0x2576
};
private int
jtoc(int jis, int wmode)
{
int i, num_vchars = sizeof(vchars)/sizeof(*vchars);
if(wmode == 1 && jis <= vchars[num_vchars-1]) {
#ifdef DEBUG
fprintf(stderr, "WMode: %04X\n", jis);
#endif
for(i=0; i<num_vchars; i++) {
if(jis == vchars[i]) {
jis = i + 0x7521;
break;
}
}
}
return (( jis >> 8) - 0x21) * 94 + (jis & 0xff) - 0x21;
}
/*
* Hash Index
*/
typedef struct index_item_s {
struct index_item_s *next;
char *str;
int fd;
} index_item;
private index_item *hash_index[256];
/* store */
private int
store(char *str, int fd)
{
int key = hash((unsigned char *)str);
index_item *item;
if((item = (index_item *)malloc(sizeof(index_item))) == 0)
return e_VMerror;
if((item->str = (char *)malloc(strlen(str) + 1)) == 0)
return e_VMerror;
strcpy(item->str, str);
item->next = hash_index[key];
item->fd = fd;
hash_index[key] = item;
return 0;
}
/* search */
private int
search(char *str, int *fd)
{
int key = hash((unsigned char *)str);
index_item *item;
item = hash_index[key];
while(item != 0) {
if(strcmp(item->str, str) == 0) {
*fd = item->fd;
return 1;
}
item = item->next;
}
return 0;
}
/*
* Hash function
*/
private int
hash(unsigned char *str)
{
unsigned char hash;
for(hash = 0; *str != 0; str++)
hash ^= *str;
return hash;
}
/*
* Open font
*/
private int
open_font(char *file)
{
int code, fd;
if(search(file, &fd))
return fd;
else {
if((fd = FS_open_font(file)) < 0) {
fprintf(stderr, "FS_open_font: error code = %d\n", fd);
return fd;
}
if((code = store(file, fd)) < 0)
return code;
return fd;
}
}
/*
* moveto
*/
#define moveto(x, y) gs_moveto(igs, map_x(x), map_y(y))
/*
* lineto
*/
#define lineto(x, y) gs_lineto(igs, map_x(x), map_y(y))
/*
* atan360
*/
private double
atan360(double y, double x)
{
double ang;
static double factor = -1.0;
#ifdef M_PI
if(factor < 0.0)
factor = 180.0 / M_PI;
#else
factor = 45.0 / atan(1.0);
#endif
if((ang = atan2(y, x) * factor) < 0)
ang += 360.0;
return ang;
}
/*
* darc3
*/
private int
darc3(floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3)
{
int code;
floatp dx1, dy1, dx3, dy3, cx, cy, z, r, ang1, ang2, ang3, ang;
x1 = map_x(x1); y1 = map_y(y1);
x2 = map_x(x2); y2 = map_y(y2);
x3 = map_x(x3); y3 = map_y(y3);
dx1 = x1 - x2; dy1 = y1 - y2;
dx3 = x3 - x2; dy3 = y3 - y2;
if((z = dx1*dy3 - dx3*dy1) == 0) {
if((dx1 == dx3) && (dy1 == dy3)) {
cx = dx1 / 2.0;
cy = dy1 / 2.0;
r = sqrt(cx*cx + cy*cy);
ang = atan360(dy1 - cy, dx1 - cx);
return gs_arc(igs, cx + x2, cy + y2, r, ang, ang+360);
}
else {
if((code = gs_lineto(igs, x1, y1)) < 0)
return code;
return gs_lineto(igs, x3, y3);
}
}
cx = ((dx1*dx1 + dy1*dy1)*dy3 - (dx3*dx3 + dy3*dy3)*dy1) / z / 2.0;
cy = - ((dx1*dx1 + dy1*dy1)*dx3 - (dx3*dx3 + dy3*dy3)*dx1) / z / 2.0;
r = sqrt(cx*cx + cy*cy);
ang1 = atan360(dy1 - cy, dx1 - cx);
ang2 = atan360(-cy, -cx);
ang3 = atan360(dy3 - cy, dx3 - cx);
if(ang1 == ang3)
return gs_arc(igs, cx + x2, cy + y2, r, 0.0, 360.0);
else if(ang1 < ang3) {
if(ang1 <= ang2 && ang2 <= ang3)
return gs_arc(igs, cx + x2, cy + y2, r, ang1, ang3);
else
return gs_arcn(igs, cx + x2, cy + y2, r, ang1, ang3);
}
else {
if(ang3 <= ang2 && ang2 <= ang1)
return gs_arcn(igs, cx + x2, cy + y2, r, ang1, ang3);
else
return gs_arc(igs, cx + x2, cy + y2, r, ang1, ang3);
}
}
/*
* curveto
*/
#define curveto(x1, y1, x2, y2, x3, y3) \
gs_curveto(igs, map_x(x1), map_y(y1), \
map_x(x2), map_y(y2), map_x(x3), map_y(y3))
/*
* Draw Font
*/
#define FS_XY(ptr, x, y) \
if(is_bos(*ptr)) return e_undefinedresult; \
x = (*ptr >> X_SHIFT) & XY_MASK; \
y = *ptr & XY_MASK;
#define GMASK (LINE | ARC | BEZIER)
private int
draw_font(char *font_name, int jis, int wmode)
{
long *ptr, token, next_token;
int font_fd, code;
int x, y, x0, y0, x1, y1, x2, y2, x3, y3;
if((font_fd = open_font(font_name)) <0)
return e_undefinedfilename;
if((code = FS_get_outline(jtoc(jis, wmode), font_fd, &ptr)) < 0) {
switch(code) {
#ifdef FS_GET_OUTLINE_ERR_5
case FS_GET_OUTLINE_ERR_5:
/* undefined font */
return 0;
#endif
default:
fprintf(stderr, "FS_get_outline: error code = %d\n",
code);
return e_ioerror;
}
}
while(*ptr != 0) {
/* The beginning of segment */
if(!is_bos(*ptr))
return e_undefinedresult;
token = *ptr ++;
FS_XY(ptr, x, y);
ptr ++;
x0 = x;
y0 = y;
moveto((floatp)x0, (floatp)y0);
switch(token & GMASK) {
case LINE:
break;
case ARC:
x1 = x;
y1 = y;
FS_XY(ptr, x2, y2);
ptr ++;
break;
case BEZIER:
FS_XY(ptr, x2, y2);
ptr ++;
FS_XY(ptr, x3, y3);
ptr ++;
break;
default:
return e_undefinedresult;
}
while(!is_bos(*ptr) && *ptr != 0) {
if(is_token(*ptr))
next_token = *ptr++;
else
next_token = token;
FS_XY(ptr, x, y);
ptr ++;
switch(token & GMASK) {
case LINE:
lineto((floatp)x, (floatp)y);
break;
case ARC:
darc3((floatp)x1, (floatp)y1,
(floatp)x2, (floatp)y2,
(floatp)x, (floatp)y);
break;
case BEZIER:
curveto((floatp)x2, (floatp)y2,
(floatp)x3, (floatp)y3,
(floatp)x, (floatp)y);
break;
default:
return e_undefinedresult;
}
token = next_token;
switch(token & GMASK) {
case LINE:
break;
case ARC:
x1 = x;
y1 = y;
FS_XY(ptr, x2, y2);
ptr ++;
break;
case BEZIER:
FS_XY(ptr, x2, y2);
ptr ++;
FS_XY(ptr, x3, y3);
ptr ++;
break;
default:
return e_undefinedresult;
}
}
switch(token & GMASK) {
case LINE:
lineto((floatp)x0, (floatp)y0);
break;
case ARC:
darc3((floatp)x1, (floatp)y1,
(floatp)x2, (floatp)y2,
(floatp)x0, (floatp)y0);
break;
case BEZIER:
curveto((floatp)x2, (floatp)y2,
(floatp)x3, (floatp)y3,
(floatp)x0, (floatp)y0);
break;
default:
return e_undefinedresult;
}
}
return 0;
}