Milán Major

netscape-revival

1 branch
Code

sun-java/awt/macos/LMacCompStr.cp

// =================================================================================
// Copyright Netscape Communication 1996-1997
// Author: Frank Tang <ftang@netscape.com>
// =================================================================================
#include "LMacCompStr.h"
#include <LList.h>
//
// LEncodingTextList is current a private class that only used by this file
//
typedef struct {
	char* text;
	int16 len;
	int16 encoding;
} EncodingRunStruct;

class LEncodingTextList {
	public:
		LEncodingTextList();
		~LEncodingTextList();
		void AddItem(char* text, int16 len, int16 encoding);
		void Draw(LJavaFontList* font);
		void Reset();
	private:
		LList *mList;
};
LEncodingTextList::LEncodingTextList()
{
	mList = new LList(sizeof(EncodingRunStruct));
	ThrowIfNil_( mList );
}
LEncodingTextList::~LEncodingTextList()
{
	delete mList;
}
void
LEncodingTextList::AddItem(char* text, int16 len, int16 encoding)
{
	EncodingRunStruct newrun;
	newrun.text 	= text;
	newrun.len 		= len;
	newrun.encoding = encoding;
	mList->InsertItemsAt(1, arrayIndex_Last ,&newrun);
}
void
LEncodingTextList::Draw(LJavaFontList* font)
{
	EncodingRunStruct currun;
	LListIterator	iter( *mList, iterate_FromStart );
	while ( iter.Next( &currun ) )
	{
		font->SetTextFont(currun.encoding);
		::DrawText(currun.text, 0 , currun.len);
	}
}
void
LEncodingTextList::Reset()
{
	delete mList;
	mList = new LList(sizeof(EncodingRunStruct));
}

LMacCompStr::LMacCompStr() : LCompStr()
{
	// Empty
}
LMacCompStr::LMacCompStr(unicode* ustr, int32 len) 
	: LCompStr(ustr, len)
{
}
LMacCompStr::LMacCompStr(struct Hjava_lang_String *stringObject) 
	: LCompStr(stringObject)
{
}
LMacCompStr::LMacCompStr(HArrayOfChar *text, long offset, long length) 
	: LCompStr(text, offset, length)
{
}
LMacCompStr::LMacCompStr(ConstStr255Param unicodePStr) :  LCompStr(unicodePStr)
{
}
LMacCompStr::~LMacCompStr()
{
	// Empty
}
void LMacCompStr::Draw(LJavaFontList* font, Rect& rect)
{
	short x,y;
	y = this->Baseline(font, rect);
	x = ( ( rect.right - this->Width(font) + rect.left ) / 2) ;
	this->Draw(font, x, y);
}



#define CaculateJustifiedStart(j,l,r,w)		(((j) == teJustRight) \
												? ((r)-(w)) \
												: (((j) == teJustCenter) \
													? ((l) + (((r) - (l)) - (w)) / 2)  \
													: (l)))

void LMacCompStr::DrawJustified(LJavaFontList* font, Rect& inRect, Int16 justification )
{
	long base = this->Baseline(font, inRect);
	long height = this->Height(font);
	font->SetTextSize();
	font->SetTextStyle();
	
	Fixed totalWidth = ::Long2Fix(inRect.right - inRect.left);
	long accumWidth = 0;
	
	int16 encoding;
	char* text;
	LCompStrIterator	iter(this);
	LEncodingTextList	textList; 

	Int32	blackSpace, lineBytes;
	Fixed	wrapWidth = totalWidth;

	while(iter.Next(&encoding, (unsigned char**)&text))
	{
		StyledLineBreakCode	lineBreak;
		lineBytes = 1;
		short length = strlen(text);
		do {
			// we need to set the font every time because the textList->DrawAllItems may change font.
			font->SetTextFont(encoding);
			// wrapWidth have to be set in per line base
			// lineBytes have to be set in per call base - 
			// 				!= 0 first call in a line
			//			 	== 0 remainnig call in that line
			lineBreak = ::StyledLineBreak(text, length, 0, length, 0,
											&wrapWidth, &lineBytes);
											
			if(lineBreak != smBreakOverflow)	// the line is broken here
			{
				// this is the last run in that line. So we need to
				// take care VisibleLength stuff here
				blackSpace = ::VisibleLength(text, lineBytes);
				short visibleWidth = ::TextWidth(text,0,blackSpace);
				accumWidth += visibleWidth;	// accumulate the length for this line
				textList.AddItem(text, blackSpace, encoding);

				// Ok, now let's decide the 
				short x = CaculateJustifiedStart(justification, inRect.left, inRect.right, accumWidth);
				::MoveTo(x, base);
				textList.Draw(font);
				textList.Reset();
				
				// adjust the base to the baseline of the next line
				base += height;
				// reset accumWidth 
				accumWidth = 0;
				// adjust the text and length to the new position				
				text += lineBytes;
				length -= lineBytes;				
				// since we break the line, 
				// we need to setup warpWidth and lineBytes again
				wrapWidth = totalWidth;
				lineBytes = 1;
			}
			else			// the line is not broken here
			{
				short visibleWidth = ::TextWidth(text,0,length);
				textList.AddItem(text, length, encoding);
				lineBytes = 0;	// we need to setup lineBytes for every call.
				accumWidth += visibleWidth;	// accumulate the length for this line
			}
		} while(lineBreak != smBreakOverflow);
	}
	// We still need to draw the text in the list
	short x = CaculateJustifiedStart(justification, inRect.left, inRect.right, accumWidth);
	::MoveTo(x, base);
	textList.Draw(font);
}

void LMacCompStr::DrawLeft(LJavaFontList* font, Rect& rect)
{
	short y;
	y = this->Baseline(font, rect);
	this->Draw(font, rect.left, y);
}
void LMacCompStr::Draw(LJavaFontList* font, short x, short y)
{
	int16 encoding;
	unsigned char* text;
	font->SetTextSize();
	font->SetTextStyle();
	LCompStrIterator	iter(this);
	::MoveTo(x,y);
	while(iter.Next(&encoding, &text))
	{
		font->SetTextFont(encoding);
		::DrawText(text, 0 , strlen((char*)text));
	}
}
long LMacCompStr::DrawWidth(LJavaFontList* font, short x, short y)
{
	long accum = 0;
	int16 encoding;
	unsigned char* text;
	font->SetTextSize();
	font->SetTextStyle();
	::MoveTo(x,y);
	LCompStrIterator	iter(this);
	while(iter.Next(&encoding, &text))
	{
		short length = strlen((char*)text);
		font->SetTextFont(encoding);
		::DrawText(text, 0 , length);
		accum += ::TextWidth(text, 0 , length);
	}
	return accum;
}
long LMacCompStr::Width(LJavaFontList* font)
{
	long accum = 0;
	int16 encoding;
	unsigned char* text;
	font->SetTextSize();
	font->SetTextStyle();
	LCompStrIterator	iter(this);
	while(iter.Next(&encoding, &text))
	{
		font->SetTextFont(encoding);
		accum += ::TextWidth(text, 0 , strlen((char*)text));
	}
	return accum;
}
long LMacCompStr::Baseline(LJavaFontList* font, Rect& rect)
{
	long max = 0;
	int16 encoding;
	unsigned char* text;
	font->SetTextSize();
	font->SetTextStyle();
	LCompStrIterator	iter(this);
	while(iter.Next(&encoding, &text))
	{
		font->SetTextFont(encoding);
		FontInfo	fontInfo;
		::GetFontInfo(&fontInfo);
		long base = fontInfo.ascent + fontInfo.leading;
			// long base = fontInfo.ascent + fontInfo.leading - fontInfo.descent;
			// According to UTextDrawing::DrawWithJustification() we dont need to
			// minus fontInfo.descent here.
		if(base > max)
			max = base;
	}
	return ( max +  rect.top + rect.bottom) / 2;
}
long LMacCompStr::Height(LJavaFontList* font)
{
	long max = 0;
	int16 encoding;
	unsigned char* text;
	font->SetTextSize();
	font->SetTextStyle();
	LCompStrIterator	iter(this);
	while(iter.Next(&encoding, &text))
	{
		font->SetTextFont(encoding);
		FontInfo	fontInfo;
		::GetFontInfo(&fontInfo);
		long height = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
		if(height > max)
			max = height;
	}
	return max;
}