Вроде все научились выводить, а вот шрифты еще пока нет. Давайте создадим новый класс для шрифтов. Или Вы их хотите сами рисовать попиксельно ?!
Думаю не надо объяснять, что существует два вида шрифтов: векторные и растровые. Векторные шрифты не плохи (даже круты :-), но на данном этапе лично мне сложно написать за час класс выводящий шрифты 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 приложения постоянно растут :-)