Построение геометрических фигур. Прямые линии.
Геометрические фигуры являются наиболее подходящими объектами для первого знакомства с компьютерной графикой. Способы их построения зависят только от природы самой фигуры (линия, прямоугольник, эллипс и т. д.) и от используемого видеорежима. Если угодно, это программирование компьютерной графики в чистом виде, без многочисленных вспомогательных действий, которые неизбежны при выводе заранее заготовленных рисунков.
Прямые линии бывают горизонтальные, вертикальные и наклонные, от этого зависят способы (алгоритмы) их рисования. Линии на экране далеко не всегда являются гладкими, в большинстве случаев они ступенчатые. Гладкими могут быть только линии, угол наклона которых равен нулю или кратен 45 градусам. При других углах наклона линия становится ступенчатой.
В данном разделе описаны подпрограммы для рисования гладких линий, иллюстрирующие различные способы работы с адресами точек. Основную часть раздела занимают алгоритмы рисования горизонтальных прямых.
Рисование линии слева направо
В примере 3.6 приведены два варианта подпрограммы, для рисования горизонтальной линии в направлении слева направо. Перед их вызовом должно быть установлено окно видеопамяти, содержащее первую точку прямой, а ее адрес в этом окне указан в регистре di. В регистрах сх и ai помещаются, соответственно, количество точек в линии (длина прямой) и их код (цвет).
В этом и всех последующих примерах предполагается, что регистр еs содержит адрес видеосегмента (значение переменной vbuff).
Пример 3.6. Подпрограммы для рисования горизонтальной линии.
; Вариант 1, используется команда пересылки horline: mov es: [di], al запись кода точки в видеобуфер inc di увеличение адреса на 1 jne @F переход, если не нуль call NxtWin установка следующего окна @@: loop horline управление повторами цикла ret возврат из подпрограммы
; Вариант 2, используется строковая операция horline: stosb запись кода точки в видеобуфер or di, di начало нового сегмента? jne @F › нет call NxtWin установка следующего окна @@: loop horline управление повторами цикла ret возврат из подпрограммы
Различие между подпрограммами примера 3.6 состоит в том, что в одном случае для записи кода точки в видеопамять использована обычная команда пересылки, а в другом – строковая, которая сама увеличивает содержимое регистра di на 1. Поэтому в первом варианте адрес надо увеличивать, что и делает команда inc di, а во втором варианте просто проверяется его новое значение, это делает команда or di, di.
Как уже говорилось, при коррекции значение адреса может выйти за границу сегмента. В таком случае надо установить следующее окно. По мере записи кодов точек в видеопамять содержимое регистра di возрастает вплоть До значения 65 535 (код OFFFFh). Если к этой величине прибавить 1, то регистр di окажется очищенным, это и использовано в примере 3.6 в качестве признака необходимости смены окна. Если содержимое регистра di отлично т нуля, то команда jne @F обходит вызов процедуры NxtWIN, а если равно нулю, то она выполняется и происходит установка следующего окна.
В примере 3.6 впервые использованы локальные метки, поэтому опишем правила работы с ними. Все локальные метки имеют имя @@, после которого, как обычно, ставится двоеточие. В командах переходов или ветвлений вместо имени локальной метки применяются операторы @F или @в. Оператор @F (переход вперед) указывается, если локальная метка расположена ниже по тексту. Оператор @в (переход назад) применяется, если локальная метка расположена выше по тексту. Обнаружив один из этих операторов, Макроассемблер ищет в нужном направлении ближайшую локальную метку. Количество локальных меток в программе не ограничено, но их применение не должно затруднять визуальный анализ текста.
В обоих вариантах примера 3.6 линия рисуется слева направо, при этом номера точек и адреса байтов от шага к шагу увеличиваются. Это естественный способ построения изображения, при котором адреса точек корректируются наиболее просто, но он не применим, если при рисовании прямой значения одной или обеих координат уменьшаются. Простейшим примером является прямая линия, соединяющая правый верхний и левый нижний углы любой прямоугольной области. Ее можно провести снизу вверх или сверху вниз, но в любом случае значение одной координаты будет увеличиваться, а другой уменьшаться.