Справочник программиста на персональном компьютере фирмы 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