Blob Blame Raw
// Copyright © 1999 Middlesoft, Inc. All rights reserved.
// First Created By Lee Thomason.
// First Created On 09/08/1999.
// Last Modified On 11/09/1999.

/****************************************************************************************

				File Summary: FDTFonts.cpp

  This source file contains the definition for all low-level font-related functions,
  grouped by classes:

  		Class						Member Function

	FDTDefineFont				FDTDefineFont();
								~FDTDefineFont();
								U16 ID();
								void AddShapeGlyph(FShape*);
								void WriteToSWFStream(FSWFStream*);

	FDTDefineFont2				FDTDefineFont2(char*, U16, U16, U16);
								FDTDefineFont2(char*, U16, U16, U16, S16, S16, S16);
								~FDTDefineFont2();
								void AddShapeGlyph(FShape*, U16, S16, FRect*);
								void AddKerningRec(FKerningRec*);
								U16 nIndexBits();
								U16 ID(void);
								void WriteToSWFStream(FSWFStream*);

	FDTDefineFontInfo			FDTDefineFontInfo(const char*, U16, U16, U16, U16);
								void FDTDefineFontInfo::AddCode(U16);
								U16 FDTDefineFontInfo::ID();
								void WriteToSWFStream(FSWFStream*);

//	FGlyphEntry					FGlyphEntry(U16, S16);
//								S16 AdvanceValue();
//								void IncludeNBitInfo(U16, U16);
//								void WriteToSWFStream(FSWFStream*);

	FKerningRec					FKerningRec (U16, U16, short);
								void CodesWide (U16);
								void WriteToSWFStream(FSWFStream*);

	
	Note: All member functions of FGlyphEntry have been commented out. Need to fix.

****************************************************************************************/
#ifdef WIN32
#pragma warning(disable : 4786)
#endif

#include "FDTFonts.h"
#include "FDTShapes.h"

//////////////////////////////////////////////////////////////////////////////////////
//  --------  FButtonRecord1 ---------------------------------------------------------

FDTDefineFont::FDTDefineFont()
{

	characterID = FObjCollection::Increment();

	nFillBits = 1;
	nLineBits = 0;
}

FDTDefineFont::~FDTDefineFont()
{

	while (!shapeGlyphs.empty()) {

		delete shapeGlyphs.front();
		shapeGlyphs.pop_front();
	}
}

U16 FDTDefineFont::ID()
{

	return (U8)characterID;
}

void FDTDefineFont::AddShapeGlyph(FShape *_shape)
{

	_shape->SetFillBits(nFillBits);
	_shape->SetLineBits(nLineBits);
	shapeGlyphs.push_back(_shape);
}

void FDTDefineFont::WriteToSWFStream(FSWFStream *_SWFStream)
{

	U32 offsetsBufferSize = shapeGlyphs.size() * 2;

	FSWFStream body;
	FSWFStream shapeBuffer;
	std::list<U32> offsetsList;

	// get values for offsets and place them in a list
	// write list of shapeGlyphs to shape buffer
	offsetsList.push_back(offsetsBufferSize);

	std::list<FShape *>::iterator cursor;
	std::list<FShape *>::iterator nextToLast = shapeGlyphs.end();
	nextToLast--;
	for (cursor = shapeGlyphs.begin(); cursor != nextToLast; cursor++) {

		(*cursor)->WriteToSWFStream(&shapeBuffer);
		offsetsList.push_back(offsetsBufferSize + shapeBuffer.Size());
	}

	(*cursor)->WriteToSWFStream(&shapeBuffer);

	body.WriteWord((U32)characterID);

	// write offsetsList to body
	while (!offsetsList.empty()) {

		body.WriteWord((U32)offsetsList.front());
		offsetsList.pop_front();
	}

	//write shape buffer to body
	body.Append(&shapeBuffer);

	//put tag on body and write to stream
	_SWFStream->AppendTag(stagDefineFont, body.Size(), &body);
}

//////////////////////////////////////////////////////////////////////////////////////
//  --------  FDTDefineFont2 ---------------------------------------------------------

FDTDefineFont2::FDTDefineFont2(const char *_fontName, U16 _encodeType, U16 _italicFlag, U16 _boldFlag)
{
	fontID = FObjCollection::Increment();
	hasLayoutFlag = 1;
	encodeType = _encodeType;
	italicFlag = _italicFlag;
	boldFlag = _boldFlag;
	fontName = new FString((U8 *)_fontName);
	nFillBits = 1;
	nLineBits = 0;
	ascenderHeight = 0;
	descenderHeight = 0;
	leadingHeight = 0;
}

FDTDefineFont2::FDTDefineFont2(const char *_fontName, U16 _encodeType, U16 _italicFlag,
							   U16 _boldFlag, S16 _ascenderHeight,
							   S16 _descenderHeight, S16 _leadingHeight)
{

	fontID = FObjCollection::Increment();
	hasLayoutFlag = 1;
	encodeType = _encodeType;
	italicFlag = _italicFlag;
	boldFlag = _boldFlag;
	fontName = new FString((U8 *)_fontName);

	ascenderHeight = _ascenderHeight;
	descenderHeight = _descenderHeight;
	leadingHeight = _leadingHeight;

	nFillBits = 1;
	nLineBits = 0;
}

FDTDefineFont2::~FDTDefineFont2()
{

	delete fontName;

	while (!glyphs.empty()) {
		delete glyphs.front().shape;
		delete glyphs.front().bounds;
		glyphs.pop_front();
	}

	while (!kerningTable.empty()) {

		delete kerningTable.front();
		kerningTable.pop_front();
	}
}

void FDTDefineFont2::AddShapeGlyph(FShape *_shape, U16 _shapeCode, S16 _shapeAdvance,
								   FRect *_shapeBounds)
{
	// FIXME, don't know what nFillBits and nLineBits are
	_shape->SetFillBits(nFillBits);
	_shape->SetLineBits(nLineBits);
	Glyph g;
	g.advance = _shapeAdvance;
	g.bounds = _shapeBounds;
	g.code = _shapeCode;
	g.shape = _shape;
	glyphs.push_back(g);
}

void FDTDefineFont2::AddKerningRec(FKerningRec *_kerningRecord)
{

	if (hasLayoutFlag)
		kerningTable.push_back(_kerningRecord);
}

U16 FDTDefineFont2::nIndexBits()
{

	return (U16)FSWFStream::MinBits(glyphs.size() - 1, false);
}

U16 FDTDefineFont2::ID(void)
{

	return fontID;
}

void FDTDefineFont2::WriteToSWFStream(FSWFStream *_SWFStream)
{
	//	U32 offsetsSize		= (glyphs.size() * 2);
	//	U32 offsetsSizeWide = glyphs.size() * 4;
	//	U16 wideOffsetsFlag = 0;
	//	U16 wideCodesFlag	= 0;
	//	std::list<U32> offsetsList;

	// FIXME: add wide offset later
	S16 *offsetTable;
	if (glyphs.size() > 0)
		offsetTable = new S16[glyphs.size()];
	else
		offsetTable = 0;

	int i;

	FSWFStream body;
	FSWFStream shapeBuffer;

	std::list<Glyph>::iterator glyphCursor;
	for (glyphCursor = glyphs.begin(), i = 0; glyphCursor != glyphs.end(); glyphCursor++, i++) {
		offsetTable[i] = (S8)shapeBuffer.Size();
		glyphCursor->shape->WriteToSWFStream(&shapeBuffer);
	}

	body.WriteWord((U32)fontID);
	//write flags to body
	body.WriteBits((U32)hasLayoutFlag, 1);

	switch (encodeType) {

	case ShiftJIS:
		body.WriteBits((U32)1, 1);
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)0, 1);
		break;
	case Unicode:
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)1, 1);
		body.WriteBits((U32)0, 1);
		break;
	case ANSI:
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)1, 1);
		break;
	}
	body.WriteBits((U32)0, 1); // 0 for narrowOffsetFlag
	body.WriteBits((U32)0, 1); // 0 for narrowOffsetCode
	body.WriteBits((U32)italicFlag, 1);
	body.WriteBits((U32)boldFlag, 1);
	body.WriteByte(0); // FontFlagsReserved UB[8]

	body.WriteByte((U32)fontName->Length());
	fontName->WriteToSWFStream(&body, false); // write the name

	body.WriteWord((U32)glyphs.size());

	// write offsetsList to body
	if (glyphs.size() > 0)
		body.WriteLargeData((U8 *)offsetTable, 2 * glyphs.size());

	//write shape glyph buffer to body
	body.Append(&shapeBuffer);

	for (glyphCursor = glyphs.begin(), i = 0; glyphCursor != glyphs.end(); glyphCursor++, i++) {
		body.WriteWord(glyphCursor->code);
	}

	// write layout information to body
	if (hasLayoutFlag) {
		body.WriteWord((U32)ascenderHeight);
		body.WriteWord((U32)descenderHeight);
		body.WriteWord((U32)leadingHeight);

		for (glyphCursor = glyphs.begin(), i = 0; glyphCursor != glyphs.end(); glyphCursor++, i++) {
			body.WriteWord(glyphCursor->advance);
		}

		for (glyphCursor = glyphs.begin(), i = 0; glyphCursor != glyphs.end(); glyphCursor++, i++) {
			glyphCursor->bounds->WriteToSWFStream(&body);
		}

		body.WriteWord((U32)kerningTable.size());

		std::list<FKerningRec *>::iterator kernCursor;

		for (kernCursor = kerningTable.begin(); kernCursor != kerningTable.end(); kernCursor++) {

			(*kernCursor)->CodesWide(0); // 0 is narraw offset flag
			(*kernCursor)->WriteToSWFStream(&body);
		}
	}

	// create entire tag with record header
	_SWFStream->AppendTag(stagDefineFont2, body.Size(), &body);
	delete[] offsetTable;
}

//////////////////////////////////////////////////////////////////////////////////////
//  --------  FButtonRecord1 ---------------------------------------------------------

FDTDefineFontInfo::FDTDefineFontInfo(const char *_fontName, U16 _fontID,
									 U16 _encodeType, U16 _italicFlag,
									 U16 _boldFlag)
{

	characterID = FObjCollection::Increment();
	encodeType = _encodeType;
	italicFlag = _italicFlag;
	boldFlag = _boldFlag;

	fontID = _fontID;

	fontName = new FString((U8 *)_fontName);
}

FDTDefineFontInfo::~FDTDefineFontInfo()
{
	delete fontName;
}

void FDTDefineFontInfo::AddCode(U16 _someCode)
{

	codeTable.push_back(_someCode);
}

U16 FDTDefineFontInfo::ID()
{
	return (U8)characterID;
}

void FDTDefineFontInfo::WriteToSWFStream(FSWFStream *_SWFStream)
{

	U16 wideCodesFlag = 0;
	FSWFStream body;

	//determine whether 8 or 16 bit code fields are needed
	std::list<U16>::iterator cursor;
	for (cursor = codeTable.begin(); (cursor != codeTable.end()) && (wideCodesFlag == 0) // fixed from DV
		 ;
		 cursor++) {
		if ((*cursor) > 65530)
			wideCodesFlag = 1;
	}

	body.WriteWord((U32)fontID);

	body.WriteByte((U32)fontName->Length());

	fontName->WriteToSWFStream(&body, false);

	// 	body.WriteBits((U32) reservedFlags, 2);
	body.WriteBits((U32)0, 2);

	switch (encodeType) {

	case ShiftJIS:
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)1, 1);
		body.WriteBits((U32)0, 1);
		break;
	case Unicode:
		body.WriteBits((U32)1, 1);
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)0, 1);
		break;
	case ANSI:
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)0, 1);
		body.WriteBits((U32)1, 1);
		break;
	}

	body.WriteBits((U32)italicFlag, 1);
	body.WriteBits((U32)boldFlag, 1);

	body.WriteBits((U32)wideCodesFlag, 1);

	//write code table to body
	while (!codeTable.empty()) {
		if (wideCodesFlag) {
			body.WriteWord((U32)codeTable.front());
			codeTable.pop_front();
		} else {
			body.WriteByte((U32)codeTable.front());
			codeTable.pop_front();
		}
	}

	// create entire tag with record header
	_SWFStream->AppendTag(stagDefineFontInfo, body.Size(), &body);
}

//////////////////////////////////////////////////////////////////////////////////////
//  --------  FGlyphEntry ------------------------------------------------------------

// FGlyphEntry::FGlyphEntry(U16 index, S16 advance)
// {
//
// 	glyphIndex = index;
// 	glyphAdvance = advance;
//
// }
//
//
// S16 FGlyphEntry::AdvanceValue()
// {
//
// 	return glyphAdvance;
//
// }

//	Used to specify the nBit info for the entries.  This is determined and passed to
//	the glyph entry just before write time.

// void FGlyphEntry::IncludeNBitInfo(U16 _nIndexBits, U16 _nAdvanceBits)
// {
//
// 	nIndexBits = _nIndexBits;
// 	nAdvanceBits = _nAdvanceBits;
// }
//
// void FGlyphEntry::WriteToSWFStream(FSWFStream *_SWFStream)
// {
//
// 	_SWFStream->WriteBits((U32) glyphIndex, nIndexBits);
// 	_SWFStream->WriteBits((U32) glyphAdvance, nAdvanceBits);
//
// }

//////////////////////////////////////////////////////////////////////////////////////
//  --------  FKerningRec ------------------------------------------------------------

FKerningRec::FKerningRec(U16 cd1, U16 cd2, short krnAdj)
{

	wideCodesFlag = 0; // default not wide
	code1 = cd1;
	code2 = cd2;
	kerningAdjust = krnAdj;
}

void FKerningRec::CodesWide(U16 _flag)
{

	if (_flag)
		wideCodesFlag = 1;
	else
		wideCodesFlag = 0;
}

void FKerningRec::WriteToSWFStream(FSWFStream *b)
{
	if (wideCodesFlag) {
		b->WriteWord((U32)code1);
		b->WriteWord((U32)code2);
	} else {
		b->WriteByte((U32)code1);
		b->WriteByte((U32)code2);
	}

	b->WriteWord((U32)kerningAdjust);
}