/*
 *  %W% %E%
 *
 * (C) Copyright IBM Corp. 1998 - All Rights Reserved
 *
 * Portions Copyright 1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 *
 * The original version of this source code and documentation is
 * copyrighted and owned by IBM. These materials are provided
 * under terms of a License Agreement between IBM and Sun.
 * This technology is protected by multiple US and International
 * patents. This notice and attribution to IBM may not be removed.
 */

#include <stdio.h>

#include "LETypes.h"
#include "FontObject.h"
#include "LESwaps.h"

FontObject::FontObject(char *fileName)
  : directory(NULL), numTables(0), searchRange(0),entrySelector(0),
    cmapTable(NULL), cmSegCount(0), cmSearchRange(0), cmEntrySelector(0),
	cmEndCodes(NULL), cmStartCodes(NULL), cmIdDelta(0), cmIdRangeOffset(0),
	headTable(NULL), hmtxTable(NULL), numGlyphs(0), numOfLongHorMetrics(0), file(NULL)
{
	file = fopen(fileName, "rb");

	if (file == NULL) {
		printf("?? Couldn't open %s", fileName);
		return;
	}

	SFNTDirectory tempDir;

	fread(&tempDir, sizeof tempDir, 1, file);

	numTables		= SWAPW(tempDir.numTables);
	searchRange		= SWAPW(tempDir.searchRange) >> 4;
	entrySelector	= SWAPW(tempDir.entrySelector);
	rangeShift		= SWAPW(tempDir.rangeShift) >> 4;

	int dirSize = sizeof tempDir + ((numTables - ANY_NUMBER) * sizeof(DirectoryEntry));

	directory = (SFNTDirectory *) new char[dirSize];

	fseek(file, 0L, SEEK_SET);
	fread(directory, sizeof(char), dirSize, file);

	initUnicodeCMAP();
}

FontObject::~FontObject()
{
    fclose(file);
	delete[] directory;
	delete[] cmapTable;
	delete[] headTable;
	delete[] hmtxTable;
}

void FontObject::deleteTable(void *table)
{
	delete[] (char *) table;
}

DirectoryEntry *FontObject::findTable(LETag tag)
{
	le_uint16 table = 0;
	le_uint16 probe = 1 << entrySelector;

	if (SWAPL(directory->tableDirectory[rangeShift].tag) <= tag) {
		table = rangeShift;
	}

	while (probe > (1 << 0)) {
		probe >>= 1;

		if (SWAPL(directory->tableDirectory[table + probe].tag) <= tag) {
			table += probe;
		}
	}

	if (SWAPL(directory->tableDirectory[table].tag) == tag) {
		return &directory->tableDirectory[table];
	}

	return NULL;
}

void *FontObject::readTable(LETag tag, le_uint32 *length)
{
	DirectoryEntry *entry = findTable(tag);

	if (entry == NULL) {
		*length = 0;
		return NULL;
	}

	*length = SWAPL(entry->length);

	void *table = new char[*length];

	fseek(file, SWAPL(entry->offset), SEEK_SET);
	fread(table, sizeof(char), *length, file);

	return table;
}

CMAPEncodingSubtable *FontObject::findCMAP(le_uint16 platformID, le_uint16 platformSpecificID)
{
	LETag cmapTag = 0x636D6170; // 'cmap'

	if (cmapTable == NULL) {
		le_uint32 length;

		cmapTable = (CMAPTable *) readTable(cmapTag, &length);
	}

	if (cmapTable != NULL) {
		le_uint16 i;
		le_uint16 nSubtables = SWAPW(cmapTable->numberSubtables);


		for (i = 0; i < nSubtables; i += 1) {
			CMAPEncodingSubtableHeader *esh = &cmapTable->encodingSubtableHeaders[i];

			if (SWAPW(esh->platformID) == platformID &&
				SWAPW(esh->platformSpecificID) == platformSpecificID) {
				return (CMAPEncodingSubtable *) ((char *) cmapTable + SWAPL(esh->encodingOffset));
			}
		}
	}

	return NULL;
}

void FontObject::initUnicodeCMAP()
{
	CMAPEncodingSubtable *encodingSubtable = findCMAP(3, 1);

	if (encodingSubtable == 0 ||
		SWAPW(encodingSubtable->format) != 4) {
		printf("Can't find unicode 'cmap'");
		return;
	}

	CMAPFormat4Encoding *header = (CMAPFormat4Encoding *) encodingSubtable;

	cmSegCount = SWAPW(header->segCountX2) / 2;
	cmSearchRange = SWAPW(header->searchRange);
	cmEntrySelector = SWAPW(header->entrySelector);
	cmRangeShift = SWAPW(header->rangeShift) / 2;
	cmEndCodes = &header->endCodes[0];
	cmStartCodes = &header->endCodes[cmSegCount + 1]; // + 1 for reservedPad...
	cmIdDelta = &cmStartCodes[cmSegCount];
	cmIdRangeOffset = &cmIdDelta[cmSegCount];
}

LEGlyphID FontObject::unicodeToGlyph(LEUnicode32 unicode32)
{
	if (unicode32 >= 0x10000) {
		return 0;
	}

	LEUnicode16 unicode = (LEUnicode16) unicode32;
	le_uint16 index = 0;
	le_uint16 probe = 1 << cmEntrySelector;
	LEGlyphID result = 0;

	if (SWAPW(cmStartCodes[cmRangeShift]) <= unicode) {
		index = cmRangeShift;
	}

	while (probe > (1 << 0)) {
		probe >>= 1;

		if (SWAPW(cmStartCodes[index + probe]) <= unicode) {
			index += probe;
		}
	}

	if (unicode >= SWAPW(cmStartCodes[index]) && unicode <= SWAPW(cmEndCodes[index])) {
		if (cmIdRangeOffset[index] == 0) {
			result = (LEGlyphID) unicode;
		} else {
			le_uint16 offset = unicode - SWAPW(cmStartCodes[index]);
			le_uint16 rangeOffset = SWAPW(cmIdRangeOffset[index]);
			le_uint16 *glyphIndexTable = (le_uint16 *) ((char *) &cmIdRangeOffset[index] + rangeOffset);

			result = SWAPW(glyphIndexTable[offset]);
		}

		result += SWAPW(cmIdDelta[index]);
	} else {
		result = 0;
	}

	return result;
}

le_uint16 FontObject::getUnitsPerEM()
{
	if (headTable == NULL) {
		LETag headTag = 0x68656164; // 'head'
		le_uint32 length;

		headTable = (HEADTable *) readTable(headTag, &length);
	}

	return SWAPW(headTable->unitsPerEm);
}

le_uint16 FontObject::getGlyphAdvance(LEGlyphID glyph)
{
	if (hmtxTable == NULL) {
		LETag maxpTag = 0x6D617870; // 'maxp'
		LETag hheaTag = 0x68686561; // 'hhea'
		LETag hmtxTag = 0x686D7478; // 'hmtx'
		le_uint32 length;
		HHEATable *hheaTable;
		MAXPTable *maxpTable = (MAXPTable *) readTable(maxpTag, &length);

		numGlyphs = SWAPW(maxpTable->numGlyphs);
		deleteTable(maxpTable);

		hheaTable = (HHEATable *) readTable(hheaTag, &length);
		numOfLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
		deleteTable(hheaTable);

		hmtxTable = (HMTXTable *) readTable(hmtxTag, &length);
	}

	le_uint16 index = glyph;

	if (glyph >= numGlyphs) {
		return 0;
	}

	if (glyph >= numOfLongHorMetrics) {
		index = numOfLongHorMetrics - 1;
	}

	return SWAPW(hmtxTable->hMetrics[index].advanceWidth);
}


