Filter:   InfoImg
download texthandler.cc
Language: C++
LOC: 215
Project Info
Ultima Online Project(uop)
Server: SourceForge
Type: cvs
SourceForge\u\uop\uop\uop\
   acinclude.m4
   aclocal.m4
   action.cc
   action.h
   animation.cc
   animation.h
   artexport.cc
   artfactory.cc
   artfactory.h
   audio.cc
   audio.h
   btree.cc
   btree.h
   cache.h
   cliloc.cc
   cliloc.h
   config.h.in
   configure.in
   cvs2cl.pl
   entity.cc
   entity.h
   gumps.cc
   gumps.h
   interface.cc
   interface.h
   interfacegumps.cc
   interfacegumps.h
   interfacehandler.cc
   interfacehandler.h
   intrface.def
   Makefile.am
   Makefile.in
   message.cc
   message.h
   musicmap.def
   network.cc
   network.h
   patchhandler.cc
   patchhandler.h
   readable.pl
   serverhandler.cc
   serverhandler.h
   sprite.cc
   sprite.h
   stamp-h.in
   texthandler.cc
   texthandler.h
   tiledata.cc
   tiledata.h
   unreadable.pl
   uop.cc
   uop.cfg
   uop.dox
   uop.h
   uopconfig.cc
   uopconfig.h
   uosprite.h
   uostub.pl
   world.cc
   world.h

#include "uop.h"
#include <SDL/SDL.h>
#include <SDL/SDL_endian.h>
#include <iostream>
#include "texthandler.h"
#include "uopconfig.h"
#include "gumps.h"

extern UOPConfig *config;
extern SDL_Surface *screen;
extern Gumps *gumps;

TextHandler::TextHandler()
{
	string fontfname=config->encapDatLoc("fonts.mul");
	fontfile.open(fontfname.c_str(),ios::in|ios::binary);
	if (!fontfile.is_open())
	{
	        cerr<<"Couldn't open "<<fontfname<<endl;
		exit(1);
	}
	unifont[0]=new UniFont(config->encapDatLoc("unifont.mul"));
	unifont[1]=new UniFont(config->encapDatLoc("unifont1.mul"));
	unifont[2]=new UniFont(config->encapDatLoc("unifont2.mul"));
}

TextHandler::~TextHandler()
{
	fontfile.close();
}

void TextHandler::drawString(string &str,Uint16 font,
		Uint16 x,Uint16 y,Uint16 hue)
{
	Uint16 *scr,*scrn;
	char ch;

	Hue &hued=gumps->getHue(hue);
	
	scrn=(Uint16 *)screen->pixels;

	UOFont &uoFont=getFont(font);
	Uint8 height=uoFont.chars['M'-32].height;
	Uint8 width=uoFont.chars['M'-32].width;
	if (y<height || y>480 || x>640-width)
		return;

	Uint16 color;

	string::iterator istr;
	for (istr=str.begin();istr!=str.end();istr++)
	{
		ch=(*istr)-32;
		width=uoFont.chars[ch].width;
		height=uoFont.chars[ch].height;
		Uint16 *data=(Uint16 *)uoFont.chars[ch].data;

		scr=scrn+((screen->pitch*(y-height))>>1)+x;
		Uint16 delta=(screen->pitch>>1)-width;
		for (Uint16 sy=0;sy<height;sy++,scr+=delta)
			for (Uint16 sx=0;sx<width;sx++,scr++)
			{
				color=*data++;
				if (color)
				{
					if (hue)
						if ((color&0x1f)==((color>>5)&0x1f) && (color&0x1f)==((color>>10)&0x1f))
							color=hued.colors[color&0x1f];
					*scr=((color&0x7fe0)<<1)|(color&0x1f);
				}
			}
		x+=width;
	}
}

void TextHandler::drawUnicodeString(string &str,Uint16 font,
		Uint16 x,Uint16 y,Uint32 hue)
{
	Uint16 *scr,*scrn;
	unsigned short ch;
	Uint32 source;

	scrn=(Uint16 *)screen->pixels;

	Uint16 color=((hue&0xf8)<<8)|((hue&0xf800)>>5)|((hue&0xf80000)>>19);
	Uint8 *dPtr;
	string::iterator istr;
	for (istr=str.begin();istr<str.end();istr++)
	{
		ch = ((unsigned char)(*istr)) << 8;
		istr++;
		ch += (unsigned char)(*istr);
		if (unifont[font]->chars[ch].data==NULL)
			unifont[font]->loadChar(ch);
		Uint8 width=unifont[font]->chars[ch].width;
		Uint8 height=unifont[font]->chars[ch].height;
		Uint8 bwidth=unifont[font]->chars[ch].bwidth;
		Sint8 xOff=unifont[font]->chars[ch].xOff;
		Sint8 yOff=unifont[font]->chars[ch].yOff;
	
		Uint16 delta=(screen->pitch>>1);
		scrn+=width;
		scr=scrn+(yOff+y)*delta+x+xOff;
		scrn++;	//skip a space
		dPtr=unifont[font]->chars[ch].data;
		Uint8 bDelta=32-width;

		for (int sy=0;sy<height;sy++,scr+=delta,dPtr+=bwidth)
		{
			source=SDL_SwapBE32(*(Uint32*)dPtr)>>bDelta;
			Uint16 *bScr=scr;
			while (source)
			{
				if (source&1) *bScr=color;
				bScr--;
				source>>=1;
			}
		}
	}
}

Uint16 TextHandler::unicodeWidth(string &str,Uint16 font)
{
	char ch;
	Uint16 width=0;
	string::iterator istr;
	for (istr=str.begin();istr<str.end();istr++)
	{
		ch = ((unsigned char)(*istr)) << 8;
		istr++;
		ch += (unsigned char)(*istr);

		if (unifont[font]->chars[ch].data==NULL)
			unifont[font]->loadChar(ch);
		width+=unifont[font]->chars[ch].width+1;
	}
	if (width) width--;  //remove trailing space
	return width;
}

Uint8 TextHandler::unicodeHeight(Uint16 font)
{
	if (unifont[font]->chars['M'].data==NULL)
		unifont[font]->loadChar('M');
	return unifont[font]->chars['M'].height;
}

Uint16 TextHandler::getWidth(string &str,Uint16 font)
{
	char ch;
	Uint16 width=0;
	string::iterator istr;
	UOFont &uoFont=getFont(font);
	for (istr=str.begin();istr!=str.end();istr++)
	{
		ch=(*istr)-32;
		width+=uoFont.chars[ch].width;
	}
	return width;
}
Uint8 TextHandler::getHeight(Uint16 font)
{
	UOFont &uoFont=getFont(font);
	return uoFont.chars['M'].height;
}

UOFont &TextHandler::getFont(Uint16 font)
{
	char fontid,width,height,base;
	UOFont &idx=fonts[font];
	if (idx.loaded) return idx;
	
	fontfile.seekg(0);
	for (int i=0;i<10;i++)
	{
		UOFont &fnt=fonts[i];
		fontfile.get(fontid);
		for (int c=0;c<224;c++)
		{
			fontfile.get(width);
			fontfile.get(height);
			fontfile.get(base);
			fnt.chars[c].data=new Uint8[width*height*2];
			fontfile.read((char *)fnt.chars[c].data,width*height*2);
			fnt.chars[c].width=width;
			fnt.chars[c].height=height;
		}
		fnt.loaded=true;
	}
	return fonts[font];
}

UOFont::UOFont()
{
	loaded=false;
}
UOFont::~UOFont()
{
}

UOChar::UOChar()
{
	data=NULL;
}
UOChar::~UOChar()
{
	if (data) delete [] data;
}

UniFont::UniFont(string fname)
{
	file.open(fname.c_str(),ios::in|ios::binary);
	if (!file.is_open())
	{
		cerr<<"Couldn't open "<<fname.c_str()<<endl;
		exit(1);
	}
	offsets=new Uint32[0x10000];
	file.read((char *)offsets,0x40000);
	for (int i=0; i<0x10000; i++)
		offsets[i]=SDL_SwapLE32(offsets[i]);
}
UniFont::~UniFont()
{
	file.close();
	delete [] offsets;
}

void UniFont::loadChar(Uint16 ch)
{
	file.seekg(offsets[ch]);
	file.get((char&)chars[ch].xOff);
	file.get((char&)chars[ch].yOff);
	file.get((char&)chars[ch].width);
	file.get((char&)chars[ch].height);

	if (ch==' ')  chars[ch].width=8;

	chars[ch].bwidth=(chars[ch].width+7)>>3;
	chars[ch].data=new Uint8[chars[ch].bwidth*chars[ch].height];
	file.read((char *)chars[ch].data,chars[ch].bwidth*chars[ch].height);
}