Бьерн Страуструп - Язык программирования С++. Главы 5-8
Страница 36. Монитор экрана



6.4.1 Монитор экрана

 Вначале было желание написать монитор экрана на С, чтобы еще больше
 подчеркнуть разделение между уровнями реализации. Но это оказалось
 утомительным, и поэтому выбрано компромиссное решение: стиль
 программирования, принятый в С (нет функций-членов, виртуальных
 функций, пользовательских операций и т.д.), но используются
 конструкторы, параметры функций полностью описываются и проверяются
 и т.д. Этот монитор очень напоминает программу на С, которую
 модифицировали, чтобы воспользоваться возможностями С++, но
 полностью переделывать не стали.
      Экран представлен как двумерный массив символов и управляется
 функциями put_point() и put_line(). В них для связи с экраном
 используется структура point:

         // файл screen.h

         const int XMAX=40;
         const int YMAX=24;

         struct point {
             int x, y;
             point() { }
             point(int a,int b) { x=; y=b; }
         };

         extern void put_point(int a, int b);
         inline void put_point(point p) { put_point(p.x,p.y); }

         extern void put_line(int, int, int, int);
         extern void put_line(point a, point b)
            { put_line(a.x,a.y,b.x,b.y); }

         extern void screen_init();
         extern void screen_destroy();
         extern void screen_refresh();
         extern void screen_clear();

         #include <iostream.h>

    До вызова функций, выдающих изображение на экран (put_...), необходимо
 обратиться к функции инициализации экрана screen_init(). Изменения
 в структуре данных, описывающей экран, станут видимы на нем
 только после вызова функции обновления экрана screen_refresh().
 Читатель может убедиться, что обновление экрана происходит
 просто с помощью копирования новых значений в массив, представляющий
 экран. Приведем функции и определения данных для управления
 экраном:

         #include "screen.h"
         #include <stream.h>

         enum color { black='*', white=' ' };

         char screen[XMAX] [YMAX];

         void screen_init()
         {
           for (int y=0; y<YMAX; y++)
               for (int x=0; x<XMAX; x++)
                   screen[x] [y] = white;
         }

 Функция

         void screen_destroy() { }

 приведена просто для полноты картины. В реальных системах обычно
 нужны подобные функции уничтожения объекта.
      Точки записываются, только если они попадают на экран:

        inline int on_screen(int a, int b)  // проверка попадания
        {
           return 0<=a && a <XMAX && 0<=b && b<YMAX;
        }

        void put_point(int a, int b)
        {
           if (on_screen(a,b)) screen[a] [b] = black;
        }

 Для рисования прямых линий используется функция put_line():

        void put_line(int x0, int y0, int x1, int y1)
        /*
           Нарисовать отрезок прямой (x0,y0) - (x1,y1).
           Уравнение прямой: b(x-x0) + a(y-y0) = 0.
           Минимизируется величина abs(eps),
           где eps = 2*(b(x-x0)) + a(y-y0).
           См. Newman, Sproull
           ``Principles of interactive Computer Graphics''
           McGraw-Hill, New York, 1979. pp. 33-34.
         */
         {
           register int dx = 1;
           int a = x1 - x0;
           if (a < 0) dx = -1, a = -a;

           register int dy = 1;
           int b = y1 - y0;
           if (b < 0) dy = -1, b = -b;

           int two_a = 2*a;
           int two_b = 2*b;
           int xcrit = -b + two_a;
           register int eps = 0;

           for (;;) {
             put_point(x0,y0);
             if (x0==x1 && y0==y1) break;
             if (eps <= xcrit) x0 +=dx, eps +=two_b;
             if (eps>=a || a<b) y0 +=dy, eps -=two_a;
           }
         }

 Имеются функции для очистки и обновления экрана:

       void screen_clear() { screen_init(); }

       void screen_refresh()
       {
        for (int y=YMAX-1; 0<=y; y--) { // с верхней строки до нижней
           for (int x=0; x<XMAX; x++)   // от левого столбца до правого
               cout << screen[x] [y];
           cout << '\n';
        }
      }

 Но нужно понимать, что все эти определения хранятся в некоторой
 библиотеке как результат работы транслятора, и изменить их нельзя.

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