Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Программирование с использованием gtkmm 3. Виджет области рисования (DrawingArea)

Оригинал: Programming with gtkmm 3
Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Перевод: А.Панин

17.3. Рисование изогнутых линий

В дополнение к возможности рисования прямых линий Cairo предоставляет вам возможность простого рисования изогнутых линий (или, говоря техническим языком, кубических сплайнов Безье) с помощью функций Cairo::Context::curve_to() и Cairo::Context::rel_curve_to(). Эти функции принимают координаты удаленной точки наряду с координатами двух "контрольных" точек. Проще всего объяснить эти понятия на примере, поэтому давайте приступим к его рассмотрению.

17.3.1. Пример

Это простое приложение позволяет нарисовать изогнутую линию с помощью библиотеки Cairo и показывает контрольные точки для каждого из концов нарисованной изогнутой линии.

Рисунок 17-4: Область рисования - Линии
Область рисования - Линии

Исходный код

Файл: myarea.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: myarea.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Единственным принципиальным отличием данного примера от примера рисования прямых линий является реализация функции on_draw(), но при этом в данном примере используется несколько новых концепций и функций, поэтому их следует кратко рассмотреть.

Мы осуществляем вызов функции Cairo::Context::scale(), передавая значения ширины и высоты области рисования в качестве аргументов. Эта функция позволяет произвести масштабирование координатной системы пространства пользователя таким образом, что ширина и высота виджета станут равными 1.0 "единицы измерения". В данном случае не существует веской причины для масштабирования координатной системы описанным способом, но иногда масштабирование значительно упрощает выполнение операций рисования.

Методика вызова функции Cairo::Context::curve_to() должна быть достаточно понятна. Первая пара координат определяет контрольную точку для начала изогнутой линии. Вторая пара координат задает контрольную точку для окончания изогнутой линии, а последняя пара координат задает удаленную точку. Для небольшого упрощения визуализации концепции контрольных точек линия рисуется из каждой контрольной точки в конечную точку на изогнутой линии, с которой она ассоциирована. Обратите внимание на то, что обе эти линии с контрольными точками являются полупрозрачными. Такой эффект достигается благодаря использованию варианта функции set_source_rgb() с именем set_source_rgba(). Эта функция принимает четвертый аргумент, устанавливающий значение прозрачности цвета (корректные значения находятся в диапазоне от 0 до 1).

17.4. Рисование дуг и окружностей

В Cairo для рисования дуг, окружностей и эллипсов используется одна и та же функция Cairo::Context::arc(). Эта функция принимает пять аргументов. Первые два аргумента определяют координаты центральной точки дуги, третий аргумент определяет радиус дуги, а последние два аргумента - начальный и конечный угол дуги. Для измерения всех углов используются радианы, поэтому операция рисования круга аналогична операции рисования дуги от 0 до 2*M_PI радиан. Угол в 0 радиан совпадает с положительным направлением оси X (в системе координат пространства пользователя). Угол в M_PI/2 радиан (90 градусов) совпадает с положительным направлением оси Y (в системе координат пространства пользователя). Увеличение значений углов идет от положительно направления оси X к положительному направлению оси Y. Таким образом, при использовании стандартной матрицы преобразования увеличение значений углов происходит по часовой стрелке. (Помните о том, что положительным направлением оси Y в нашем случае является направление сверху вниз).

Для рисования эллипса вы можете произвести масштабирование текущей матрицы преобразования с использованием различных значений для преобразования координат по направлениям осей X и Y. Например, для рисования эллипса с центром в точке с координатами x, y и с размером, заданным с помощью значений ширины и высоты width и height, может быть использован следующий код:
context->save();
context->translate(x, y);
context->scale(width / 2.0, height / 2.0);
context->arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI);
context->restore();

17.4.1. Пример

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

Рисунок 17-5: Область рисования - Дуги
Область рисования - Дуги

Исходный код

Файл: myarea.h (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: myarea.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Файл: main.cc (Для использования совместно с gtkmm 3, а не с gtkmm 2)

Есть несколько вещей, о которых стоит упомянуть при рассмотрении кода примера. И снова единственным принципиальным отличием данного примера от предыдущих является реализация функции on_draw(), поэтому мы ограничимся внимательным рассмотрением именно этой функции. Дополнительно следует отметить, что код первой части этой функции практически идентичен соответствующему коду из предыдущих примеров, поэтому мы пропустим его.

Обратите внимание на то, что в этот раз мы поставили практически все параметры, в том числе ширину линий, в зависимость от высоты и ширины окна. Благодаря этому в моменты, когда вы изменяете размеры окна, производится масштабирование рисунка соответствующим образом. Также следует отметить то, что функция разделена на три фрагмента кода для рисования, каждый из которых ограничен вызовами функций save()/restore(), поэтому после каждой операции рисования происходит возвращение к известному состоянию контекста.

Фрагмент кода для рисования дуги содержит вызов новой функции close_path(). В результате использования этой функции происходит рисование прямой линии из текущей точки в начальную точку контура. Однако, существует значительное отличие между вызовом функции close_path() и рисованием линии до начальной точки контура вручную. В том случае, если вы используете функцию close_path(), линии будут аккуратно соединены. Если же вы вместо этого используете функцию line_to(), линии будут пересекаться в одной точке, но Cairo не будет осуществлять соединение этих линий каким-либо определенным методом.

Рисование дуг против часовой стрелки
Функция Cairo::Context::arc_negative() полностью аналогична функции Cairo::Context::arc(), но углы откладываются в противоположном направлении.

Следующий раздел : 17.5. Вывод текста.