Маскируемый курсор
Маскировка является одним из способов исключения ненужных элементов изображения в процессе построения рисунка. Она применяется не только при выводе на экран курсоров и пиктограмм, но и во многих других случаях, например, при сборке рисунков из отдельных частей. Маска может быть подготовлена заранее с учетом особенностей рисунка или сформирована динамически, на основании анализа цветов строящегося рисунка. В данном разделе рассмотрена работа с готовой маской.
Как производится маскировка
В предыдущем разделе мы использовали тот факт, что при определенных условиях команда хоr инвертирует значение операнда-приемника. Заметим также, что у этой команды есть еще одно полезное свойство. Вспомним таблицу истинности логической функции "исключающее ИЛИ" (Табл. 5.1). Из нее, в частности, следует, что если один из двух операндов очищен, то результат выполнения команды хоr будет равен значению другого операнда. Следовательно, при наложении двух цветов с помощью операции хоr черный цвет становится прозрачным.
При построении маскируемого курсора та часть экрана, которую займет его изображение, предварительно окрашивается в черный цвет (очищается). С помощью команды хоr (или or) на чистом месте можно построить рисунок любого цвета. Чтобы не портить окружающий фон в образе рисунка, точки, дополняющие его основную часть до прямоугольника, должны иметь черный цвет. Это условие обязательно выполняется у стандартных рисунков курсоров и пиктограмм (см. пример 6.3).
Для закрашивания в черный цвет на место расположения выводимого рисунка накладывается маска. Как говорилось в предыдущем разделе, байты маски могут содержать только два значения кодов – 00 или OFFh. Маска является черно-белым рисунком, у которого черные точки соответствуют основной части маскируемого рисунка, а белые – черным точкам маскируемого рисунка, дополняющим его заготовку до прямоугольника.
Посмотрите на пример 6.3, и вы увидите, что маска соответствует основному рисунку.
Фактически маска как рисунок не используется. Она записывается в видеопамять с помощью логической операции "И" (конъюнкция), которую вычисляет команда and. При выполнении этой команды операнд приемника будет очищен, если очищен операнд источника и не изменится, если у операнда источника установлены все разряды. При маскировке источником являются байты маски, а приемником – байты видеопамяти. Поэтому после наложения маски очищенными будут только те байты видеопамяти, которые очищены в маске, а содержимое остальных не изменится.
Если вы внимательно проанализируете пример 6.3, то обнаружите что находящаяся в массиве pntmask маска очищает несколько большую часть экрана, чем нужно для размещения стрелки, хранящейся в массиве pat image. Это сделано для того, чтобы белая стрелка не потерялась на белом фоне. В результате наложения такой маски рисунок курсора на экране окажется окруженным черной окантовкой, и белая стрелка будет видна на любом фоне.
Схема построения рисунка
Для получения изображения маскируемого курсора на экране надо сохранить исходный фон, наложить на этот фон маску, полученный результат объединить с заготовкой рисунка с помощью команды хоr или or и записать его в видеопамять.
Сохранение исходного фона необходимо потому, что восстановить его после построения рисунка курсора невозможно. Для размещения сохраняемого фона в оперативной памяти надо зарезервировать массив pntbuff. Его размер соответствует размеру рисунка курсора в байтах, т. е. совпадает с размерами массивов pntimage и pntmask. Каждый из этих трех массивов занимает в памяти pntxsize pntYsize байтов. Массив Pntbuff надо расположить в том же сегменте, в котором находятся pntimage и pntmask. Мы будем считать, что они размещены в разделе данных задачи и доступ к ним происходит через сегментный регистр as. При этом буфер описывается так:
pntbuff db 294 dup (?); резервирование 294 байтов в разделе данных
Если вы расположите массивы в другом сегменте, то в подпрограмму придется внести незначительные изменения, о чем будет сказано после ее описания. Порядок расположения массивов не имеет значения, важно чтобы они находились в одном сегменте.