Справочник программиста на персональном компьютере фирмы IBM. Принтер - Копирование экрана на принтер (дамп экрана)
ОГЛАВЛЕНИЕ
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