Вроде все научились выводить, а вот шрифты еще пока нет. Давайте создадим новый класс для шрифтов. Или Вы их хотите сами рисовать попиксельно ?!
Думаю не надо объяснять, что существует два вида шрифтов: векторные и растровые. Векторные шрифты не плохи (даже круты :-), но на данном этапе лично мне сложно написать за час класс выводящий шрифты Windows TTF или хотя бы Borland CHR. Так что давайте не будем мучиться и разработаем класс для работы с растровыми шрифтами.
Формат наших шрифтов будет чуть похож на формат спрайтов, описанных ранее. Вообще-то видимо я не с этого начинаю :-) Давайте разберемся как мы вообще будем представлять шрифты в памяти.
Для начала надо выбрать размер шрифтов. Горизонтальный размер символа в этом конкретном случае не будет превышать 8 пикселов. По высоте он не ограничен. С чем это связано ? С тем, что мы будем хранить в памяти битовую маску символов. Т.е. если бит в байте равен единице, значит в соответствующем положении на экране будет выведен пиксел. Пример символа "A":
...oo... 0x18 ..oooo.. 0x3C .oo..oo. 0x66 oo....oo 0xC3 oooooooo 0xFF oo....oo 0xC3 oo....oo 0xC3В памяти этот символ будет представлен в виде массива байтов:
{0x18,0x3C,0x66,0xC3,0xFF,0xC3,0xC3}
Как видите при таком способе хранения максимальная ширина символа может быть 8 пикселов, а вертикальный размер не ограничен. В принципе никто не мешает нам расширить нашу битовую матрицу до 16 бит, но я думаю символы такой величины не понадобятся.
В памяти будем представлять шрифт таким способом:
1 байт - Ширина символа 2 байт - Высота символа 3 байт - Первая битовая маска первого символа .....Если коротко, то первые два байта это физические размеры символов шрифта, а далее битовые образы всех 256 символов. У меня на компьютере имеется несколько интересных шрифтов такого формата. Но для вас напишем утилитку, которая сможет генерить такие шрифты, хотя многие из Вас смогут написать и сами.
Теперь описание класса CGIFont:
class CGIFont{
char *Font;
public:
CGIFont(char *FileName);
~CGIFont();
void WriteChar(CGIScreen *scr,int x,int y, unsigned char color,
unsigned char color1,
int bol,unsigned char ch);
void WriteString(CGIScreen *scr,int x,int y, unsigned char color,
unsigned char color1,
int bol,unsigned char *S);
};
Конструктор будет сразу инициализировать шрифт и загружать его из файла с именем FileName:
CGIFont::CGIFont(char *FileName){
FILE *f;
unsigned char l,k;
long len;
Font=NULL;
if ((f = fopen(FileName, "rb")) == NULL) return;
fread(&k,1,1,f);
fread(&l,1,1,f);
rewind(f);
len=l*256+2;
if((Font=(char *)malloc(len))==NULL){
fclose(f);
return;
};
fread(Font,len,1,f);
fclose(f);
};
Деструктор, можно сказать, в старом стиле:
CGIFont::~CGIFont(){
if (Font!=NULL) free(Font);
};
Теперь осталась процедура вывода символа и строки.
void CGIFont::WriteChar(CGIScreen *scr,int x,int y, unsigned char color,
unsigned char color1,
int bol,unsigned char ch)
{
unsigned char i,j,Number,N;
if (Font==NULL) return;
char l=*Font;
char k=*(Font+1);
for (j=0;j<=k-1;j++)
{
Number=*(Font+2+ch*k+j);
for (i=0;i<=l-1;i++)
{
N = Number << i;
N >>= 7;
if (N==1) scr->PutPixel(x+i,y+j,color);
else if (bol==0) scr->PutPixel(x+i,y+j,color1);
}
}
};
Здесь scr - это тот виртуальный экран, на который нам надо вывести символ. Позиция для вывода символа задается координатами x,y. Цвет символов задается параметром color, а фон цветом color1. При этом, если признак bol равен 1, то фон не выводится. Этот эффект похож на прозрачность в спрайтах. Параметр ch задает тот символ, который надо вывести.
Теперь на базе этой процедуры строим процедуру вывода строки на экран:
void CGIFont::WriteString(CGIScreen *scr,int x,int y, unsigned char color,
unsigned char color1,
int bol,unsigned char *S)
{
unsigned char l;
if (Font==NULL) return;
l=*Font;
int i=0;
while (*S!='\0')
{
if (*S!='\n')
{
WriteChar(scr,x+(i*l),y,color,color1,bol,*S);
i++;
}
else {i=0;y+=*(Font+1);}
S++;
};
};
Все параметры аналогичны предыдущей процедуре. Строка задается указателем *S.
Теперь можно выводить символы на виртуальный экран. Графические возможности нашего CGI приложения постоянно растут :-)