TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Гостевая книга

Рассылка

Благодарности

Об авторе

 

 

ПЗ. РЕДАКТОР ВЕКТОРНЫХ ШРИФТОВ

В этом приложении приводится орисание работы и текст программы, предназначенной для редактирования существующих или создания новых векторных BCI— шрифтов. Такие шрифты используются для вывода текстовых сообщений стандартными процедурами OutText и OutTextXY, а также процедурой OutString из модуля F_GrText в графическом режиме работы экрана. Описание формата BCI— шрифтов приведено в п. 1.2. Программа рассчитана на работу с мышью и экраном типа EGA/VGA.

П3.1. Интерфейс с пользователем

Для запус ка программы следует дать команду

fontedit [FName]

В квадратных скобках указан необязательный параметр, определяющий имя уже существующего CHR— файла.

В момент запуска программа проверяет параметры обращения и, если указано имя FName, настраивается на редактирование шрифта из этого файла. Например, обращение

fontedit trip

заставит программу загрузить BCI— шрифт из файла trip.chr с целью редактирования стандартного шрифта TriplexFont (добавления новых символов или изменения старых). Вы можете задать имя с предшествующим ему маршрутом поиска CHR — файла на диске (если файл имеет стандартное расширение CHR, это расширение можно не указывать — см. пример выше).

Если параметр обращения отсутствует, программа запрашивает имя файла. В этот момент Вы должны ввести имя, если хотите редактировать шрифт, или нажать Enter, если хотите создать новый.

После правильной загрузки данных из CHR—файла экран приобретет вид, показанный на рис.ШЛ.

Верхняя строка содержит опции меню, левую часть экрана занимает поле редактора, а правую часть — таблица всех символов из редактируемого BGI— шрифта.

Для создания нового или изменения существующего символа используется поле редактора. Это поле расчерчено точками, определяющими локальные координаты символа — любой векторный элемент представляет собой вектор, соединяющий две произвольные точки (два узла) поля редактора. Каждое изменение поля редактора автоматически отображается в уменьшенном виде (точнее, с масштабными коэффициентами 1,1) в небольшом окне повторения ниже поля редактора.

Таблица символов предназначена для выбора очередного символа перед его загрузкой в поле редактора, а также для указания того места в ASCII— таблице, куда будет помещен вновь созданный или отредактированный в этом поле символ. Ниже таблицы создается небольшое окно, в котором показывается ASCII—mop, выбираемого элемента. Так как стандартные векторные шрифты не содержат символов с ASCII— кодами от 0 до 31 и символа #255, соответствующие позиции в таблице заполняются матричными символами шрифта DefaultFont и изображаются пониженной яркостью. При желании Вы можете создать векторный символ для любого ASCII— кода, в том числе и для этих позиций таблицы.

h02921.jpg

Рис.Ш. 1. Вид экрана редактора шрифтов Опции меню имеют следующий смысл:

• «Из таблицы» — активизирует выбор из таблицы символа," который требуется загрузить в поле редактора; - '

• «В таблицу» — выбирает то место в таблице ASCII1- кодов, в которое будет ггомвщвй вновь созданный или отредактированный символ; \ "

• «Очистить» -• очищает поле редактора;

• «Образец» — активизирует выбор из таблицы символа, Который будет слухить образцом для вновь разрабатываемого; образец выводится в рабочем поле пониженной яркостью и никак не влияет на новый символ;

• «Сохранить» — сохраняет текущее состояние шрифта в файле;

• «Конец» — завершает работу программы и возвращает управление ДОС; если к этому

моменту в ASCII— таблице были сделаны несохраненные на диске изменения, шрифт

автоматически сохраняется в файле.

Работа программы управляется мышью, две кнопки которой отождествляются со следующими действиями:

• левая кнопка: выбирает продолжение из меню, начинает или заканчивает .формиро-" вание очередного векторного элемента в поле редактора, выбирает текущий элемент в таблице символов;

• правая кнопка: отменяет формирование нового векторного элемента, удаляет (стирает) векторный элемент, отменяет выбор из таблицы символов, перемещает в новое положение правую границу символа в поле редактора.

Для редактирования (изменения) существующего векторного символа выберите- в меню продолжение «Из таблицы», сместите мышью курсор таблицы {белый прямоугольник) к нужному символу и нажмите левую кнопку — поле редактора очистится и в него будет помещена совокупность векторов, определяющих начертание нужного символа. Замечу, что все последующие изменения символа в поле редактора никак не связываются с редактируемом символом до тех пор, пока вновь созданный символ не будет тгомещен на ?го место. Более того, из поля редактора можно переносить новый символ на любое место — таким способом, например, можно быстро заполнить ту часть русского алфавита, которая по наяертанию совпадает с латиницей.

Если Вы хотите создать новый символ, не имеющий сходства с ранее еозданнымйг очистите поле редактора с помощью продолжения «Очистить». Возможно, Ры захотите посмотреть на детали реализации того или иного ранее созданного символа, но не хотите, чтобы его векторы «мешали» вновь создаваемому — в этом случае используйте продолжение «Образец» (например, можно загрузить как образец латинскую букву Р при создании символа

Ф).

Для добавления нового вектора подведите указатель мыши к узлу, от которого он должен начинаться, и нажмите левую кнопку — указатель исчезнет, что сигнализирует о «захвате» узла. Указатель появится вновь только после отпускания кнопки, но будет уже представлять собой небольшой прямоугольник, показывающий границы чувствительности мыши. При перемещении такого указателя по рабочему полю за ним будет тянуться «резиновая нить». В этом состоянии подведите указатель ко второму узлу так, чтобы этот узел попал в прямоугольник указателя, и вновь нажмите левую кнопку — указатель приобретет нормальный вид, а в поле редактора добавится новый вектор. Если Вы передумаете и не захотите добавить вектор, нажмите правую кнопку — «резиновая нить» исчезнет без каких-либо последствий.

Для удаления какого-либо вектора подведите к нему указатель и нажмите правую кнопку. Если мышь спозиционирована достаточно точно, вектор ^удет стерт, а стандартная маска указателя заменится на небольшой прямоугольник. Если теперь, не отпуская кнопки, перемещать указатель в рабочем поле, будут стираться все векторы, на коюрые покажет этот указатель. После отпускания кнопки указатель восстановит стандартный вид и мышь перестанет стирать векторы.

После того, как Вы отредактируете символ нужным образом, выберите в меню продолжение «В таблицу» и поместите символ на нужное место.

На некотором расстоянии справа от символа в поле редактора формируется вертикальная линия, показывающая текущую ширину символа. Положение этой линии автоматически изменяется, если вновь созданный векторный элемент выходит за нее. Вы можете установить положение линии вручную, для этого подведите к ней указатель и нажмите правую кнопку — указатель изменит свой вид на небольшой прямоугольник. В таком состоянии перемещайте мышь, удерживая нажатой ее правую кнопку — линия будет отслеживать горизонтальное

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

П3.2. Описание программы

Работа программы проходит в три этапа и реализуется процедурами /nit. Run и Done. На этапе выполнения процедуры uii't осуществляются следующие действия:

• вводится имя редактируемого или вновь создаваемого CHR— файла, содержащего нужный векторный шрифт (процедура Namelnputf;

• если файл уже существует, программа проверяет его структуру и считывает данные (процедура ReadData), в противном случае — запрашивает параметры вновь создаваемого файла и готовит его описание (процедура NewFUef;

• переводит экран в графический режим, инициирует мышь и готовит для нее графические указатели, расчерчивает поле редактирования, выводит таблицу символов и готовит меню для работы с мышью (процедура BuildScreenf. Основная работа реализуется процедурой Run. тело которой состоит из бесконечного цикла While True do begin ... end. В ходе этого цикла непрерывно сканируется состояние мыши, и в зависимости от результатов сканирования выполняются следующие действия:

• если мышью выбран один из элементов меню (т.е. указатель подведен к соответствующей надписи и нажата левая кнопка мыши), вызывается одна из процедур GetChar, SetChar, ClearWE, Pattern, SaveFont или Exit в зависимости от сделанного выбора;

• если нажата левая кнопка мыши, а указатель при этом был в поле редактора, вызывается процедура MouseInNed, проверяющая выбор того или иного узла поля редактора; если узел выбран, он становится исходной точкой и от него вслед за указателем мыши будет тянуться «резиновая нить»; если «резиновая нить» уже была сформирована предыдущим обращением к MouseInNed, обращение к этой процедуре вызовет формирование нового векторного элемента редактируемого символа;

• если нажата правая кнопка и указатель располагался в поле редактора, вызывается процедура MouseInLine, проверяющая выбор того или иного вектора и осуществляющая его стирание, если вектор выбран;

• если не нажата ни одна кнопка, но мышь изменила свое положение, будет вызвана процедура MouseMove, реализующая «резиновую нить».

Завершающий этап работы программы реализуется процедурой Done. В ходе ее выполнения вызывается процедура SaveFont для сохранения в файле сделанных изменений, и восстанавливается текстовый режим работы экрана.

В программе используются процедуры и функции из модулей F_GrText (для формирования меню и вывода номера элемента ASCII— таблицы), F_Mouse (для обслуживания мыши и контроля выбора элемента меню) и F_Anti (для автоматической защиты программы от нападения вирусов).

1$Х+} ^——————————————————————————————+

¦ Редактор векторных шрифтов формата CHR ¦

+--------—----—--—-----------—----------——+

;

Uses CRT,Graph,F_GrText,F_Mouse,F Anti;

{

Глобальные определения

}

type

TChar4 = array [1..4] o? Char;

TFontHead = record {Структура заголовка шрифта}

case Byte of

0:(FontFileID: TChar4) ;

1:(B: array [1..128] of byte; ;

end;

TFontPara = record {Блок параметров шрифта}

case Byte of

ParPrefix : Char; {Символ "+"}

CharsCount: Word; {Количество символов а шрифте}

Reservl : Byte; (He используется)

firstChar : Byte; {Код первого символа}

DataOffset: Word; {Смещение до векторных команд первого -символа}

FillFlag : Byte; (Флаг заливки}

UpperMargin: Byte; {Высота, символов}

Reserv2 : Byte; {He используется}

LowerMargin: Shortint; {Нижняя кромка}

Reserv3 : array [1..5] of Byte?);

1:(H2: array [1..16] of Byte) end;

TOffst = array [0..255] of Word; {Смещения} TWidth = array [0..255] of Byte; {Ширины} TChars = array [0..255] of Pointer; (Данные} TLengD = array [0..255] of Word; {Длина} AW = array [1..255] of Word;

TCooE " record (Векторы рабочего поля}

X1,Y1,X2,X2: Integer;

end;

TMouseMask = array [0..1,0..151 of Word;

var

FontHead TFontHead; {Заголовок файла} HeaderSize: Word; (Смещение блока параметров} FontPara TFontPara; {Параметры шрифта} FileSize Word; {Длина загружаемой части файла} AFileSize: Byte; {Положение FileSize} Offsets TOffst; {Таблица смещений} Widths TWidth; (Таблица ширин} Chars TChars; (Указатели на данные} LengD TLengD; (Длина данных в байтах} F File; {CHR-файл} FName String; {Имя файла} MaxW Byte; {Максимальная ширина символа} MaxH Byte; (Полная высота символа} {——————— рабочее поле ———————}

ХЕ Integer; {Левый верхний угол f/S.} IS Integer;

ХЕ2 Integer; (Правый нижний угод WE) YE2 Integer;

YB Integer; {Ордината базовой линии} WidthX Integer; (Правая граница символа} DXE Integer; {Ширина клетки WE} DYE Integer; {Высота, клетки WE} NVecE Word; {Количество векторов в ИЕ} VecE: array [1..250] of TCooE; {Векторы в ИЕ} (———————— Окно повтора ————————}

XR,YR: Integer; {Координаты окна повтора} HR: Pointer; {Образ пустого окна повтора} {---------- Таблица символов ------------}

XT : Integer; {Левый верхний угол таблица символов} YT : Integer;

DXT : Integer; {Ширина клетки таблицы символов} DYT : Integer; {Высота клетки} {—————————— Мышь -——————————}

dXm,dYm : Integer; {Границы мыши в рабочем поле} CurM: TMouseMask; (Стандартная маска указателя} CurE: TMouseMask; (Маска в рабочем поле} HouseF : Boolean; {Флаг формы указателя мыши}

const

ChangeF: Boolean '» False; {Флаг изменения шрифта} Head: TChar4 - ('P','К',#8,#8) ;

procedure OutChar(XO,YO: Integer; C: Byte; DX,DY: Real);

(Выводит символ С в позицию X,Y с масштабом DX,DY} var

PW:'-AW;

k: Integer;

x,y: Integer;

Procedure Vector(W: Word);

{Рисует очередной вектор символа} vax

хх,уу: Integer;

ор: Word;

begin

{Выделяем Код операции}

ор := W and $8080;

if op=0 then Exit;

W := H acor ор;

(Выделяем координаты}

уу := W shr 8;

хх := W and $FF;

if xx>63 then xx :•= xx-128;

if yy>63 then yy :•= yy-128;

{Поучаеы координаты второй точки}

хх :=• XO+Round(xx*DX) ;

уу YO-Round(yy*DY) ;

{Выполняем операцию}

if op-$8080 then Line(X,Y,XX,YY);

X := XX;

У :« YY end; {Vector} {——————}

begin {OutChar}

if LengD[C]"0 then

Exit; {Блокируем вывод не определенных символов}

YO :" YO-DXT div 4;

X :" ХО; {Точка отсчета координат}

У :° YO;

PW :•=• Chars [С]; (Описатель символа}

{Вычерчиваем символ}

for k :» 1 to LengD[C] div 2 do

Vector (PWik]) end; {OutCharXY} _•————————————;

Procedure ClearWinEd;

{Очищает рабочее поле} var

X,Y: Integer;

begin SetViewPort(XE-dXm,YE-dYm,XE2+dXm,YE2+dYm.True) ;

ClearViewPort;

SetViewPort(0,0,GetMaxX,GetMaxY,True;;

/Выводим вертикали/

for X := 0 to MaxW do for Y :» 0 to MaxH do

PutPixel(XE+X*DXE,YE+Y*DYE,White);

{Выводим базовую линию}

SetColor(Cyan);

YB := YE+succ(FontPara.UpperMargin)*DYE;

Line(XE,YB,XE2,YB) ;

{Выводим указатель границы символа}

WidthX := ХЕ;

Line(XE,YE,XE,YE2) ;

{Обводим рамкой}

?etColor(White) ;

Rectangle(ХЕ-dXm,YE-dYm,XE2+dXm,YE2+dYm) end; (ClearffE} _•————————————;

Procedure I nit;

{Запрашивает и вводит имя CHR-файла, вводит данные из файла, инициирует--гря~ фику и создает экран}

Procedure FontRsad. (var Dest; Size: Word);

(Читает из файла F в переменную Dest Size байР я контролирует результат. При ошибке аварийно завершает программу} var

k: Word;

begin

BlockRead(F,Dest,Size,k) ;

if k=Size then Exit;

WriteLnCОшибка при чтении данных из файла!');

Halt end; (FontRead) {—————} Procedure NameInput(var FName: String);

(Вводит и проверяет имя CHR-файла} label

Loop,HeadErr;

var

k: Byte;

begin

Write('Программа редактирования векторных BQI-шрифтов формата CHR. ') ;, WriteLn('<C) 1993 В.В.Фаронов') ;

{Проверяем параметры обращения} if ParamCountoO then

FName := ParamStr(l) else

FName := '';

if FName='' then

begin Loop: (Сюда возврат при ошибке в имени}

Write('Введите имя CHR-файла (*.CHR): ');

ReadLntFName) ;

it FName = ' ' then

begin {Пустой ввод} Write('Создать новый шрифт (Y/N)? ');

ReadLntFMame);

if (FName=") or

(UpCase(FName[1])<>'Y') then Halt;

FName :° '';

Exit

end end;

{Проверяем существование файла) if Pos('.',FName)=0 then FMame := FName+'.CHR' ;

{$!-} {Отключаем контроль lOEtrorf Assign(F,FName);

Reset(F,1); {Пытаемся открыть файл} {$!+} {Восстанавливаем контроль ЮЕггог} if IQResultoO then begin

WriteLn('Файл '+FName+' не найден');

Goto Loop end;

{Читаем заголовок файла} FontRead(FontHead,SizeOf(FontHead)) ;

if FontHead. FontFileIDoHead then begin

WriteLn('Ошибка в заголовке файла!');

Goto Loop end;

{Ищем смещение блока параметров и длину файла'} with FontHead do begin

k := 5; {Начинаем с пятого байта} while (kOizedf (FontHead)) and (B[k]o$lA) do inc(k);

if B[k]=$lA then begin

HeaaerSize := B[k+l]+B[k+2] ehl 8;

FileSize := B[k+7]+B[k+8] ahl 8;

AFileSize := k+7;

{Читаем блок параметров} Seek(F,HeaderSize) ;

FontRead(FontPara,SizeOf(FontPara)) ;

if FontPara.ParPrefix='+' then

Exit {Нормальный выход) else /Her префикса параметров}

Goto HeadErr end end;

{Не найден терминатор CopycightEnd) HeadErr:

Close(F) ;

WriteLn('Ошибка в заголовке файла!');

Goto Loop end; {Каше Input} {—————} Procedure ReadData;

{Читает данные из файла} var

k: Integer;

LastChar: Byte;

begin

with FontPara do begin

LastChar := FirstChar+CharsCount-1;

{Заполняем таблицу смещений} for k := 0 to 255 do

if k in [FirstChar..LastChar] than

FontRead(Off sets[k],2) else

Offsets[k] := 0;

{Заполняем таблицу ширин) MaxW := 0;

for k := 0 to 255 do

if k in [FirstChar..LastChar] then begin

FontRead(Widths[k],1) ;

if Widths[k]>MaxW then

MaxW := Widths(k] end else

Widths[k] :" 0;

if MaxW<20 then MaxW := 20;

{Готовим память и считываем данные) for k := 0 to 255 do

LengD[k] := 0; (Обнуляем таблицу длин} for k := FirstChar to LastChar do begin

if k=LastChar then

LengD[k] := FileSize-Offsets[k]-FontPara.DataOffset

else

LengD(k] := Offsets[k+1]-Off sets[k];

if LengD[k]<>0 then begin

GetMem(Chars[k],LengD[k]) ;

FontRead(Chars[k]",LengD[k]) end end;

Close(F) ;

end; {with FontData) end; {ReadData} f—————} Procedure BuildScreen;

{Переводит дисплей а графический реяшм, вычисляет константы и создает экран)

procedure PutCur(var Cur: TMouseMask) ;

{Сканирует изображение в левом верхнем углу экрана и формирует маску указателя мыши} var

х,у: Byte;

b: Word;

begin

for у := 0 to 15 do begin b :° 0;

for x := 0 to 15 do

if GetPixel (x, y) OGetBkColor then b := b or ($8000 shr x) ;

Cur[l,y] := b;

Cur[0,y] := not b end end; {PutCLir} {—————} var

D,R,E,k,n,X,Y: Integer;

с: Byte;

S: String;

Sz: Word;

FF: File;

Font: Pointer;

const

Txt: array [1..6] of String [10]=(

•Из таблицы', 'В таблицу', 'Очистить', 'Образец', 'Сохранить', 'Конец');

Items: array [1..6] of MouseItemType=(

(X1:1 ; Y1:1; X2:13; 12:2; Butt: LeftButton; Key 1 ehl 8), (X1:14; Y1:1; X2:25; Y2:2; Butt: LeftButton; Key 2 shi 8), (XI:26; Y1:1; X2:37; Y2:2; Butt: LeEtButton; Key 3 shi 8), (X1:38; Y1:1; X2:49; Y2:2; Butt: LeftButton; Key 4 shi 8), (X1:50; Y1:1; X2:61; Y2:2; Butt: •LeftButton; Key 5 shi 8), (X1:61; Y1:1; X2:80; Y2:2; „Butt: beftButton; Key 6 shi 8));

begin {BuildScreen)

{Переходим в графику}

D := Detect; {Автоопределение драйвера I

InitGraph(D,R,''); (Инициируем графику}

Е :=• GraphResult; {Проверяем результат}

if EoO then

begin {Есть ошибка} WriteLn(GraphErrorMsg(Б));

Halt end;

{Выбираем шрифт а зависимости от разрешения экрана}

case GetMaxY of

199: с := S; {CGA 8х8} 349: с := 14; {EGA 8х14} 479..1024: с := 19; {VGA,SVGA 8х19}

else

с := 8 {Прочие 8х8}

end;

with FontPara do

MaxH := UpperMargin-LowerMargin+1;

{Определяем границы рабочего поля}

DYE = succ(GetMaxY) div (5*MaxH div 4); (Высота клетки}

DXE = succ(GetMaxX) div (2*MaxW); {Ширина клетки}

XE = DXE div 3; (Смещение слева}

YE = 2*с; (Смещение сверху}

ХЕ2 = XE+MaxW*DXE; (Правый нижний угол}

YE2 = YE+MaxH*DYE;

(Определяем размеры указателя мыши в рабочем поле и формируем его маски}

dXm = XE;

dYm = DYE div 3;

(Проверяем наличие мыши}

if not InitMouse then

begin (Нет мыши - завершаем работу} CloseGraph;

WriteLn('Нет мыши - программа не может работать');

Halt end;

(Готовим стандартный указатель}

ShowMouse;

MouseGotoXY(0,0); (В левый верхний угол}

PutCur(CurM); (Получить образ}

HideMouse;

(Указатель-квадратик для рабочего поля}

Rectangle(0,0,2*dXm,2*dXm);

PutCur(CurE); {Подучить образ}

{Расчерчиваем рабочее поле}

ClearWinEd;

fГотовим координаты окна повторения символа} XR :=(XE2-XE) div 2;

YR := GetMaxY-MaxH;

sz := ImageSize(XR,YR,XR+MaxW,YR+MaxH);

GetMem(WR,sz) ;

Getlmage (XR^R^R+MaxW^R+MaxH.WR*);

{Создаем таблицу символов)

XT :- XE+(MaxW+l)*DXE; {Левый верхний} YT :== YE; {угол таблицы символов} DXT := GetMaxX div 32; {Шаг по горизонту} DYT := GetMaxY div 20; {Шаг по вертикали} SetColor(White); /Белый цвет;

for n := 0 to 255 do /'Выводим символы} with FontPara do begin

X :» XT+(n mod 16)*DXT;

Y :" YT+(n div 16)*DYT;

if LengD[n]<>0 then begin

SetColor(White) ;

OutChar(X,Y+DYT,n,DXT/MaxW,DYT/(MaxH+5)) end •Xse

begin [Выводим недостающие символы} SetColor(DarkGray);

OutTextXY(X,Y+DYT-8,Chr(n)) end end;

{Загружаем шрифт из файла SxH.fntf Str(c,S);

S := '8x'+S+'.fnt';

Assign(FF,S) ;

{$!-} Reset (FF,1);

{$!+} if lOResultoO then begin

CloseGraph;

WriteLnCHer шрифтового файла '+S);

Halt end;

Sz := System.FileSize(FF);

GetMem(Font,Sz);

BlockRead(FF,Font",Sz,r) ;

Close(FF) ;

if rOSz then begin

CloseGraph;

WriteLn('Ошибка чтения файла '+S);

Halt end;

{Регистрируем шрифт и переназначаем ввод/вывод} SetFont(Font,8,с) ;

GraphWriteOn;

(Выводим строку меню} ' Colors(Black,LightGray) ;

for k := 1 to 6 do with Items[k] do

SetWindow(XI,Y1,X2,Y2-1,EmptyBorder,Txt[k],False,False,False);

{Инициируем мышь} SetMouseItem(6,Items);

ShowMouse; {Показывав» указатель тшши} TextRatioY := с;

end; (BulldScreen} {—————} Procedure NewFile(var FName: String);

{Создает новый CHR-файл} var

Name: String;

HH: ShortInt;

H,k: Byte;

Y: String [1] ;

const

tl='Максимальная высота символов от базовой линии: ';

t2='Расстояние до нижней кромки символа: ';

13"'Максимальная ширина: ';

t4=" font VI.1 Jan 12, 1989';

t5=#13#10;

t6='Copyright (c) 1987,1988 Borland International';

begin

(Вводим в диалоге параметры шрифта} repeat

Write('Введите 4-буквенное имя шрифта: ':55);

ReadLn(Name);

while Length(Name)<4 do Name := Name+'0';

Name[0] := chr(4) ;

for k := 1 to 4 do

Name[k] := UpCase(Name[k]);

Write(tl:55) ;

ReadLn(H) ;

H :° H and 63;

Write (t2:55) ;

ReadLn(HH) ;

if HH>0 then HH :- -HH;

Write(t3:55) ;

ReadLn(MaxW) ;

MaxW := MaxW and 63;

MaxH := H-HH;

WriteLn;

WriteLn('Будет создан шрифт с именем '+

Name+' со следующими параметрами:');

WriteLn(tl:55,H);

WriteLn(t2:55,HH) ;

WriteLn(t3:55,MaxW) ;

Write('Согласны (Y/N, умлч.У)? ');

ReadLn(У) ;

until (Y<>") or (UpCase(Y[l])<>'N') ;

{Готовим заголовок} for k := 1 to 128 do

FontHead.B[k] := 0;

for k := 1 to 16 do

FontPara.H2[k] := 0;

FName :» Name+'.CHR';

with FontHead do

begin

FontFileID := Head;

Name := 'BGI 4-Name+t4+t5+t6+t5+#0;

for k := 1 to Length(Name) do B[k+4] := ord(Name[k]);

AFileSize :" k+12;

Name := #$80#0+FName;

Name[0] := #$1A; {CopyrightEndl Name[7] := #0; {LolfileSise]} Name[8] := #0; {Hl[FileSizeJ} Name[9] :- *1; {VI.) Name[10] :- #0;

Name[11] := #1; (V.I} for k := 0 to 11 do

B[AFileSi2e-7+k] :- ord(Name[k]) ;

end;

{Готовим Блок параметров} with FontPara do begin

ParPrefix :" '+';

CharsCount :=° 0;

FirstChar :» 0;

DataOffset := 16;

FillFlag := 0;

UpperMargin := H;

LowerMargin := HH end;

{Готовим таблицу длин} for k :- 0 to 255 do LengD[k] := 0;

Assign(F,FName) end;

(—————} begin {Init} repeat

Namelnput(FName); {Вводим и контролируем имя файла} it FNameoI' then

ReadData {Читаеи данные из файла/ else

NewFile(FName) {Создаем новый файл} until FNameo'';

BuildScreen {Создаем экран} end; {Init} /————————————^

Procedure SaveFont;

{Сохраняет шрифт в файле} Procedure Alarm;

{Сообщает об ошибке записи} •чах

X2,Y2,X1,Y1: Integer;

Sz: Word;

P: Pointer;

С: Char;

begin

HideMouse;

Colors(White,Red) ;

Window(15,12,65,14) ;

GetWindGraphCoo(Xl,Yl,X2,Y2) ;

Sz := ImageSize(Xl,Yl,X2,Y2) ;

GetImage(Xl,Yl,X2,Y2,PЛ);

SetWindow(15,12,65,14,2,' Нажмите любую клавишу ',True,True,True);

Write('Ошибка доступа к файлу!':37);

ShowMouse;

while not KeyPressed or not MousePressed do;

while KeyPressed do С := ReadKey;

While MousePressed do;

HideMouse;

PutImagetX^Y^P^NormalPut) ;

ShowMouse;

FreeMem(P,Sz) end; {Alarm} {——————}

Function WriteFile(var Source; S: Word): Boolean;

{Записывает в файл S байт из переменной Source и контролирует результат} var

k: Word;

begin

BlockWrite(F,Source,S,k) ;

WriteFile := S»k;

if Sok then

Alarm end;

/——————;

var

k: Integer;

MinChr,MaxChr: Byte;

W,Offs,PredO: Word;

begin

if not ChangeF then Exit;

{Определяем начальный символ} MinChr := 0;

while (MinChr<255) and (LengD[MinChr]=0) do inc(MinChr) ;

if MinChr=255 then Exit;

(Определяем последний символом} MaxChr := MinChr;

k := MaxChr;

while k<-255 do begin

if LengD[k]<>0 then MaxChr := k;

inc(k) end;

{Корректируем пустые символы к подсчитываем длину загружаемой части} FileSize := 0;

for k := MinChr to MaxChr do if LengD[k]-0 then

begin {Пустой символ) Widths[k] := Widths[MinChr] ;

inc(FileSize,LengD[MinChr]) end else

inc(FileSize,LengD[k]) ;

{Определяем смещение в файле) Offs := 3*(MaxChr-MinChr+l)+16;

(Корректируем описатель шрифта) with FontPara do begin

FirstChar :- MinChr;

CharsCount:» MaxChr-MinChr+1;

Data0ffset:= Offs;

FileSize :» FileSize+16+3*CharsCount end;

{Записываем заголовок} With FontHead do begin

B[AFileSize] :° Lo(FileSize) ;

B[AFileSize+l] :-Hi(FileSize) end;

{Готовим файл} {SI-} Rewrite(F,1) ;

($!+} if IQResultoO then begin Alarm;

Exit end;

if not WriteFile(FontHead,SizeOf(FontHead)) then Exit;

{Записываем описатель)

if not WriteFile(FontPara,SizeOf(FontPara)) then Exit;

{Записываем таблицу смещений) PredO := Offs;

for k :» MinChr to MaxChr do begin

W := Offs-PredO;

if LengD(k]<>0 then

inc(0?fs,LengD[k]) else

inc(Offs,LengD[MinChr]) ;

if not WriteFile(W,2) theo

Exit end;

{Записываем таблицу ширин) for k := MinChr to MaxChr do

if not WriteFile(Widths[k],l) then Exit;

{Записываем данные) for k := MinChr •to MaxChr do if LengD[k]<>0 then

if not WriteFile (Chars [It]*, LengD[k]) then

Exit else else

if not WriteFile(Charstk]",LengD[MinChr]) then Exit;

Close(F); (Все в порядке) ChangeF := False Mid; {SaveFont} ^——————.—————;

Procedure Run;

{Основная работа: чтение мыши или клавиатуры и вызов нужных процедур}

•VAX

BM,XM,YM,B,X,Y: Integer;

x0g,y0g,xlg,ylg: Integer; {Координаты резиновой нити} MPF: Boolean; (Флаг резиновой нити}

PW^AW;

W,op: Word;

Procedure RepChar;

{Повторяет символ в окне повтора} var

k: Word;

begin

{Стираем старое изображение}

PutIniagetXI^YR.WR-^NormalPut) ;

{Формируем новое}

SetWriteMode(NormalPut) ;

SetColor(White) ;

for k := 1 to NVecE do with VecE[k],FontPara do

Line(XR+Xl div DXE,YR+MaxH+LowerMargin-(YB-Y1) div DYE,XR+X2 div DXE, YR+MaxH+LowerMargin-(YB-Y2) div DYE);

end;

{——————}

Function Tabi(var N: Byte): Boolean;

{Выбирает символ из таблицы. Возвращает номер символа или False для правой кнопки} var

X,Y, k,xx,yy,ddx,ddy: Integer;

NX,NY,NXX,NYY: Byte;

Sz: Word;

P: Pointer;

begin

HideMouse;

ddx :" DXT div 2; {Половина ширины}

day :" DYT div 2; {Половина высоты)

X :« XT+ddx; /'Начальный символ)

У :- YT+ddy;

NX :- 0; {Номер столбца)

NY :« 0; {Номер строки)

MouseGotoXy(X,Y) ;

MouseWindow(X,y,X+16*DXT,Y+16*DyT);

{Выделяем символ)

Sz :- ImageSize(X-ddx,Y-ddx,X+ddx,Y+ddx) ;

GetMem(P,sz);

Getlmage(X-ddx,Y-ddy,X+ddx,X+ddy,P*) ;

PutImage(X-ddx,Y-ddy,PA,NotPut) ;

while MousePressed do; ^Сбрасываем кнопку)

{Перемещаемся по таблице до нажатия на кнопку мыши}

while not MousePressed do begin

GetMouseState(k,xx,yy); {Текущее положение} NXX := (xx-XT) div DXT,-NYY := (yy-YI) div DYT;

if (NXONXX) or (NYONYY) then

begin {Перешли в новую клетку} Putlmage(X-ddx,Y-ddy,P",NormalPut) ;

Window(l,l,80,25);

GotoXY(60,25) ;

TextColor(White) ;

TextBackGround(LightRed);

Write(NYY*16+NXX:4,' ');

NX :== NXX;

NY := NYY;

X :» XT+NX*DXT+ddx;

У :« YT+NY*DYT+ddy;

Getlmage(X-ddx,Y-ddy,X+ddx,Y+ddy,P^ ;

Putlmage(X-ddx,Y-ddy,P^,NotPut) ;

end end;

(Нажата кнопка: восстанавливаем экран} Putlmage (X-ddx,Y-ddy,P'',MormalPut);

FreeMem(P,sz);

GotoXY(60,25) ;

Write (' ') ;

GetMouseState(k,xx,yy); {k - нажатая кнопка) while MousePressed do; {Ждем отпускания} N := NY*16+NX;

Tab! := k=LeftButton;

ShowMouse;

MouseScreen (Освобождаем мышь} end; {Tab!} {——————}

Procedure ClearWE;

{Очищает рабочее поле} begin

ClearWinEd;

Putlmage (XR.YI^WR^NormalPut:) ;

NVecE := 0;

WidthX := 0 end;

{——————}

Procedure GetChar;

(Берет символ из таблицы} var

k: Integer;

N: Byte;

W,op: Word;

xx,yy: Shortint;

begin

if not Tab!(N) then

Exit; {Выход по правой кнопке} ClearWE; (Очищаем рабочее поле} PW := Chars[N]; (Адрес описателей} X := 0; (Начальные координаты пера} У := 0;

SetColor(Yellow) ;

SetWriteMode(XORPut) ;

(Цикл по командам} for k := 1 to LengD[N] div 2 do begin

H := PW[k]; (Очередное слово} op := W and $8080; {Код операции} W := W xor op;

xx := W and 127; (Координата Х} yy :=• W shr 8; {Координата Y} if yy>63 then yy := yy-128;

if op=$8080 then

begin (Команда чертить} inc(NVecE); (Колич.векторов} with VecE[NVecE] do

begin (Формируем новый вектор} XI := XE+X*DXE;

Yl :- YB-Y*DYE;

X2 := XE+xx*DXE;

Y2 := YB-yy*DYE;

{Чертим линию в рабочей поле) Line(Xl,Yl,X2,Y2) end;

end;

X := хх; {Новое положение пера) Y :- уу end;

(Чертим правую границу символа} WidthX := XE+Widths[N]*DXE;

SetColor(Cyan) ;

Line(WidthX,YE,WidthX,YE2) ;

{Повторяем символ в окне повтора} RepChar end; {GetChar} {——————}

Procedure SetChar;

{Помещает символ в таблицу} var

k: Integer;

N: Byte;

W,op: Word;

Data: AW;

X,Y,XX1,YY1,XX2,YY2: Shortint;

Xc,Yc: Integers-begin

if not Tabl(N) then Exit;

{Удаляем старый описатель} if LengD[N]<>0 then

FreeMem(Chars[N],LengD[N]);

Widths[N] :«= (WidthX-XE) div DXE;

LengD[N] :" 0;

{Цикл по векторам} X :° 0;

Y :- 0;

for k :- 1 to NVecE do with VecE[k] do begin

XXI := (Xl-XE) div DXE;

XX2 := (X2-XE) div DXE;

YY1 := (YB-Y1) div DYE;

YY2 := (YB-Y2) div DYE;

if (xoxxi) or (YOYYI) then begin {команда перехода} if YYKO then inc(YYl,128) ;

inc(LengD[N]) ;

Data[LengD[N]] :« YYl «Ы 8+ХХ1 or $80 end;

X := XX2;

Y :•= YY2;

if YY2<0 then inc(YY2,128);

inc(LengD[N]) ;

Data[LengD[N]] :- YY2 ahl 8+XX2 or $8080;

end;

{Формируем переход в конец символа} inc (LengD [N]) ;

Data[LengD[N]] :- Widths[N] or $80;

inc(LengD[N]) ;

Data[LengD[N]] :» 0; {Конец команд) {Записываем в память} LengD[N] :-2*LengD[N];

GetMem(Chars[N],LengD[N] ) ;

Move(Data,CharstN]",LengC[N]) ;

{Чертим символ в таблице} HideMouse;

Хс := XT+(N mod 16)*DXT;

Yc := YT+(N div 16)*DYT;

SetFillStyle(SolidFill,Black) ;

Bar(Xc,Yc,Xc+DXT-l,Yc+DYT-l);

SetColor(White) ;

SetWriteMode(NormalPut) ;

OutChar(Xc,Yc+DYT,N,DXT/MaxW,DXT/(MaxH+5)) ;

SetColor(Yellow) ;

SetWriteMode(XORPut) ;

ShowMouse;

ChangeF := True end; {SetChar} {——————}

function Nedfvar x,y: Integer): Boolean;

(Возвращает TRUE и координаты узла, если мышь попала в его окрестности} var

Is: Boolean;

begin

Is := False;

у := YE;

repeat

X := XE;

repeat

Is := MouseIn(x-dXm,y-dYm,x+dXin,y+dYm);

if not Is then

inc(x,DXE) until Is or (x>XE2);

if not Is then

inc(y,DYE) until Is or (y>YE2) ;

Ned := Is end; {Ned} {——————}

Procedure MouseInNed;

{Проверяет отметку мышью узла сетки} var

XM,YN: Integer;

begin

if not Ned(XN,YN) then

Exit; /Яе попали в узел} HideMouse;

while MousePressed do;

MouseGotoXY(XN,YN) ;

if not MPF then

begin /Запоминаем узел} MPF := True;

XOg := XN;

YOg := YN;

Xlg := XOg Ylg :- YOg;

SetColor(Yellow) ;

SetWriteMode(XORPut);

MouseWindow(XE,YE,XE2,YE2) ;

MouseGraphCursor(CurE» dXm,dYm);

ShowMouse and else

begin (Формируем новый вектор! MPF := False;

if (xOgOxlg) or (yOgOylg) then Line(xOg,yOg,xlg,ylg) ;

MouseScreen;

it (XOgoXN) or (YOgoYN) then

begin (Поиещаем очередной вектор} inc(NVecE) ;

with VecE[NVecE] do begin

XI XOg;

Yl := YOg;

X2 := XN;

Y2 :- YN;

Lir)e(xl,yl,x2,y2);

RepChar end;

{Проверяем ширину символа^ if XOg>XN then XN := XOg;

if XN>WidthX then

begin {Смещаем правую границу} SetColor(Cyan) ;

SetWriteMode(XORPut) ;

Line(WidthX,YE,WidthX,YE2) ;

WidthX := XN+4*DXE;

if WidthX>XE2 then WidthX := XE2;

Line(WidthX,YE,WidthX,YE2) ;

SetColor(Yellow) ;

end;

MouseGraphCursor(CurM,0,0);

ShowMouse end end

end; {MouseInNed} {——————}

Procedure MouseInLine;

(Проверяет отметку вектора} var

х1т,у1я,х2т,у2т,dx,dy,x,y,n: Integer;

Is,Sign: Boolean;

k: Word;

k0,y0: Real;

label Loop;

begin

if MPF then

begin {Уничтожаем резиновую нить} HideMouse;

MPF := False;

if (XOgoXlg) or (YOgoYlg) then Line(XOg,YOg,Xlg,Ylg) ;

MouseGraphCursor(CurM,0,0);

ShowMouse;

MouseScreen;

Exit end;

if NVecE-0 then

Exit; {Пустое рабочее поле} Loop:

GetMouseState(x,xlm,ylm) ;

if (not MousePressed) and MouseF then begin

HideMouse;

MouseGraphCursor(CurM,0,0);

ShowMouse;

MouseScreen;

MouseF :" False;

Exit end;

x2m := xlm+dXm;

y2m := ylm+dYm;

xlm := xlm-dXm;

ylm := ylm-dYm;

{Проверяем все векторы} n := 1;

Is :a= False;

repeat

with VecE[n] do if (xl=x2) and (xl>=xlm) and (xl<=x2m) then {Вертикальный вектор}

Is := ((yl>=y2m) and (y2<=ylm)) or ((yl<=ylm) and (y2>=y2m)) else if (yl=y2) and (yl>=ylm) and (yl<=y2m) -then (Горизонтальный вектор}

Is := ((xl>=xlm) and (x2<=x2m)) or ( (xl<=x2m) and (x2>»-xlm)) else {Наклонный вектор} if (((yl>=y2m) and (y2<=ylm)) or ((yl<=ylm) and (y2>=y2m))) and (((xl>=xlm) and (x2<»St2m)) or ((xl<=x2m) and (x2>=xlm))) then begin

kO := (y2-yl)/(x2-xl);

yO := yl-k0*xl;

for x := xlm to x2m do if not Is then begin

у := Round(k0*x+y0) ;

Is := (y>=ylm) and (y<»y2m) ;

if not Is then if x=xlm then

Sign := y<ylm else

Is:= (Sign and (y>ylm)) or (not Sign and (y<ylm)) end end;

if not Is then

inc(n) until Is or (n>NVecE) ;

if Is then

begin {Удаляем вектор! HideMouse;

SetColor(Yellow) ;

SetHriteMode(XORPut) ;

with VecE[N) do

Line(xl,yl,x2,y2); /Стираем линию}

if NVecE>l then {Перемещаем векторы} for N :- N to NVecE-1 do VecE[N] := VecEtN+1];

dec(NVecE) ;

RepChar;

it NVecE>l then begin

MouseGraphCursor(CurE,dXm,dYm);

MouseWindow(XE-dXm,YE-dYm,XE2+dXm,YE2+dYm) ;

MouseF True end else begin

MouseGraphCursor(CurM,0,0);

MouseScreen;

MouseF := False end;

ShowMouse;

it MouseF then

Goto Loop end else if MouseF then

Goto Loop els» if (WidthX>-xlm) and (WidthX<"x2m) then

begin {Перемещаем правую границу} SetColor(Cyan) ;

SetWriteMode(XORPut);

HideMouse;

MouseGraphCursor(CurE,dXm,dYm);

ShowMouse;

MouseWindow(XE,YE,XE2,YE2) ;

while MousePressed do begin

GetMouseStste(n,xlm,ylm);

if XE+DXE*Round((xlm-XE)/DXE)<>WidtbX then begin

HideMouse;

Line(WidthX,YE,WidthX,YE2) ;

WidthX := XE+DXE*Round((xlm-XE)/DXE) ;

Line(WidthX,YE,WidthX,YE2) ;

ShowMouse end end;

MouseScreen;

HideMouse;

MouseGraphCursor(CurM,Q, 0) ;

ShowMouse and end;

{——————}

Procedure MouseMove;

{Контролирует перемещение мыши} begin

if MPF and ( (XMoXlg) or (YMOYlg)) then

begin {Формируем резиновую нить) HideMouse;

if (XOgOXlg) or (YOgOYlg) then

Line(XOg,YOg,Xlg,Ylg); {Стираем старую}

Xlg := XM; (Новые координаты конца}

Ylg := YM;

if (XOgoXlg) or (YOgOYlg) then Line (XOg,YOg,Xlg, Ylg) ;

ShowMouse end;

end; {MouseMove} {——————}

Procedure Pattern;

{Выбирает и помещает в рабочее поле образец} var X,Y,xx,yy: Integer;

k,op,W: Word;

PW^AW;

N: Byte;

begin

if not Tabi(N) than

Exit; (Выход по правой кнопке} SetColor(LightGray) ;

PW := Chars[N]; {Адрес описателей} X := XE; (Начальные координаты пера} У := YB;

{Цикл по командам} for k := 1 to LengD[N] div 2 do begin

H := PW^I-k]; (Очередное слово} ор := H and $8080; (Код операции) W := W acor op;

xx := W and 127; {Координата Х} yy := W shr 8y {Координата Y) if yy>63 then УУ ••= УУ-128;

xx :- XE+xx*DXE;

yy := YB-yy*DYE;

if op-$8080 then Line (X, У, xoc, yy) ;

X := xx; {Новое положение пера} Y := yy end;

SetColor(Yellow) end;

/—————;

begin {Run}

SetWriteMode(XORPut) ;

NVecE :•= 0; (Нет векторов в WE} MPF := False; {Мышь не нажималась} SetColor(Yellow) ;

GetMouseState(BM,XM,YM); (Начальное состояние ыыши} While True do /Бесконечный цикл до команды "Конец" } begin

{Проверяем выбор меню и клавиатуру} if KeyOrMousePressed then case ReadKeyOrMouse of

#0: case ReadKeyOrMouse of

#1 GetChar;

#2 SetChar;

#3 ClearWE;

#4 Pattern;

#5 Savefont;

#6 Exit;

end;

end;

{Проверяем текущее состояние мыши} GetMouseState(В,X,Y) ;

if (BOBM) or (XOXM) or (YOYM) then if MousePressed and

MouseIn(XE,YE,XE2,YE2) then

case В of {Контролируем кнопки} LeftButton :MouseInNed;

RightButton:MouseInLine;

end

else {Контролируем перемещение} MouseMove;

XM :» X;

YM := Y;

BM := В end end; {Run}

Procedure Done;

begin

SaveFont;

CloseGraph;

end; (Done} _•-————————————;

begin {Главная программа}

Init; {Инициация шрифта и экрана}

Run; {Редактирование или создание символов}

Done (Завершение работы}

end.

 

 Оглавление

На первую страницу

Rambler's Top100 Rambler's Top100
PROext: Top 1000

(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz