Страница 20 из 20
6.3.5 Копирование экрана на принтер (дамп экрана). Дамп текстового экрана сделать достаточно просто, если все используемые символы содержатся в ПЗУ принтера и ни один из них не выводится со специальными атрибутами, такими как подчеркивание или негативное изображение. В этом простейшем случае программе нужно лишь установить ширину принтера равной 80 символам, а затем считывать символы поочередно из видеобуфера, посылая их как неп- рерывный поток данных на принтер. Если в ПЗУ принтера отсутствуют специальные символы, такие как символы псевдографики, то програм- ма должна подготовить свою таблицу данных для этих символов и выводить их на принтер в графическом режиме. Поскольку эти симво- лы могут заходить в межстрочные интервалы, то может потребоваться специальное программирование [6.3.4]. Каждый из специальных атрибутов символов создает свои пробле- мы. Проверяйте атрибут каждого символа при считывании его из видеобуфера (в [4.1.3] обсуждается значение битов, соответствую- щее различным атрибутам). Когда символ выделен с помощью подчер- кивания или повышенной интенсивности, то надо включать подчерки- вание или печать жирным шрифтом на принтере. Однако если символ выводится в негативном изображении, то возникают те же проблемы, что и с некоторыми графическими символами: область негативного изображения должна простираться до верхнего края следующей стро- ки. В этом случае надо следуя указаниям [6.3.4] заполнить черным всю область при втором проходе. В зависимости от принтера, Вам может понадобиться создать специальную таблицу данных для вывода символов в негативе, поскольку когда они будут печататься, то окружающие точки могут находиться слишком близко одна к другой, затемняя изображаемый символ. В этом случае не может быть и речи о печати в два прохода. Простым решением проблемы с негативным изображением является использование графического режима экрана для вывода текста, а затем сделать дамп графического экрана. Графические дампы создают свои проблемы. Байт данных принтера соответствует восьми вертикальным точкам, в то время как на экра- не байт представляет 8 горизонтальных точек. Поэтому требуется процедура преобразования, показанная на рис. 6-4. Надо сразу получать по 8 байтов памяти экрана, выбирая такие, которые соот- ветствуют области точек 8*8. Затем надо использовать логические операции для перестановки битов, как показано в примерах. Имейте ввиду, что большинство матричных принтеров искажают экранное изображение. Это происходит потому, что они используют масштабный коэффициент 1:1, в то время как экран использует коэф- фициент 5:6 (масштабный коэффициент сравнивает число горизонталь- ных точек на дюйм с числом вертикальных точек на дюйм). Точнее говоря, искажение изображения на самом деле возникает из-за масш- табного коэффициента экрана, поскольку программы должны специаль- но менять данные для изображения, чтобы оно выглядело так, как нам хочется (например, изображение окружности на экране создается выводом на него эллипса). Когда данные с экрана выводятся на
принтер, то эти искажение должны обращаться. Некоторые графичес- кие принтеры имеют специальные режимы, в которых можно выводить копию экрана без искажения, а цветной принтер IBM может менять масштабный коэффициент в любом из своих графических режимов.
Высокий уровень. Приводимая процедура на Бейсике делает копию текстового экра- на, игнорируя специальные атрибуты:
10 OPEN "LPT1:" AS #1 'открываем принтер 20 DEF SEG = &HB000 'указываем на видеобуфер 30 PRINT #1,CHR$(13) 'сдвигаем головку влево 40 FOR G = 0 TO 3998 STEP 2 'для каждого байта буфера 50 PRINT #1,CHR$(PEEK(G)); 'читаем его и выводим на принтер 60 NEXT 'обрабатываем следующий байт
Переброска цепочек битов для графического дампа требует в Бейсике слишком много времени. Поместите в массив (здесь, BYTE$) восемь байтов, отвечающих области экрана 8*8 точек. Создайте второй массив (VERTICAL$) и обнулите его элементы, а затем поочередно перебрасывайте биты элементов этих массивов следующим образом:
500 FOR M = 0 TO 7 'для каждого бита 510 FOR N = 0 TO 7 'для каждого байта 520 X = ASC(BYTES(N)) 'получаем значение байта 530 Y = 2*(7 - M) 'маска для одного включенного бита 540 Z = X AND Y 'проверка этого бита в байте 550 IF Z <> 0 THEN VERTICAL$(M) = CHR$(ASC(VERTICAL$(M) OR 2*N) 'если он включен, то устанавливаем бит 'в соответствующей позиции 2-го массива 560 NEXT N 'следующий бит 570 NEXT M 'следующий байт
Низкий уровень. Язык ассемблера делает битовые преобразования намного быстрее. Вот процедура, которая делает эти преобразования ужасно быстро, поскольку она держит все в микропроцессоре (она немного великова- та, но Вы можете использовать взамен алгоритм, показанный в Бей- сике). Процедура работает, храня 8 результирующих байтов в ре- гистрах CX, DX, BP и DI. Байт экранных данных помещается в AL, а затем в AH передвигаются последовательно CL, CH, DL и DH. Каждый раз из AL в AH сдвигается один бит и когда сделаны 4 сдвига, то CX и DX обмениваются с DX и BP, после чего все это повторяется снова. Этот процесс повторяется для каждого из 8-ми экранных байтов и когда он завершен, то преобразованное изображение хра- нится в регистрах микропроцессора, причем самый левый байт данных для печати в CL. Содержимое регистров выводится на принтер и обнуляется, после чего процесс повторяется для следующих восьми байтов экрана. Сначала получите 8 байтов из видеобуфера и помес-
тите их в буфер с именем BUFFER. Поместите 0 в AX, CX, DX, BP и DI. Затем:
LEA BX,BUFFER ;указываем на буфер видеоданных MOV SI,0 ;смещение в этом буфере GET_BYTE: MOV AL,[BX][SI] ;берем байт DO_HALF: XCNG AH,CL ;получаем CL, CH, DL и DH SHL AX,1 ;сдвигая бит из AL XCNG AH,CL ; XCNG AH,CH ; SHL AX,1 ;
XCNG AH,CH ; XCNG AH,DL ; SHL AX,1 ; XCNG AH,DL ; XCNG AH,DH ; SHL AX,1 ; XCNG AH,DH ; ;---начинаем вторую половину перемещения битов XCNG CX,BP ;обмениваем содержимое CX и DX XCNG DX,DI ; CMP SI,7 ;если все байты преобразованы, то печатаем JE PRINT_BYTES ; INC SI ;иначе переходим к следующему байту JMP SHORT GET_BYTE ; ;---печатаем байты PRINT_BYTES: PUSH DX ;сохроаняем DX MOV AH,5 ;функция вывода на принтер MOV DL,27 ;код Esc INT 21H ;посылаем его MOV DL,75 ;код графического режима INT 21H ;посылаем его MOV DL,6 ;будет послано 6 байтов INT 21H ; MOV DL,0 ; INT 21H ; CALL PRINT_2_BYTES ;посылаем содержимое CX POP CX ; CALL PRINT_2_BYTES ;посылаем содержимое DX MOV CX,BP ; CALL PRINT_2_BYTES ;посылаем содержимое BP MOV DX,DI ; CALL PRINT_2_BYTES ;посылаем содержимое DI . (идем к следующей группе из восьми байтов) . PRINT_2_BYTES: PROC NEAR MOV AH,5 ;функция печати MOV DL,CL ;сначала CL INT 21H ;печатаем MOV DL,CH ;затем CH INT 21H ;печатаем RET PRINT_2_BYTES ENDP
|