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

 
« Предыдущая статья   Следующая статья »