Предварительная подготовка рисунка
В исходном виде рисунок курсора и маска не удобны для многократного использования. Их надо распаковать, перевернуть, по возможности сократить и хранить в оперативной памяти до конца выполнения задачи.
Перед построением изображения курсора, как и любого рисунка, должна быть установлена палитра используемых цветов (см. Главу 4). В данном случае палитра хранится в формате BMP для Windows, который описан в Приложении А.
Замечание
Напомним, что в зависимости от способа установки палитры могут измениться коды точек рисунка курсора (но не маски).
Поворот рисунка и маски
Рисунок на экране проще строить в естественном порядке, т. е. в направлении слева направо и сверху вниз. В исходном виде рисунок и маска хранятся "вверх ногами", поэтому перед распаковкой их надо повернуть. При повороте переставляют 16 пар строк: первую строку с последней, вторую – с предпоследней и т. д.
В примере 6.2 показано, как можно программно переставить строки маски или черно-белого рисунка. Перед выполнением примера исходный файл должен быть прочитан в буфер, сегмент которого указывается в регистре fs, а смещение (адрес) рисунка или маски в буфере помещается в регистр di. Перевернутое изображение записывается на место исходного.
Пример 6.2. Поворот черно-белого рисунка или маски.
mov si, di копируем адрес первой строки add si, 124 получаем адрес последней строки mov ex, 16 количество пар строк turn: mov eax, fs: [di] еах = строка 1 xchg eax, f s: [si j еах = строка 2; fs: [si] = строка 1 mov fs: [di], eax fs: [di] = строка 2 add di, 04 адрес следующей строки sub si, 04 адрес предыдущей строки loop turn управление повторами цикла
Выполнение примера 6.2 начинается с подготовки адреса последней строки и задания количества переставляемых пар. Перестановку выполняет цикл, его первая команда имеет метку turn. Она копирует в регистр еах первую строку пары. Следующая команда переставляет содержимое еах и второй строки пары. Третья команда копирует содержимое еах в первую строку. В результате переставлена пара строк. Затем корректируются адреса строк, и команда loop повторяет выполнение цикла 16 раз.
При перестановке расположение байтов в строке не изменяется, поскольку пересылку выполняет одна команда. Для переворота цветного рисунка этот пример не подходит, т. к. для перестановки 16-ти байтов пары строк надо организовать внутренний цикл, а во внешнем подготавливать адреса переставляемой пары.
Распаковка рисунка и маски
Повернутые рисунок и маску надо распаковать и сохранить в оперативной памяти. Для их хранения выделяется два массива, размером по 1024 байта (один байт на точку). В дальнейшем мы будем называть их pntimage и pntmask, первый содержит распакованный рисунок курсора, а второй – маску.
При распаковке черно-белого рисунка содержимое каждого байта обрабатывается, начиная со старшего разряда, и значение каждого бита (0 пли I) помешается в соответствующий байт массива pntimage.
При распаковке 16-цветного рисунка в байты массива pntimage записываются сначала старшая, а затем младшая тетрада каждого байта упакованного рисунка. Коды распакованных точек изменяются от о до огь.
Подпрограммы распаковки строк 16- и 2-цветных рисунков приведены в примерах 3.17 и 3.18, но они записывают результат в видеопамять. Применительно к данному случаю их надо изменить так, чтобы результат записывался в оперативную память, и организовать цикл для распаковки всего рисунка или маски.
После распаковки рисунка будут получены коды цветов, являющиеся адресами строк прилагаемой палитры. Маловероятно, чтобы они совпали с кодами цветов системной палитры, с которой работает задача. Едва ли в ней код белого цвета будет равен 1 или OFh, как в прилагаемой к рисунку палитре. Поэтому у вас есть две возможности: либо преобразовать распакованные коды рисунка так, чтобы они соответствовали системной палитре, либо в системной палитре зарезервировать 2 или 16 первых регистров цвета для работы с курсором. Второй способ используется в Windows при работе в режимах PPG.
Последовательность действий при распаковке маски та же, что и при распаковке черно-белого рисунка. Если текущий бит маски содержит 0, то соответствующий байт массива pntmask очищается, но если текущий бит маски содержит 1, то устанавливаются все разряды соответствующего байта массива pntmask (в него записывается код OFFh). Это объясняется специфическим назначением маски – при ее наложении байты видеопамяти либо полностью очищаются, либо остаются без изменения.