//	Zinc Application Framework - Z_DSP.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_dsp.hpp>
#include <z_string.hpp>
#define ZAF_DISPLAY_INFO
#include "gbl_def.cpp"

ZafDisplay::ZafDisplay(void) :
	coordinateType(ZAF_PIXEL), displayMode(ZAF_DISPLAY_COLOR),
	mode(ZAF_MODE_COPY), originX(0), originY(0), scaleNumerator(1),
	scaleDenominator(1)
{
	clipRegion.coordinateType = ZAF_PIXEL;
	clipRegion.left = clipRegion.top = -10000;
	clipRegion.right = clipRegion.bottom = 10000;
	palette.lineStyle = ZAF_LINE_SOLID;
	palette.fillPattern = ZAF_PTN_SOLID_FILL;
	palette.colorForeground = ZAF_CLR_BLACK;
	palette.colorBackground = ZAF_CLR_WHITE;
	palette.monoForeground = ZAF_MONO_BLACK;
	palette.monoBackground = ZAF_MONO_WHITE;
	palette.font = ZAF_FNT_DIALOG;
	memset(&palette.osPalette, 0, sizeof(OSPaletteID));
}

ZafDisplay::~ZafDisplay(void)
{
}

// --- Coordinates ---

void ZafDisplay::Origin(ZafCoordinate &x, ZafCoordinate &y) const
{
	x = originX;
	y = originY;
}

int ZafDisplay::Scale(int *getScaleNumerator, int *getScaleDenominator) const
{
	if (getScaleNumerator)
		*getScaleNumerator = scaleNumerator;
	if (getScaleDenominator)
		*getScaleDenominator = scaleDenominator;

	return ((int)(scaleNumerator * 100L / scaleDenominator));
}

ZafCoordinateType ZafDisplay::SetCoordinateType(ZafCoordinateType setCoordinateType)
{
	ZafCoordinateType oldCoordinateType = coordinateType;
	coordinateType = setCoordinateType;
	return (oldCoordinateType);
}

void ZafDisplay::SetOrigin(ZafCoordinate x, ZafCoordinate y)
{
	originX = ConvertXValue(x, coordinateType, ZAF_PIXEL);
	originY = ConvertYValue(y, coordinateType, ZAF_PIXEL);
}

int ZafDisplay::SetScale(int setScaleNumerator, int setScaleDenominator)
{
	scaleNumerator = setScaleNumerator;
	scaleDenominator = setScaleDenominator;

	return (Scale());
}

long ZafDisplay::ConvertXValue(long value, ZafCoordinateType typeIn, ZafCoordinateType typeOut) const
{
	// This function converts a value in "typeIn" coordinates to a value
	// in "typeOut" coordinates.  Rounding is used to eliminate drift.

	// Make sure conversion is necessary.
	if (typeOut == typeIn)
		return value;

	// Convert to pixel coordinates.
	if (typeIn == ZAF_CELL)
		value *= cellWidth;
	else if (typeIn == ZAF_MINICELL)
	{
		if (value >= 0)
			value = (value * 2 * cellWidth * miniNumeratorX + miniDenominatorX) /
				(2 * miniDenominatorX);
		else
			value = (value * 2 * cellWidth * miniNumeratorX - miniDenominatorX) /
				(2 * miniDenominatorX);
	}
	else if (typeIn == ZAF_POINTS)
	{
		if (value >= 0)
			value = (value * pixelsPerInchX + 36) / 72;
		else
			value = (value * pixelsPerInchX - 36) / 72;
	}
	else if (typeIn == ZAF_TWIPS)
	{
		if (value >= 0)
			value = (value * pixelsPerInchX + 720) / 1440;
		else
			value = (value * pixelsPerInchX - 720) / 1440;
	}
	else if (typeIn == ZAF_INCH_1000)
	{
		if (value >= 0)
			value = (value * pixelsPerInchX + 500) / 1000;
		else
			value = (value * pixelsPerInchX - 500) / 1000;
	}
	else if (typeIn == ZAF_MILLIMETER_10)
	{
		if (value >= 0)
			value = (value * pixelsPerInchX + 127) / 254;
		else
			value = (value * pixelsPerInchX - 127) / 254;
	}

	// Convert from pixel coordinates to specified coordinates.
	if (typeOut == ZAF_PIXEL)
		return (value);
	else if (typeOut == ZAF_CELL)
	{
		if (value >= 0)
			return ((value * 2 + cellWidth) / (2 * cellWidth));
		else
			return ((value * 2 - cellWidth) / (2 * cellWidth));
	}
	else if (typeOut == ZAF_MINICELL)
	{
		if (value >= 0)
			return ((value * 2 * miniDenominatorX + (cellWidth * miniNumeratorX)) /
				(2 * miniNumeratorX * cellWidth));
		else
			return ((value * 2 * miniDenominatorX - (cellWidth * miniNumeratorX)) /
				(2 * miniNumeratorX * cellWidth));
	}
	else if (typeOut == ZAF_POINTS)
	{
		if (value >= 0)
			return ((value * 144 + pixelsPerInchX) / (2 * pixelsPerInchX));
		else
			return ((value * 144 - pixelsPerInchX) / (2 * pixelsPerInchX));
	}
	else if (typeOut == ZAF_TWIPS)
	{
		if (value >= 0)
			return ((value * 2880 + pixelsPerInchX) / (2 * pixelsPerInchX));
		else
			return ((value * 2880 - pixelsPerInchX) / (2 * pixelsPerInchX));
	}
	else if (typeOut == ZAF_INCH_1000)
	{
		if (value >= 0)
			return ((value * 2000 + pixelsPerInchX) / (2 * pixelsPerInchX));
		else
			return ((value * 2000 - pixelsPerInchX) / (2 * pixelsPerInchX));
	}
	else if (typeOut == ZAF_MILLIMETER_10)
	{
		if (value >= 0)
			return ((value * 508 + pixelsPerInchX) / (2 * pixelsPerInchX));
		else
			return ((value * 508 - pixelsPerInchX) / (2 * pixelsPerInchX));
	}

	return (0); // Error condition.
}

long ZafDisplay::ConvertYValue(long value, ZafCoordinateType typeIn, ZafCoordinateType typeOut) const
{
	// This function converts a value in "typeIn" coordinates to a value
	// in "typeOut" coordinates.  Rounding is used to eliminate drift.

	// Convert to pixel coordinates.
	if (typeIn == ZAF_CELL)
		value *= cellHeight;
	else if (typeIn == ZAF_MINICELL)
	{
		if (value >= 0)
			value = (value * 2 * cellHeight * miniNumeratorY + miniDenominatorY) /
				(2 * miniDenominatorY);
		else
			value = (value * 2 * cellHeight * miniNumeratorY - miniDenominatorY) /
				(2 * miniDenominatorY);
	}
	else if (typeIn == ZAF_POINTS)
	{
		// Convert to pixel coordinates.
		if (value >= 0)
			value = (value * pixelsPerInchY + 36) / 72;
		else
			value = (value * pixelsPerInchY - 36) / 72;
	}
	else if (typeIn == ZAF_TWIPS)
	{
		// Convert to pixel coordinates.
		if (value >= 0)
			value = (value * pixelsPerInchY + 720) / 1440;
		else
			value = (value * pixelsPerInchY - 720) / 1440;
	}
	else if (typeIn == ZAF_INCH_1000)
	{
		if (value >= 0)
			value = (value * pixelsPerInchY + 500) / 1000;
		else
			value = (value * pixelsPerInchY - 500) / 1000;
	}
	else if (typeIn == ZAF_MILLIMETER_10)
	{
		if (value >= 0)
			value = (value * pixelsPerInchY + 127) / 254;
		else
			value = (value * pixelsPerInchY - 127) / 254;
	}

	// Convert from pixel coordinates to specified coordinates.
	if (typeOut == ZAF_PIXEL)
		return (value);
	else if (typeOut == ZAF_CELL)
	{
		if (value >= 0)
			return ((value * 2 + cellHeight) / (2 * cellHeight));
		else
			return ((value * 2 - cellHeight) / (2 * cellHeight));
	}
	else if (typeOut == ZAF_MINICELL)
	{
		if (value >= 0)
			return ((value * 2 * miniDenominatorY + (cellHeight * miniNumeratorY)) /
				(2 * miniNumeratorY * cellHeight));
		else
			return ((value * 2 * miniDenominatorY - (cellHeight * miniNumeratorY)) /
				(2 * miniNumeratorY * cellHeight));
	}
	else if (typeOut == ZAF_POINTS)
	{
		if (value >= 0)
			return ((value * 144 + pixelsPerInchY) / (2 * pixelsPerInchY));
		else
			return ((value * 144 - pixelsPerInchY) / (2 * pixelsPerInchY));
	}
	else if (typeOut == ZAF_TWIPS)
	{
		if (value >= 0)
			return ((value * 2880 + pixelsPerInchY) / (2 * pixelsPerInchY));
		else
			return ((value * 2880 - pixelsPerInchY) / (2 * pixelsPerInchY));
	}
	else if (typeOut == ZAF_INCH_1000)
	{
		if (value >= 0)
			return ((value * 2000 + pixelsPerInchY) / (2 * pixelsPerInchY));
		else
			return ((value * 2000 - pixelsPerInchY) / (2 * pixelsPerInchY));
	}
	else if (typeOut == ZAF_MILLIMETER_10)
	{
		if (value >= 0)
			return ((value * 508 + pixelsPerInchY) / (2 * pixelsPerInchY));
		else
			return ((value * 508 - pixelsPerInchY) / (2 * pixelsPerInchY));
	}

	return (0); // Error condition.
}

// bitmap
ZafError ZafDisplay::ConvertToOSBitmap(ZafBitmapStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::ConvertToZafBitmap(ZafBitmapStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyOSBitmap(ZafBitmapStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyZafBitmap(ZafBitmapStruct &bitmap)
{
	if (bitmap.array && !bitmap.StaticArray())
	{
		delete []bitmap.array;
		bitmap.array = ZAF_NULLP(ZafLogicalColor);
		bitmap.width = bitmap.height = 0;
	}
	return (ZAF_ERROR_NONE);
}

// icon
ZafError ZafDisplay::ConvertToOSIcon(ZafIconStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::ConvertToZafIcon(ZafIconStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyOSIcon(ZafIconStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyZafIcon(ZafIconStruct &icon)
{
	// Destroy the icon array.
	if (icon.array && !icon.StaticArray())
	{
		delete []icon.array;
		icon.array = ZAF_NULLP(ZafLogicalColor);
		icon.width = icon.height = 0;
	}
	return (ZAF_ERROR_NONE);
}

// mouse
ZafError ZafDisplay::ConvertToOSMouse(ZafMouseStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::ConvertToZafMouse(ZafMouseStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyOSMouse(ZafMouseStruct &)
{
	return (ZAF_ERROR_NONE);
}

ZafError ZafDisplay::DestroyZafMouse(ZafMouseStruct &mouse)
{
	// Destroy the mouse array.
	if (mouse.array && !mouse.StaticArray())
	{
		delete []mouse.array;
		mouse.array = ZAF_NULLP(ZafLogicalColor);
		mouse.width = mouse.height = 0;
	}
	return (ZAF_ERROR_NONE);
}

// --- Get ------------------------------------------------------------------

ZafLogicalColor ZafDisplay::Background(void) const
{
	return (palette.colorBackground);
}

ZafRegionStruct ZafDisplay::ClipRegion(void) const
{
	return (clipRegion);
}

ZafDisplayMode ZafDisplay::DisplayMode(void) const 
{ 
	return (displayMode); 
}

ZafClassName ZafDisplay::DisplayType(void) const 
{ 
	return (displayType); 
}

ZafLogicalFillPattern ZafDisplay::FillPattern(void) const
{
	return (palette.fillPattern);
}

ZafLogicalFont ZafDisplay::Font(void) const
{
	return (palette.font);
}

ZafLogicalColor ZafDisplay::Foreground(void) const
{
	return (palette.colorForeground);
}

ZafLogicalLineStyle ZafDisplay::LineStyle(void) const
{
	return (palette.lineStyle);
}

ZafLogicalMode ZafDisplay::Mode(void) const
{
	return (mode);
}

ZafLogicalColor ZafDisplay::MonoBackground(void) const
{
	return (palette.monoBackground);
}

ZafLogicalColor ZafDisplay::MonoForeground(void) const
{
	return (palette.monoForeground);
}

ZafPaletteStruct ZafDisplay::Palette(void) const
{
	return (palette);
}

// --- Set ------------------------------------------------------------------

ZafLogicalColor ZafDisplay::SetBackground(ZafLogicalColor color)
{
	ZafLogicalColor oldColor = palette.colorBackground;
	palette.colorBackground = color;
	return(oldColor);
}

ZafRegionStruct ZafDisplay::SetClipRegion(const ZafRegionStruct &setClipRegion)
{
	ZafRegionStruct oldClipRegion = clipRegion;
	clipRegion = setClipRegion;
	return (oldClipRegion);
}

ZafLogicalFillPattern ZafDisplay::SetFillPattern(ZafLogicalFillPattern fillPattern)
{
	ZafLogicalFillPattern oldFillPattern = palette.fillPattern;
	palette.fillPattern = fillPattern;
	return(oldFillPattern);
}

ZafLogicalFont ZafDisplay::SetFont(ZafLogicalFont font)
{
	ZafLogicalFont oldFont = palette.font;
	palette.font = font;	
	return(oldFont);
}

ZafLogicalColor ZafDisplay::SetForeground(ZafLogicalColor color)
{
	ZafLogicalColor oldColor = palette.colorForeground;
	palette.colorForeground = color;
	return(oldColor);
}

ZafLogicalLineStyle ZafDisplay::SetLineStyle(ZafLogicalLineStyle lineStyle)
{
	ZafLogicalLineStyle oldLineStyle = palette.lineStyle;
	palette.lineStyle = lineStyle;
	return (oldLineStyle);
}

ZafLogicalMode ZafDisplay::SetMode(ZafLogicalMode setMode)
{
	ZafLogicalMode oldMode = mode;
	mode = setMode;
	return (oldMode);
}

ZafLogicalColor ZafDisplay::SetMonoBackground(ZafLogicalColor color)
{
	ZafLogicalColor oldColor = palette.monoBackground;
	palette.monoBackground = color;
	return (oldColor);
}

ZafLogicalColor ZafDisplay::SetMonoForeground(ZafLogicalColor color)
{
	ZafLogicalColor oldColor = palette.monoForeground;
	palette.monoForeground = color;
	return (oldColor);
}

ZafPaletteStruct ZafDisplay::SetPalette(ZafPaletteStruct setPalette)
{
	ZafPaletteStruct oldPalette = palette;
	palette = setPalette;
	return (oldPalette);
}
