Руководство программиста в Photon (1037671), страница 48
Текст из файла (страница 48)
PhPoint_t start_point = { 0, 0 };
int num_points = 6;
PhPoint_t points[6] = {
{ 32,21 }, { 50,30 }, { 50,50 },
{ 32,59 }, { 15,50 }, { 15,30 }
};
PgSetFillColor( Pg_BLUE );
PgSetStrokeColor( Pg_WHITE );
PgDrawPolygon( points, num_points, start_point, Pg_DRAW_FILL_STROKE | Pg_CLOSED );
}
Перекрытие многоугольников
Многоугольники, которые чем-то перекрываются, заполняются с использованием так называемого правила чёт-нечет: если область пересекается чётное количество раз, она не заполнена. Чтобы понять это, давайте нарисуем горизонтальную линию, пересекающую многоугольник. Когда Вы идёте вдоль этой линии и пересекаете первую линию, Вы оказываетесь внутри многоугольника; пересекая вторую линию – выходите наружу. В качестве примера рассмотрим простой многоугольник:
Заполнение простого многоугольника
Это правило можно расширить на более сложные многоугольники:
-
Когда Вы пересекаете нечётное число линий, Вы находитесь внутри многоугольника, так что область заполнена.
-
Когда Вы пересекаете чётное число линий, Вы находитесь вне многоугольника, так что область не заполнена.
Заполнение перекрывающися многоугольников
Правило чёт-нечет применимо и к функции PgDrawPoligon() и к PgDrawPoligonmx().
Дуги, круги, хорды и сектора
Функция PgDrawArd() может использоваться для рисования:
-
дуг
-
кругов
-
эллипсов
-
эллиптических дуг
-
сегментов
-
секторов
Чтобы нарисовать эллипс, можно также вызвать функцию PgDrawEllipse(). Начальный и конечный углы сегмента дуги задаются в бинарных градусах (bi-grads) – полный круг соответствует 65536 бинарным градусам (0х10000).
Чтобы нарисовать полный круг или эллипс, задайте одно и то же значение в бинарных градусах для начальнго и конечного углов. Например:
void DrawFullCurves( void ) {
PhPoint_t circle_center = { 150, 150 }, ellipse_center = { 150, 300 };
PhPoint_t circle_radii = { 100, 100 }, ellipse_radii = { 100, 50 };
/* Рисование белого, незаполненного круга. */
PgSetStrokeColor( Pg_WHITE );
PgDrawArc( &circle_center, &circle_radii, 0, 0, Pg_DRAW_STROKE | Pg_ARC );
/* Рисование чёрного эллипса с белым контуром. */
PgSetFillColor( Pg_BLACK );
PgDrawArc( &ellipse_center, &ellipse_radii, 0, 0, Pg_DRAW_FILL_STROKE | Pg_ARC );
}
Чтобы нарисовать сегмент (кривую, у которой крайние точки соединены прямой линией), добавьте к параметру flags значение Pg_ARC_CHORD. Например:
void DrawChord( void ) {
PhPoint_t center = { 150, 150 };
PhPoint_t radii = { 100, 50 };
/* Рисование чёрного эллиптического сегмента с белым контуром.
Дуга рисуется от 0 градусов до 45градусов (0x2000 биградусов). */
PgSetStrokeColor( Pg_WHITE );
PgSetFillColor( Pg_BLACK );
PgDrawArc( ¢er, &radii, 0, 0x2000, Pg_DRAW_FILL_STROKE | Pg_ARC_CHORD );
}
Сходным образом, чтобы нарисовать сектор или дугу, добавьте к flags значения Pg_ARC_PIE или Pg_ARC. Например:
void DrawPieCurve( void ) {
PhPoint_t pie_center = { 150, 150 },
arc_center = { 150, 300 };
PhPoint_t pie_radii = { 100, 50 },
arc_radii = { 50, 100 };
/* Рисование чёрного эллиптического сектора с белым контуром. */
PgSetStrokeColor( Pg_WHITE );
PgSetFillColor( Pg_BLACK );
PgDrawArc( &pie_center, &pie_radii, 0, 0x2000, Pg_DRAW_FILL_STROKE | Pg_ARC_PIE );
/* Рисование чёрной дуги. */
PgSetStrokeColor( Pg_BLACK );
PgDrawArc( &arc_center, &arc_radii, 0, 0x2000, Pg_DRAW_STROKE | Pg_ARC );
}
Заполненные и очерченные дуги
Спэны – сложные кривые
Если кривая, которую Вы хотите нарисовать, не может быть выражена как какая-либо другая кривая, поддерживаемая Photon'овским микроGUI, Вы можете нарисовать её как набор спэнов, вызвав функцию PgDrawSpan(). Эта функция в качестве одного из своих аргументов получает массив записей типа PgSpan_t.
Членами такой записи являются:
short x1 | Начальная позиция по x1 |
short x2 | Конечная позиция по x2 |
short y | Позиция по y |
Линии, пиксели и массивы пикселей
Линии и пиксели рисуются с использованием текущего состояния черты (цвет, толщина и пр.). Примитивами рисования являются:
PgDrawBezier(), PgDrawBeziermx() | Рисование очерченных и/или заполненных кривых Безье |
PgDrawGrid() | Рисование сетки |
PgDrawLine(), PgDrawILine() | Рисование одинарной линии |
PgDrawPixel(), PgDrawIPixel() | Рисование одной точки |
PgDrawPixelArray(), PgDrawPixelArraymx() | Рисование множества точек |
PgDrawTrend(), PgDrawTrendmx() | Рисование направленного графика (trend graph) |
В следующем примере рисуются красная, зелёная и синяя линии:
void DrawLines( void ) {
PgSetStrokeColor( Pg_RED );
PgDrawILine( 8, 8, 152, 8 );
PgSetStrokeColor( Pg_GREEN );
PgDrawILine( 8, 8, 152, 60 );
PgSetStrokeColor( Pg_BLUE );
PgDrawILine( 8, 8, 152, 112 );
}
Линии, созданные примитивами рисования
Текст
В заисимости от Ваших потребностей можно использовать различные процедуры рисования текста:
PgDrawMultiTextArea() | Рисование в некой области многострочного текста |
PgDrawString(), PgDrawStringmx() | Рисование строки символов |
PgDrawText(), PgDrawTextmx() | Рисование текста |
PgDrawTextArea() | Рисование текста внутри некой области |
PgDrawTextChars() | Рисование заданного количества текстовых символов |
PgExtentMultiText() | Вычисление пространства, занимаемого многострочной текстовой строкой |
PgExtentText() | Вычисление пространства, занимаемого строкой текста |
Текст рисуется с использованием текущих значений текстовых атрибутов; более подробно см. в разделе "Текстовые атрибуты" выше. Если Вы устанавливаете flags в значение Pg_BACK_FILL, пространство, занимаемое текстом, заполняется в соответствии с текущими атрибутами заполнения (см. "Атрибуты заполнения"). Если Вы задали подчёркивание с помощью PgSetUnderline(), подчёркивание рисуется под текстом и вверху фоновой заливки.
Например, чтобы напечатать чёрный текст 18-пунктовым шрифтом Helvetica:
void DrawSimpleText( void ) {
char *s = "Hello World!";
PhPoint_t p = { 8, 30 };
char Helvetica18[MAX_FONT_TAG];
if (PfGenerateFontName("Helvetica", 0, 18, Helvetica18) == NULL) {
perror("Невозможно сгенерировать имя шрифта ");
}
else { PgSetFont( Helvetica18 ); }
PgSetTextColor( Pg_BLACK );
PgDrawText( s, strlen( s ), &p, 0 );
}
Чтобы напечатать чёрный текст на голубом фоне:
void DrawBackFillText( void ) {
char *s = "Hello World!";
PhPoint_t p = { 8, 30 };
char Helvetica18[MAX_FONT_TAG];
if (PfGenerateFontName("Helvetica", 0, 18, Helvetica18) == NULL) {
perror("Невозможно сгенерировать имя шрифта");
}
else { PgSetFont( Helvetica18 ); }
PgSetTextColor( Pg_BLACK );
PgSetFillColor( Pg_CYAN );
PgDrawText( s, strlen( s ), &p, Pg_BACK_FILL );
}
Чтобы напечатать чёрный текст с красным подчёркиванием:
void DrawUnderlineText( void ) {
char *s = "Hello World!";
PhPoint_t p = { 8, 30 };
char Helvetica18[MAX_FONT_TAG];
if (PfGenerateFontName("Helvetica", 0, 18, Helvetica18) == NULL) {
perror("Невозможно сгенерировать имя шрифта");
}
else { PgSetFont( Helvetica18 ); }
PgSetTextColor( Pg_BLACK );
PgSetUnderline( Pg_RED, Pg_TRANSPARENT, 0 );
PgDrawText( s, strlen( s ), &p, 0 );
PgSetUnderline( Pg_TRANSPARENT, Pg_TRANSPARENT, 0 );
}
Чтобы напечатать чёрный текст с красным подчёркиванием на голубом фоне:
void DrawBackFillUnderlineText( void ) {
char *s = "Hello World!";
PhPoint_t p = { 8, 30 };
char Helvetica18[MAX_FONT_TAG];
if (PfGenerateFontName("Helvetica", 0, 18, Helvetica18) == NULL) {
perror("Невозможно сгенерировать имя шрифта");
}
else { PgSetFont( Helvetica18 ); }
PgSetTextColor( Pg_BLACK );
PgSetFillColor( Pg_CYAN );
PgSetUnderline( Pg_RED, Pg_TRANSPARENT, 0 );
PgDrawText( s, strlen( s ), &p, Pg_BACK_FILL );
PgSetUnderline( Pg_TRANSPARENT, Pg_TRANSPARENT, 0 );
}
Тексты, созданные примитивами рисования
Побитовые образы (bitmaps)
Побитовые образы рисуются с использованием текущего состояния текста. Если Вы установили flags в Pg_BACK_FILL, пустые пиксели образа рисуются с использованием текущего состояния заполнения. Примитивами рисования для побитовых образов являются:
PgDrawBitmap(), PgDrawBitmapmx() Рисование побитового образа
PgDrawRepBitmap(), PgDrawRepBitmapmx() Рисование побитового образа несколько раз
В этом примере рисуется побитовый образ на прозрачном фоне:
void DrawSimpleBitmap( void ) {
PhPoint_t p = { 8, 8 };
PgSetTextColor( Pg_CELIDON );
PgDrawBitmap( TestBitmap, 0, &p, &TestBitmapSize, TestBitmapBPL, 0 );
}
Побитовый образ на прозрачном фоне
В этом примере рисуется побитовый образ на жёлтом фоне:
void DrawBackFillBitmap( void ) {
PhPoint_t p = { 8, 8 };
PgSetTextColor( Pg_CELIDON );
PgSetFillColor( Pg_YELLOW );
PgDrawBitmap( TestBitmap, Pg_BACK_FILL, &p, &TestBitmapSize, TestBitmapBPL, 0 );
}
Побитовый образ с затенённым фоном
Образы (images)
В этом разделе обсуждается:
-
Образы на основе палитры
-
Образы в непосредственных цветах
-
Образы в градиентных цветах
-
Создание образов
-
Кеширование образов
-
Прозрачность в образах
-
Отображение образов
-
Управление образами
-
Отключение образов
Photon'овский микроGUI поддерживает следующие основные типы образов:
-
В непосредственных цветах (direct color)
Состоит из:
-
данных образа – матрицы цветов (но необязательно типа PgColor_t). Каждый элемент в матрице является цветом пикселя.
Образы в непосредственных цветах имеют тип, начинающийся с Pg_IMAGE_DIRECT_
-
На основе палитры
Состоят из:
-
палитры – массива типа PgColor_t;
-
данных образа – матрицы, элементы которой являются смещениями в палитре.
Образы на основе палитры имеют тип, начинающийся с Pg_IMAGE_PALETTE_
-
В градиентных цветах
Цвета сгенерированы алгоритмически как градиент между двумя заданными цветами.
Вы можете определить любой образ через его размер пикселя [т.е. числом бит на пиксель – Прим. пер.], байтов на линию, данные образа и формат. Образ может быть сохранён в структуре типа PhImage_t (описанной в "Справочнике библиотечных функций Photon'а"). Область type этой структуры определяет тип образа.
Образы на основе палитры
Образы на основе палитры обеспечивают быстрый, компактный способ рисования образов. Перед тем как прорисовывать образ на основе палитры, Вы должны установить либо аппаратную, либо программную палитру, чтобы задать цвета образа. Установка аппаратной палитры изменяет физическую палитру. Весь набор цветов функции PgSetFillColor() выбирается из этой палитры. Другие процессы продолжают выбирать цвета из глобальной палитры Photon'овского микроGUI и могут выглядеть неверно. Когда Вы отключаете аппаратную палитру, остальные процессы возвращаются к нормальному отображению без перерисовки. Вы должны всегда отключать аппаратную палитру, когда Ваше окно теряет фокус.
Установка программной палитры позволяет Вам переопределить, какие цвета интерпретируются для данного рисуемого контекста без изменения физической палитры. Все цвета программной палитры отображаются на физическую палитру.
Если Ваша физическая палитра использует больше цветов, чем поддерживает Ваша графическая карта, некоторые цвета опускаются, и образ не будет выглядеть столь красиво.
Данные образа (байты или полубайты) являются индексом в текущей палитре. Например:
PgColor_t ImagePalette[256];
char *ImageData;
PhPoint_t ImageSize;
int ImageBPL;
void DrawYourImage( PhPoint_t pos ) {