/*
 *----------------------------------------------------------------------
 *
 * PROGRAM	 : gksmc
 *
 * FILE		 : annexe_8.c
 *
 * CONTENTS	 : Routines to read items from an Annex E metafile which
 *		   are in group E.8 and E.9 of the Annex - items for
 *		   workstation attributes and items for transformations
 *		   respectively.
 *
 * ANNEX E ITEMS : Set Line Representation
 *		   Set Marker Representation
 *		   Set Text Representation
 *		   Set Fill Area Representation
 *		   Set Pattern Representation
 *		   Set Colour Representation
 *		   Set Clipping Rectangle
 *		   Set Workstation Window
 *		   Set Workstation Viewport
 *
 * GLOBALS USED  : MF_infile, MF_outfile, VDC_lower, VDC_upper,
 *		   DevSpM, DevScale
 *
 * DATE		 : 26th April 1988
 *
 *----------------------------------------------------------------------
 */


#include <stdio.h>
#include "annexe.h"
#include "cgm.h"
#include "defns.h"
#include "tables.h"

extern FILE *MF_infile,
       *MF_outfile;


/*
 *-------------------------------------------------------------------------
 * AEpolyline_rep:
 *	Polyline Representation maps directly to the CGM item Line
 * Representation.
 *-------------------------------------------------------------------------
 */
AEpolyline_rep()
{
	int     line_index,
	        linetype_no,
	        line_colour;
	double  line_width;

	read_string_int(MF_infile, &line_index, DEFAULT);
	if (line_index < 1)
		write_error(38);
	read_string_int(MF_infile, &linetype_no, DEFAULT);
	read_string_real(MF_infile, &line_width, DEFAULT);
	if (line_width < 0.0)
		write_error(39);
	read_string_int(MF_infile, &line_colour, DEFAULT);
	if (line_colour < 0)
		write_error(40);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, line_index);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, linetype_no);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, line_width);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, line_colour);
}


/*
 *-------------------------------------------------------------------------
 * AEmarker_rep:
 *	Polymarker Representation maps directly to the CGM item Marker
 * Representation.
 *-------------------------------------------------------------------------
 */
AEmarker_rep()
{
	int     marker_index,
	        marker_type,
	        marker_colour;
	double  marker_size;

	read_string_int(MF_infile, &marker_index, DEFAULT);
	if (marker_index < 1)
		write_error(41);
	read_string_int(MF_infile, &marker_type, DEFAULT);
	read_string_real(MF_infile, &marker_size, DEFAULT);
	if (marker_size < 0.0)
		write_error(42);
	read_string_int(MF_infile, &marker_colour, DEFAULT);
	if (marker_colour < 0)
		write_error(43);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, marker_index);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, marker_type);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, marker_size);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, marker_colour);
}


/*
 *-------------------------------------------------------------------------
 * AEtext_rep:
 *	The Text Representation item is the same in Annex E and CGM.
 *-------------------------------------------------------------------------
 */
AEtext_rep()
{
	int     text_index,
	        text_font,
	        text_prec,
	        text_colour;
	double  char_exp,
	        char_space;

	read_string_int(MF_infile, &text_index, DEFAULT);
	if (text_index < 1)
		write_error(44);
	read_string_int(MF_infile, &text_font, DEFAULT);
	read_string_int(MF_infile, &text_prec, DEFAULT);
	check_param_range(text_prec, 0, 2, 45);
	read_string_real(MF_infile, &char_exp, DEFAULT);
	read_string_real(MF_infile, &char_space, DEFAULT);
	read_string_int(MF_infile, &text_colour, DEFAULT);
	if (text_colour < 0)
		write_error(46);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, text_index);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, text_font);
	write_separator(MF_outfile, SEP);
	write_enum_value(MF_outfile, E_TEXTPREC, text_prec);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, char_space);
	write_separator(MF_outfile, SEP);
	write_real(MF_outfile, char_exp);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, text_colour);
}


/*
 *-------------------------------------------------------------------------
 * AEfill_area_rep:
 *	Fill Area Representation translates to Fill Representation which
 * is the same except that the Annex E item has a parameter Interior Style
 * Index for pattern and hatch, whilst CGM has two separate parameters for
 * Pattern Index and Hatch Index.
 *-------------------------------------------------------------------------
 */
AEfill_area_rep()
{
	int     fa_index,
	        fa_int_style,
	        fa_style_index,
	        fa_colour;

	read_string_int(MF_infile, &fa_index, DEFAULT);
	if (fa_index < 1)
		write_error(47);
	read_string_int(MF_infile, &fa_int_style, DEFAULT);
	check_param_range(fa_int_style, 0, 4, 48);
	read_string_int(MF_infile, &fa_style_index, DEFAULT);
	read_string_int(MF_infile, &fa_colour, DEFAULT);
	if (fa_colour < 0)
		write_error(49);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, fa_index);
	write_separator(MF_outfile, SEP);
	write_enum_value(MF_outfile, E_INTERIOR, fa_int_style);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, fa_style_index);	/* Hatch Index */
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, fa_style_index);	/* Pattern Index */
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, fa_colour);
}


/*
 *-------------------------------------------------------------------------
 * AEpatt_rep:
 *	Pattern Representation maps to the CGM item Pattern Table.
 *-------------------------------------------------------------------------
 */
AEpatt_rep()
{
	int     pat_index,
	        num_cols,
	        num_rows,
	       *colr_indices,
	        num_indices;

	read_string_int(MF_infile, &pat_index, DEFAULT);
	if (pat_index < 1)
		write_error(50);
	read_string_int(MF_infile, &num_cols, DEFAULT);
	read_string_int(MF_infile, &num_rows, DEFAULT);
	num_indices = num_cols * num_rows;
	colr_indices = (int *) calloc(num_indices, sizeof(int));
	read_int_list(MF_infile, colr_indices, num_indices);
	write_item_name(MF_outfile, OP_TABLE, DEFAULT);
	write_separator(MF_outfile, SOFTSEP);
	write_int(MF_outfile, pat_index);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, num_cols);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, num_rows);
	write_separator(MF_outfile, SEP);
	write_int(MF_outfile, 0);	/* use default colour precision */
	write_cell_row(MF_outfile, colr_indices, num_indices);
	cfree(colr_indices);
}


/*
 *-------------------------------------------------------------------------
 * AEcolour_rep:
 *	The Annex E item Colour Representation translates to the CGM item
 * Colour Table. Annex E expects real values in the range 0.0 - 1.0 for the
 * red, green and blue specifiers, whilst CGM expects integers.
 * The colour definition specified is stored in the list ColourDefList.
 * Colour definitions must be remembered because if the current picture
 * is closed and a new one opened, the changes to the colour table have to
 * be written at the head of the new picture.
 *-------------------------------------------------------------------------
 */
AEcolour_rep()
{
	int     colr_index;
	double  red,
	        green,
	        blue;
	ColourDef colr_def;

	read_string_int(MF_infile, &colr_index, DEFAULT);
	read_string_real(MF_infile, &red, DEFAULT);
	read_string_real(MF_infile, &green, DEFAULT);
	read_string_real(MF_infile, &blue, DEFAULT);
	if (colr_index < 0)
		write_error(25);
	colr_def.red = (int) (red * colr_prec);
	colr_def.green = (int) (green * colr_prec);
	colr_def.blue = (int) (blue * colr_prec);
	colr_def.ColrIndex = colr_index;
	update_colour_list(colr_def);
	write_colour_defn(MF_outfile, colr_def);
}


/*
 *-------------------------------------------------------------------------
 * AEclip_rect:
 *	The Clipping Rectangle item is the same in Annex E and CGM except
 * that the bounds are given in the order xmin, xmax, ymin, ymax in
 * Annex E, whereas the CGM item takes two points, ie (xmin, ymin),
 * (xmax, ymax).
 *-------------------------------------------------------------------------
 */
AEclip_rect()
{
	Point   lower,
	        upper;	/* xmin, xmax, ymin, ymax */
	double  tmp;

	read_point(MF_infile, &lower);
	read_point(MF_infile, &upper);
	tmp = lower.y;
	lower.y = upper.x;
	upper.x = tmp;
	CGMclip_rectangle(lower, upper);
}


/*
 *-------------------------------------------------------------------------
 * AEwks_window:
 *	CGM does not have an item which corresponds to the Workstation
 * Window item. This item implies a dynamic change in the image, and thus
 * can not be directly handled by a CGM. Addendum 1 does not include
 * an appropriate item, so the guidelines given in ISO 8632/1 Annex E
 * are followed - the current picture is finished and a new one opened
 * with the VDC extent changed.
 *-------------------------------------------------------------------------
 */
AEwks_window()
{
	double  tmp;

	read_point(MF_infile, &VDC_lower);
	read_point(MF_infile, &VDC_upper);
	tmp = VDC_lower.y;
	VDC_lower.y = VDC_upper.x;
	VDC_upper.x = tmp;
	write_item_name(MF_outfile, CGM_TABLE, ENDPIC);
	write_separator(MF_outfile, TERMINATOR);
	start_picture();
}


/*
 *-------------------------------------------------------------------------
 * AEwks_viewport:
 *	The Annex E item Workstation Viewport tranlates to the CGM item
 * Device Viewport. The Annex E metafile does not carry any information
 * concerning the specification form used - 'Metric' or 'other'. The
 * specification mode to be used in the CGM item (Fraction, mm, or
 * physical device units) can be forced by specifying in the defaults
 * file using the DEVSPEC entry followed by FRACTION, MM or PHYDEVICEUNITS.
 * The scale factor can be given using the DEVSCALE entry in the defaults
 * file, followed by a real value.
 *	If the Spec Mode is not user specified then an 'informed' guess
 * is made - the values for the viewport bounds are checked, if all values
 * are in the range 0.0 - 1.0 then MM is used with a default scale factor
 * of 1000, otherwise the values are taken as Physical device units.
 *-------------------------------------------------------------------------
 */
AEwks_viewport()
{
	Point   upper,
	        lower;
	double  tmp;

	read_point(MF_infile, lower);
	read_point(MF_infile, upper);
	tmp = lower.y;
	lower.y = upper.x;
	upper.x = tmp;
	if (DevSpM == FRACTION)
	{	/* Fraction of device viewport */
		write_item_name(MF_outfile, CGM_TABLE, DEVICEVIEWPORTMODE);
		write_separator(MF_outfile, SOFTSEP);
		write_enum_value(MF_outfile, E_DVSPECMODE, FRACTION);
		write_separator(MF_outfile, SOFTSEP);
		write_real(MF_outfile, 1.0);
		write_separator(MF_outfile, TERMINATOR);
		write_item_name(MF_outfile, DEFAULT);
		write_separator(MF_outfile, SOFTSEP);
		write_real_point(MF_outfile, lower);
		write_separator(MF_outfile, SEP);
		write_real_point(MF_outfile, upper);
	}
	else if (DevSpM == MM || (DevSpM == UNKNOWN && lower.x <= 1 && lower.y <= 1
			&& upper.x <= 1 && upper.y <= 1))
	{
		write_item_name(MF_outfile, CGM_TABLE, DEVICEVIEWPORTMODE);
		write_separator(MF_outfile, SOFTSEP);
		write_enum_value(MF_outfile, E_DVSPECMODE, MM);
		write_separator(MF_outfile, SEP);
		write_real(MF_outfile, DevScale);
		write_separator(MF_outfile, TERMINATOR);
		write_item_name(MF_outfile, DEFAULT);
		write_separator(MF_outfile, SOFTSEP);
		write_real_point(MF_outfile, lower);
		write_separator(MF_outfile, SEP);
		write_real_point(MF_outfile, upper);
	}
	else
	{
		write_item_name(MF_outfile, CGM_TABLE, DEVICEVIEWPORTMODE);
		write_separator(MF_outfile, SOFTSEP);
		write_enum_value(MF_outfile, E_DVSPECMODE, PHYDEVICEUNITS);
		write_separator(MF_outfile, SEP);
		write_real(MF_outfile, 1.0);
		write_separator(MF_outfile, TERMINATOR);
		write_item_name(MF_outfile, DEFAULT);
		write_separator(MF_outfile, SOFTSEP);
		write_int_point(MF_outfile, lower);
		write_separator(MF_outfile, SEP);
		write_int_point(MF_outfile, upper);
	}
}
