/*
*               TeX Device Driver DVIOUT, DVIPRT で
*                ＪＧ３の３次ベジェフォントを使う
*
*                             jgfont.c
*
*     "本プログラムは、T.Minagawa氏の vfont.c, vdata.c, vraster.c等を
*      できるかぎり利用して、ＪＧ３付属の「３次ベジェ」フォントを使う
*      ためのものです。"
*
*                      12 Nov 1992  by Naochan!
*/

#include <stdio.h>
#include <string.h>
#include <dir.h>

#define _DEF_STDIO_H_
#include "dd.h"
#include "err.h"
#include "vfont.h"
#include "vraster.h"
#include "jgfont.h"

#ifdef	CC_JPN
#include <jctype.h>
#else
unsigned short jistojms(unsigned short);
int jisl1(unsigned short);
int jisl2(unsigned short);

#endif
int jislgaiji(unsigned short);

extern V_FONT *vfont[MAX_VFONT];
extern const int s_ratio[3];

int bezier, bezmax;
LOCATE w[97], keep, kv;	/* (2^5)*3 + 1 */

/* vfont.c */
void bigbox(BUFFER *, long, int);
V_JFM *get_vjfm(int vjfm_no);
int draw_character(VPARA_TBL *);

/* vraster.c */
int draw_fine(VPARA_TBL *);

/* vdata.c */
int get_yofs(VPARA_TBL *);

#ifndef	NOTATEGAKI
void TateKanji_type(unsigned int);

#endif

void get_bezfont(int, PREAMBLE *, FONT_INFO *);
int get_twelve(VPARA_TBL *, GET_TEN_SW);
BEZ_LOCATE bez_locate(VPARA_TBL *);
BEZ_LOCATE bez_emulate(VPARA_TBL *);

#ifdef BEZIERFONT
/**********************************
 *  get_twelve                    *
 *  12bit の座標データを取得する  *
 **********************************/
int get_twelve(VPARA_TBL *tbl_ptr, GET_TEN_SW get_ten_sw)
{
	static short bufx[VF_BUF_SIZE];	/* データ先読みバッファ */
	static int remaining_bits;
	static int remaining_words;
	static int remaining_words_save;
	static int buf_pos;
	static union {
		short s[2];
		long l;
	}
	d;
	static int buffering = 0;

	if (get_ten_sw == GET_DATA) {
		if (remaining_bits < 12) {
			d.s[1] = d.s[0];
			if (remaining_words == 0) {
				remaining_words
					= (read(tbl_ptr->vfn_file, bufx, VF_BUF_SIZE * 2)) / 2;
				remaining_words_save = remaining_words;
				buffering++;
				if (remaining_words == 0) {
					sprintf(tmp_buf,
							"[JGfont] 12 bits data error.(%#x) %s",
							tbl_ptr->char_code, tbl_ptr->v_font_name);
					error(WARNING, tmp_buf);
					return (-1);
				}
				buf_pos = 0;
			}
			d.s[0] = bufx[buf_pos++];
			remaining_words--;
			remaining_bits += 16;
		}
		remaining_bits -= 12;
		return ((int)((d.l >> remaining_bits) & 0xfff));
	}
	else if (get_ten_sw == KEEP_BUF && buffering == 1) {
		remaining_words = remaining_words_save;
		buf_pos = 0;
		buffering = 0;
		return (-1);
	}
	else {
		remaining_bits = 0;
		remaining_words = 0;
		buffering = 0;
		return (-1);
	}
}

BEZ_LOCATE
bez_locate(VPARA_TBL *tbl_ptr)
{
	int x, y;
	char type;
	BEZ_LOCATE bl;

	x = get_twelve(tbl_ptr, GET_DATA);
	y = get_twelve(tbl_ptr, GET_DATA);
	if (x == -1 || y == -1) {
		bl.type = BEZ_ERROR;
		return bl;
	}
	bl.x = 0x200 + ((x & 0x0400) ? -(x & 0x03ff) : (x & 0x03ff));
	bl.y = 0x200 - ((y & 0x0400) ? -(y & 0x03ff) : (y & 0x03ff));

	if (x & 0x800)
		bl.type = BEZ_BEZIER;
	else
		bl.type = BEZ_LINE;
	if (x == 0xfff)
		bl.type = BEZ_STOP;

	return bl;
}

BEZ_LOCATE
bez_emulate(VPARA_TBL *tbl_ptr)
{
	int i, j, tmpi, tmpj, bez_emu_dimen, target_size;
	long l0, l1, s;
	LOCATE tmp1, tmp2, tmp3;
	BEZ_LOCATE bl, rv;

	target_size = tbl_ptr->width;
  emu_rep:
	if (bezier > 0) {
		rv.x = w[(bezmax - bezier + 1) * 3].x;
		rv.y = w[(bezmax - bezier + 1) * 3].y;
		rv.type = BEZ_LINE;
		bezier--;
	}
	else {
		bl = bez_locate(tbl_ptr);
		switch (bl.type) {
		  case BEZ_LINE:
			  keep.x = rv.x = bl.x;
			  keep.y = rv.y = bl.y;
			  rv.type = BEZ_LINE;
			  break;
		  case BEZ_BEZIER:
			  w[0].x = keep.x;
			  w[0].y = keep.y;
			  w[1].x = bl.x;
			  w[1].y = bl.y;
			  bl = bez_locate(tbl_ptr);
			  w[2].x = bl.x;
			  w[2].y = bl.y;
			  bl = bez_locate(tbl_ptr);
			  w[3].x = bl.x;
			  w[3].y = bl.y;
			  keep.x = w[3].x;
			  keep.y = w[3].y;
			  l0 = (long)(w[1].x - w[0].x) * (w[2].y - w[0].y)
				  - (long)(w[2].x - w[0].x) * (w[1].y - w[0].y);
			  l1 = (long)(w[2].x - w[0].x) * (w[3].y - w[0].y)
				  - (long)(w[3].x - w[0].x) * (w[2].y - w[0].y);
			  s = ((l0 < 0L) ? -l0 : l0) + ((l1 < 0L) ? -l1 : l1);
			  s = (s * target_size) >> 10;
			  s = (s * target_size) >> 11;
			  if (s < 4L)
				  bez_emu_dimen = 0;
			  else if (s < 16L)
				  bez_emu_dimen = 1;
			  else if (s < 64L)
				  bez_emu_dimen = 2;
			  else if (s < 256L)
				  bez_emu_dimen = 3;
			  else if (s < 1024L)
				  bez_emu_dimen = 4;
			  else
				  bez_emu_dimen = 5;
			  for (i = 0; i < bez_emu_dimen; i++) {
				  for (j = 1 << i; j > 0; j--) {
					  tmpi = (j - 1) * 3;
					  tmpj = tmpi << 1;
					  tmp1.x = w[tmpi].x + w[tmpi + 1].x;
					  tmp1.y = w[tmpi].y + w[tmpi + 1].y;
					  tmp2.x = w[tmpi + 1].x + w[tmpi + 2].x;
					  tmp2.y = w[tmpi + 1].y + w[tmpi + 2].y;
					  tmp3.x = w[tmpi + 2].x + w[tmpi + 3].x;
					  tmp3.y = w[tmpi + 2].y + w[tmpi + 3].y;
					  w[tmpj + 6].x = w[tmpi + 3].x;
					  w[tmpj + 6].y = w[tmpi + 3].y;
					  w[tmpj + 1].x = (tmp1.x + 1) >> 1;
					  w[tmpj + 1].y = (tmp1.y + 1) >> 1;
					  w[tmpj + 2].x = (tmp1.x + tmp2.x + 2) >> 2;
					  w[tmpj + 2].y = (tmp1.y + tmp2.y + 2) >> 2;
					  w[tmpj + 3].x
						  = (tmp1.x + (tmp2.x << 1) + tmp3.x + 4) >> 3;
					  w[tmpj + 3].y
						  = (tmp1.y + (tmp2.y << 1) + tmp3.y + 4) >> 3;
					  w[tmpj + 4].x = (tmp2.x + tmp3.x + 2) >> 2;
					  w[tmpj + 4].y = (tmp2.y + tmp3.y + 2) >> 2;
					  w[tmpj + 5].x = (tmp3.x + 1) >> 1;
					  w[tmpj + 5].y = (tmp3.y + 1) >> 1;
				  }
			  }
			  rv.x = w[3].x;
			  rv.y = w[3].y;
			  rv.type = BEZ_LINE;
			  bezier = (bezmax = 1 << bez_emu_dimen) - 1;
			  break;
		  default:
			  rv.type = BEZ_STOP;
			  kv.x = kv.y = 0;
			  return rv;
		}
	}
	/*  rv.x = (int)(((long)(rv.x) * target_size + 512L) >> 10);
    rv.y = (int)(((long)(rv.y) * target_size + 512L) >> 10);
    if (rv.x == kv.x && rv.y == kv.y) goto emu_rep;
    kv.x = rv.x; kv.y = rv.y; */
	return rv;
}

#endif
/* end of jgfont.c */
