Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Копия X3.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
471 Кб
Скачать
☆

Программирование фона графических окон

Разработать программу для создания графического окна, фон которого отображает заданный рисунок из периодически повторяющихся геометрических фигур. Их взаимное расположение должно образовать замощение плоскости графического окна независимо от его геометрических размеров. Программную реализацию такого замощения должна обеспечивать карта пикселей минимального по размерам прямоугольного фрагмента рисунка фона, который повторяется в нем. Такая пиксельная карта должна конструироваться в программе минимальным набором примитивов графического вывода и адресоваться графическому окну структурой его атрибутов. Это должно гарантировать автоматическое тиражирование карты пикселей слева направо и сверху вниз в пределах графического окна, пока оно отображено на экране. Кроме того, необходимо предусмотреть возможность интерактивно инвертировать цвет рисунка фона по нажатию и отпусканию любой кнопки мыши, когда ее курсор находится в границах графического окна. Для этого в программе нужно реализовать соответствующую обработку событий и изображений для ее графического окна. При разработке программы необходимо использовать библиотечные функции базисного программного интерфейса X Window System.

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

Рис. Фон сопряженных колец (кольчуга)

Основная идея программной генерации фона графического окна Х-клиента состоит в том, чтобы подготовить пиксельную карту рисунка повторяющегося элемента фона и присвоить ее идентификатор фоновому атрибуту графического окна. После создания и визуализации окна это гарантирует автоматическое тиражирование заданного рисунка независимо от его исходных и текущих габаритов. Следующий листинг содержит исходный код программы генерации фона графического окна из сопряженных колец диаметром 128 пикселей, узор из которых показан на рисунке выше.

/* Генерация графического фона из сопряженных колец */

#include <X11/Xlib.h> /* заголовок базовой Х графики */

#include <X11/Xutil.h> /* заголовок графических утилит */

/* Габаритные макросы для рисунка фона*/

#define WIDTH 128 /* ширина повторяющегося элемента */

#define HEIGHT 128 /* высота повторяющегося элемента */

/* Основная функция программы */

int main(int argc, char* argv[]) {

Display* dpy; /* адрес дисплейной структуры */

int src; /* номер экрана дисплея */

GC gc; /* графический контекст */

int depth; /* число цветовых плоскостей экрана */

Window root; /* корневое окно экрана */

Pixmap pix; /* пиксельная карта элемента фона */

Window win; /* основное окно программы */

XSetWindowAttributes attr; /* атрибуты окна программы*/

unsigned long amask; /* маска атрибутов окна */

unsigned long emask; /* маска событий */

XEvent event; /* структура оконных событий */

unsigned int done = 0; /* флаг завершения программы */

/* Графическая инициализация */

dpy = XOpenDisplay(NULL); /* Контакт с Х-сервером */

src = DefaultScreen(dpy); /* номер экрана (0) */

depth = DefaultDepth(dpy, src); /* глубина экрана */

root = DefaultRootWindow(dpy); /* корневое окно */

gc = DefaultGC(dpy, src); /* графический контекст */

/* или gc = XCreateGC(dpy, root, 0, NULL); */

/* Формирование пиксельной карты элемента фона */

pix = XCreatePixmap(dpy, root, WIDTH, HEIGHT, depth);

XSetBackground(dpy, gc, WhitePixel(dpy, src));

XSetForeground(dpy, gc, WhitePixel(dpy, src));

XFillRectangle(dpy, pix, gc, 0, 0, WIDTH, HEIGHT);

XSetForeground(dpy, gc, BlackPixel(dpy, src));

XDrawArc(dpy, pix, gc, 0, 0, WIDTH, HEIGHT, 0, (360*64));

XFlush(dpy);

/* Оконный блок */

amask = (CWOverrideRedirect | CWBackPixmap);

attr.override_redirect = False; /* Обрамление окна */

attr.background_pixmap = pix; /* Фон пиксельной карты */

win = XCreateWindow(dpy, root, 0, 0, 800, 600, 1, depth,

InputOutput, CopyFromParent, amask, &attr);

emask = (ButtonPressMask | ButtonReleaseMask |

EnterWindowMask | LeaveWindowMask |

KeyPressMask); /* Маска событий */

XSelectInput(dpy, win, emask); /* маскировка событий */

XMapRaised(dpy, win); /* отображение окна */

XStoreName(dpy, win, "floor"); /* заголовок окна */

XSetFunction(dpy, gc, GXinvert); /* для инверсии фона */

/* или XSetFunction(dpy, gc, GXcopyInverted); */

/* Обработка событий */

while(done == 0) {

XNextEvent(dpy, &event); /* Чтение событий */

switch(event.type) {

case EnterNotify:

case LeaveNotify:

case ButtonPress:

case ButtonRelease: /* инвертировать фон окна */

XCopyArea(dpy, pix, pix, gc, 0, 0,

WIDTH, HEIGHT, 0, 0);

XSetWindowBackgroundPixmap(dpy, win, pix);

XClearWindow(dpy, win);

break;

case KeyPress: /* Выход из цикла обработки событий */

done = event.xkey.keycode;

break;

default: break;

} /* switch */

} /* while */

/* Графический выход */

XFreePixmap(dpy, pix); /* Освободить память карты */

XDestroyWindow(dpy, win); /* Закрыть окно */

XCloseDisplay(dpy); /* Разрыв связи с Х-сервером */

return(done); /* exit-код */

} /* main */

Согласно принципам структурного программирования функциональная часть этого исходного кода делится на пять последовательных логических блоков: графическая инициализация, формирование пиксельной карты фона, создание графического окна, обработка событий и графический выход. Их описание приводится ниже.

В начальном блоке графической инициализации по запросу XOpenDisplay адресуется структура дисплея. Затем устанавливается по умолчанию номер экрана, его корневое окно и число цветовых плоскостей, а также графический контекст изображения. Для получения этих дисплейных умолчаний вызываются соответствующие дисплейные макросы DefaultScreen, DefaultRootWindow, DefaultDepth и DefaultGC.

В следующем блоке формируется пиксельная карта повторяющегося элемента фона. При этом сначала по запросу XCreatePixmap создается пустая пиксельная карта требуемого размера (128х128) пикселей. Затем она заполняется белым квадратом по запросам XForeground (с белым макросом WhitePixel) и XFillRectangle. После этого в ней рисуется требуемое изображение черной окружности по запросам XForeground (с черным макросом BlackPixel) и XDrawArc. В общем случае для формирования изображения могут применяться различные примитивы графического вывода, например, прямоугольники и отрезки прямых линий, которые строятся по запросам XDrawRectangle(s), XDrawLine и XDrawSegments. Вместо такой векторной техники конструирования изображения в пиксельной карте могут также использоваться растровые шаблоны из битовых карт, которые формируются, например, программой графического клиента bitmap и отображаются по запросу XCreateBitmapFromData.

В третьем блоке по запросу XCreateWindow создается графическое окно программы с заданным начальным размером (800х600) пикселей, которое является подокном корневого окна экрана, копирует его визуальный класс и глубину. Оно также декорируется оконным менеджером по его атрибуту override_redirect со значением False. Фоновый атрибут окна background_pixmap фиксирует идентификатор пиксельной карты из предыдущего блока. Это гарантирует автоматическое заполнение фона окна рядами изображений пиксельной карты, независимо от изменений габаритов окна, когда оно отображается на экране. После создания окна, по запросу XSelectInput устанавливается маска получения событий нажатия (отпускания) кнопок мыши и клавиш на клавиатуре, когда курсор мыши находится в габаритах окна или пересекает его рамку. В конце оконного блока сформированное окно отображается на экране по запросу XMapRaised, перекрывая другие окна. Графическая утилита XStoreName фиксирует заголовок окна, заданный строкой "floor", в именном свойстве WM_NAME оконного менеджера, который отображает его в своем обрамлении окна. Кроме того, по запросу XSetFunction в графическом контексте устанавливается функция инвертирования изображения GXinvert или GXcopyInverted для последующих операций графического вывода в цикле обработки событий, чтобы обеспечить переключение цвета фона графического окна.

Четвертый блок реализует цикл чтения и обработки событий из очереди Х-сервера, которые установлены для графического окна программы в блоке 3. Чтение поступающих событий обеспечивает запрос XNextEvent, а альтернативы их обработки выбираются по полю типа в структуре XEvent каждого полученного события. В частности, для событий нажатия и отпускания любой кнопки мыши, когда ее курсор находится внутри окна, предусмотрена следующая обработка. Сначала инвертируется изображение в пиксельной карте фона путем копирования ее области саму на себя по запросу XCopyArea в графическом контексте с ранее установленной функцией инвертирования GXinvert (GXcopyInverted). Затем инвертированная таким образом пиксельная карта переустанавливается для фона графического окна по запросу XSetWindowBackgroundPixmap. Наконец, очистка окна по запросу XClearWindow реализует инвертирование его фонового рисунка. Аналогичная обработка предусматривается для события пересечения курсором рамки окна в любом направлении (EnterNotify и LeaveNotify). Итерации обработки этих мышиных событий могут продолжаться, пока значение флага завершения цикла done равно 0 (False). В альтернативе KeyPress обработки нажатия любой клавиши на клавиатуре (когда окно имеет фокус ввода) этому флагу присваивается значение ее физического кода из поля keycode структуры XEvent полученного события. Его величина гарантированно больше 0 для любой клавиши. Поэтому значение флага done становится положительным (True) и происходит выход из цикла обработки событий для последующего завершения программы.

В заключительном блоке 5 графического выхода предусмотрен типовой набор завершающих действий. Сначала по запросу XFreePixmap освобождается память, выделенная для пиксельной карты. Затем по запросу XDestroyWindow закрывается графическое окно программы. Наконец, запрос XCloseDisplay обеспечивает разрыв связи с X-сервером. Физический код клавиши, которая была нажата для выхода из цикла обработки событий, возвращает exit-код программы.

Рассмотренный исходный код программы генерации фона кольчуги можно приспособить для формирования графического фона с другим узором, изменив код рисования изображения в пиксельной карте повторяющегося фрагмента фона. После соответствующего редактирования исходный код программы следует сохранить под именем xfloor.c в рабочем каталоге файловой системы. Его компиляцию и компоновку с графической библиотекой libX11.so(.a) обеспечивает следующая командная строка, которая вводится в окне эмулятора терминала:

$ cc −o xfloor xfloor.c −lX11

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