20.5. Крупные надписи на экране

В этом разделе будет рассмотрен специальный пример декоративного оформления экрана. Можно, не включая графического режима, выводить на экран символы алфавита размером 8 строк на 8 столбцов.

Различные видеоадаптеры содержат и поддерживают шрифты различного качества (разрешения). Самые простые состоят из матрицы 8x8 точек изображения, более качественные имеют большие матрицы — 14x8, 16x8 и др. Тем не менее практически во всех IBM-совместимых ПЭВМ присутствует шрифт 8x8.

Каждый символ шрифта 8x8 закодирован в виде восьми последовательных байтов. Первый байт соответствует двоичной кодировке

- 487 -

первой строки матрицы, восьмой — последней. Пример кодировки символа «+» приведен на рис. 20.10.

Рис. 20.10

Эту матрицу несложно воспроизвести на экране, если вместо нулей ставить пробелы, а вместо единиц — символы заполнения (решетки, звездочки и т.п.). Достаточно только знать, где лежат 8-байтовые матрицы шрифта. Ответ на этот вопрос прост лишь для той половины таблицы матриц символов, которая хранит символы от 0-го до 127-го. Для нее адрес матриц 8x8 всегда одинаков и равен $F000:$F0A6. Это число стабильно и реализуется аппаратно. Хуже дело со второй половиной таблицы — с матрицами символов от 128-го до 255-го. Именно там расположены знаки псевдографики и русский алфавит. На начало этой таблицы показывает системный вектор с номером $1F, и с помощью процедуры GetIntVec, рассмотренной в описании модуля DOS, можно получить адрес первого из 128 наборов по 8 байт второй части таблицы. Но этого мало. Надо убедиться, что таблица кодов со 128-го по 255-й загружена в память. Обычно их загрузку в память машины делает утилита MS-DOS GRAFTABL.COM, но она загружает «фабричные» символы. При программной русификации ПЭВМ такую таблицу должен загрузить драйвер русского алфавита. Но ему тоже надо указать, чтобы среди прочих грузился и шрифт 8x8. Например, адаптер EGA поддерживает два набора шрифтов (8x8 и 8x14), хотя в основном показывает на экране лишь второй! Если вторая половина шрифта не загружена, то вектор $1F будет указывать на адрес $F000:$0000. Если же она на месте, то вектор будет указывать на любой другой адрес, отличный от $F000:$0000.

- 488 -

Изображение увеличенных матриц символов на экране может быть получено множеством способов. Один из них предложен на рис. 20.11. Мы советуем внимательно изучить его, ибо ряд примененных приемов является достаточно универсальным. Так, массив можно наложить на область памяти через директиву absolute, причем использовать переменное значение адреса.

| PROGRAM Big_Chars; { ДЕМОНСТРАЦИЯ БОЛЬШИХ БУКВ }

| USES

| CRT, DOS; { подключены модули CRT и DOS }

{ Процедура рисует символ с кодом CharToPrint в квадрате размером 8x8 позиций. На экране этот квадрат имеет координаты нижнего левого угла, равные (Col, Row-1).

Символ заполняется образом CharToFill. Переменная AddrOfTable_2 должна иметь значение адреса второй половины таблицы символов (со 128-го по 255-й). }

| PROCEDURE WriteChar( Col, Row, CharToPrint : Byte;

| CharToFill : Char; VAR AddrOfTable_2 );

| TYPE

| CharDim = Array[1..8] of Byte; {структура символа }

| TableDim = Array[0..127] of CharDim; {половина таблицы }

| VAR

| X, Y :Byte;

| Table_1:TableDim absolute $F000:$FA6E; {1-я половина }

| Table_2:TableDim absolute AddrOfTable_2; {2-я половина }

| Pattern : CharDim; {один символ }

| BEGIN

| case CharToPrint of

| 000..127 : Pattern := Table 1[ CharToPrint ];

| 128..255 : Pattern := Table_2[ CharToPrint-128 ]

| end; {case}

| Inc(Col,7 ); { настройка положения }

| Dec( Row,8 );

| for X:=1 to 8 do

{ анализ матрицы символа }

| for Y:=7 downto 0 do begin { и его вывод на экран }

| GotoXY( Col-Y, Row+X );

| if (Odd(Pattern[X] SHR Y)) then

| Write( CharToFill )

| end { for.. for..}

| END;

Рис. 20.11

- 489 -

{ Процедура рисует большими буквами строку S (длиной не более 9 символов) с позиции ( X,Y ). Буквы закрашиваются символом C, а сдвинутая тень букв - символом Т.}

| PROCEDURE WriteLargeString(X,Y:Byte;C,T:Char;S:String);

| VAR

| i : Byte;

| Del: ShortInt;

| P : Pointer; { адрес второй половины таблицы символов }

| BEGIN

| Inc( Y ); { надо опустить Y из-за наличия тени }

| GetIntVec($1F, P ); { Р = адрес 2-й таблицы }

| if Y < 9 then

| Y := 9; { два ограничения no Y }

| if Y > Hi(WindMax) then

| Y:=Hi(WindMax)-H;

| i := Lo(WindMax)-Lo(WindMin)+1; { ширина текущего окна }

| repeat { Цикл отрывает сим- }

| Del := i-(8*length( S )+X-1); { волы с конца S, пока }

| if Del<0 { разность длин окна и }

| then Delete(S, Length(S), 1);

| { надписи Del не станет }

| until Del>=0; { неотрицательной. }

| for i:=1 to

| Length( S ) do { печать S no буквам }

| begin

| WriteChar(X+(i*8-7), Y, Ord(S[i]), T, P^); { тень }

| WriteChar(X+(i*8-8), Y-1, Ord(S[i]), C, P^) { буква }

| end

| END;

| BEGIN { -— ОСНОВНАЯ ЧАСТЬ -— }

| TextBackGround(Red); ClrScr; { очистка экрана }

| TextColor(Yellow); { выбор цветов для букв }

| TextBackGround(Blue);

| WriteLargeString(1,20,#176,' ','Turbo-Сила'); { вызов }

| Readln { пауза до нажатия ввода }

| END.

Рис. 20.11 (окончание)

Завершая этот раздел, заметим, что подобным способом можно выводить крупные символы и более детальных матриц. Но тут появляются две проблемы: одна — определение места шрифта в памяти ПЭВМ (в общем случае это не просто) и вторая — размещение столь крупных символов (размером 8 строк на 14 столбцов) на экране.