/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-93 by SHIMA
 *
 *  size.c :
 *      Apr. 29, 1989 : 2nd edition
 *
 *  このモジュールは，includeするheader-fileが device-dependentとなっている．
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 */

#include <stdio.h>
#include "dd.h"
#include "err.h"
#include "prtout.h"

#define min(a,b) ( (a) < (b) ? (a) : (b) )
#define omit_divide(a,b) ( ( (a)/(b) ) * (b) )
/* ｂで割り切れるようにする（端数切捨て）*/
#define raise_divide(a,b) ( ( ( (a) + (b) - 1 ) / (b) ) * (b) )
/* 同上　　　　　　　　　　（端数切上げ）*/

PIXEL vert_divide = VERT_DIVIDE;

/* main.c */
extern DIMENSION dviout_dimension;

#ifndef	USE_WINAPI
SCALED_PT mult20(SCALED_PT m, SCALED_PT n)
/*  return (m * n >> 20)  */
{
# if	1
	unsigned long t, hm, hn;

	t  = (((unsigned long)(m & 0xffff)*(unsigned long)(n & 0xffff)) >>18);
	t += (((hm = (unsigned long)(m >> 16)))*(unsigned long)(n & 0xffff)) >>2;
	t += ((unsigned long)(m & 0xffff)*(hn = (unsigned long)(n >> 16)))   >>2;
	return (SCALED_PT)((hm*hn << 12) + (t >> 2));
# else
	return (SCALED_PT)(((double)m * (double)n)/0x100000L);
# endif
}
#endif

#ifdef	NOFLOAT
	   long sp_per_pxl;
static long v_per_pxl;
long sp_per_h;
long v_per_h;
void set_convert(SIZE_PARA val, int h, int v)
	/* 係数を登録する．
	 */
{
	sp_per_pxl = val;
	sp_per_h = sp_per_pxl / 2;
	v_per_pxl = sp_per_pxl * (long)h / (long)v;
	v_per_h = v_per_pxl / 2;
}

#else
static double pxl_per_sp;
static double v_per_sp;
void set_convert(SIZE_PARA val, int h, int v)
	/* 係数を登録する．
	 */
{
	pxl_per_sp = 1 / val;
	v_per_sp = pxl_per_sp * v / h;
}

#endif

#ifdef	NOFLOAT
#define PIXEL_MAX 32767
#define PIXEL_MIN -32768
#else
#define PIXEL_MAX 32767.0
#define PIXEL_MIN -32768.0
#endif

#ifdef	NOFLOAT
/*
 * See sptopxl.asm
 */
PIXEL sptopixel( SCALED_PT sp )
{
   return( (int)( (sp + sp_per_h)/sp_per_pxl ));
}

PIXEL vtopixel( SCALED_PT sp )
{
   return( (int)( (sp + v_per_h)/v_per_pxl ));
}

#else
PIXEL sptopixel(SCALED_PT sp)
	/* scaled point から pixel 単位に変換
	 */
{
	double pxl;

	ENTER("sptopixel");

	pxl = ((double)sp) * pxl_per_sp;
	if (pxl < PIXEL_MIN || pxl > PIXEL_MAX)
		error(MATH_ERROR, "Conversion over(sp -> pixel)");

	RETURN((PIXEL)pxl);
}

PIXEL vtopixel(SCALED_PT sp)
	/* scaled point から pixel 単位に変換
	 */
{
	double pxl;

	ENTER("vtopixel");

	pxl = ((double)sp) * v_per_sp;
	if (pxl < PIXEL_MIN || pxl > PIXEL_MAX)
		error(MATH_ERROR, "Conversion over(sp -> pixel)");

	RETURN((PIXEL)pxl);
}

#endif

int set_size(PIXEL h, PIXEL v, PIXEL h_max, PIXEL v_max,
			 PIXEL *h_ptr, PIXEL *v_ptr)
	/* VRAM表示枠を計算する．
		 */
{
	PIXEL _v;
	int split;

	ENTER("set_size");

	if (h_max > 0 && h > h_max) {
#ifdef	JAPANESE
		  error(BAD_SYSTEM, "テキストがプリンターのドット幅を超えています．");
#else
		  error(BAD_SYSTEM, "Too wide Text!");
#endif
		h = h_max;
	}
	if ((h = raise_divide(h, HORI_DIVIDE)) <= 8)
		h = HORI_DIVIDE*2;
	dviout_dimension.output_width = *h_ptr = h;

	if (v_max > 0 && v > v_max) {
#ifdef	JAPANESE
		error(BAD_SYSTEM, "テキストの１ページの長さが大きすぎます．");
#else
		error(BAD_SYSTEM, "A page is too long!");
#endif
		v = v_max;
	}
	dviout_dimension.output_height = v = raise_divide(v, vert_divide);
	_v = (PIXEL)(bitmap_buf_pointer->size / ((long)h / 8));
	_v = omit_divide(_v, vert_divide);

	*v_ptr = min(v, _v);

	split = (v + *v_ptr - 1) / *v_ptr;
	RETURN(split);
}

/* end of file : size.c */
