#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);
}