/*
 * zkfpc98.c --- Kanji font operator for PC98 ROM
 *
 * Copyright (C) 1991 Norio Katayama.
 * Sep. 28, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
 */

#include <ctype.h>
#include <dos.h>
#include <pc.h>
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "errors.h"
#include "gsmatrix.h"
#include "state.h"
#include "store.h"
#include "alloc.h"

#define B_X_CL	500	/* horizontal center in BuildChar */
#define B_Y_CL	400	/* vertical center in BuildChar */

/* 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 pc98image(P8(int, int *, int *, byte *, int,
			 gs_matrix *, floatp *, floatp *));

/*
 * zkfpc98
 */

int
zkfpc98(register os_ptr op)
{
	int code, width, height, length;
	int jis_code, wmode;
	byte *bitmap;
	floatp w0x, w0y;
	gs_matrix *pmat, vmat, imat;
	gs_rect bbox;

	check_type(op[-3], t_integer);		/* JIS Code */
	check_type(op[-2], t_integer);		/* WMode */
	if((code = write_matrix(op - 1)) < 0)	/* ImageMatrix */
		return code;
	check_type(op[0], t_string);		/* ImageString */

	jis_code = op[-3].value.intval;
	wmode = op[-2].value.intval;

	bitmap = op[0].value.bytes;
	length = r_size(op);
	pmat = (gs_matrix *)op[-1].value.refs;

	if((code = pc98image(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(7);
	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);
	return 0;
}

/* -------- Initialization procedure -------- */

op_def zkfpc98_op_defs[] = {
	{"4kfpc98", zkfpc98},
	op_def_end(0)
};

/* -------- Internal routines -------- */

/*
 * Read Image from the Font ROM
 */

private int
read_font_rom(byte *bitmap, int jis_code)
{
	int y;
	
	outportb(0x68, 0x0B);
	outportb(0xA3, (jis_code >> 8) - 0x20);
	outportb(0xA1, jis_code & 0xFF);
	for(y=0; y<16; y++) {
		outportb(0xA5, 0x20 + y);
		bitmap[y*2] = inportb(0xA9);
		outportb(0xA5, y);
		bitmap[y*2 + 1] = inportb(0xA9);
	}
	outportb(0x68, 0x0A);
	
	return 0;
}

/*
 * Retrieve Font Image
 */

private int
pc98image(int jis_code,
	  int *width, int *height, byte *bitmap, int length,
	  gs_matrix *pmat, floatp *wx, floatp *wy)
{
	int num_bytes;
	int pixel_size, font_ascent, font_descent;
	floatp dx, dy, scale;
	gs_matrix smat, tmat;

	/* Read Font Bitmap */

	pixel_size = *width = *height = 16;
	font_ascent = 14;
	font_descent = 2;

	num_bytes = pixel_size / 8 * pixel_size;
	if(num_bytes > length)
		return e_rangecheck;

	read_font_rom(bitmap, jis_code);

	/* Transform Image */

	gs_make_identity(pmat);

	scale = (floatp)B_Y_CL * 2.0 / (floatp)font_ascent;
	gs_make_scaling(1.0 / scale, -1.0 / scale, &smat);

	dx = (floatp)pixel_size / 2.0 - (floatp)B_X_CL / scale;
	dy = (floatp)font_ascent;
	gs_make_translation(dx, dy, &tmat);

	gs_matrix_multiply(pmat, &smat, pmat);
	gs_matrix_multiply(pmat, &tmat, pmat);

	*wx = (floatp)B_X_CL * 2.0;
	*wy = 0;

	return 0;
}

