<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0">
<channel>
<title>www.gnome.org.ru - Разработка/ВиджетыCairo/часть1</title>
<link>http://gnome.org.ru/wacko/Разработка/ВиджетыCairo/часть1</link>
<description>Изменения страницы http://gnome.org.ru/wacko/Разработка/ВиджетыCairo/часть1</description>
<language>en-us</language>
<item>
<title>2008-07-26 11:50:56</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2008-07-26+11%3A50%3A56</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a name=".razrabotka.vidzhetycairo.chast_1" href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-26+11%3A50%3A56">2008-07-26 11:50:56&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1">2008-07-27 13:19:52&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">&lt;a name="h91-1">&lt;/a>&lt;h2>Создание виджетов с&amp;nbsp;использованием Cairo и&amp;nbsp;GTK+ 2.8, часть 1&lt;/h2>
Исходная статья по&amp;nbsp;адресу: &lt;a href="http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28&lt;/a>&lt;br />
2 декабря 2005, Дэвид Мадэли (Davyd Madeley)&lt;br />
4 января 2006, Безденежных Сергей (sib-mail@mtu-net.ru)&lt;br />
&lt;br />
Начиная с&amp;nbsp;версии 2.8, GTK+ отрисовывает все&amp;nbsp;свои элементы интерфейса с&amp;nbsp;помощью мощной библиотеки векторной графики Cairo. В&amp;nbsp;этой статье рассказывается как&amp;nbsp;можно самому создать виджет GTK+, используя библиотеки Cairo для&amp;nbsp;его отрисовки.&lt;br />
&lt;br />
Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;!--notypo-->OpenGL&lt;!--/notypo-->.&lt;br />
Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой &lt;a href="http://www.cairographics.org/introduction" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />Cairo 1.0&lt;/a>, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
&lt;a name="h91-2">&lt;/a>&lt;h3>Шаг 1. Пишем GObject&lt;/h3>
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Первый шаг&amp;nbsp;к&amp;nbsp;написанию своего собственного виджета – это&amp;nbsp;создание нового потомка универсального класса GObject. Всестороннее рассмотрение создания потомка GObject может стать сложной задачей, поэтому мы&amp;nbsp;остановимся на&amp;nbsp;рассмотрении ключевых моментов, необходимых для&amp;nbsp;написания нашего виджета.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;!--notypo-->GtkObject&lt;!--/notypo--> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo--> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Класс создается только один раз, тогда как&amp;nbsp;экземпляр класса создается каждый раз, когда мы&amp;nbsp;создаем новую копию виджета. Если все&amp;nbsp;это сбивает вас&amp;nbsp;с&amp;nbsp;толку или&amp;nbsp;вы&amp;nbsp;не знакомы с&amp;nbsp;объектно-ориентированным программированием в&amp;nbsp;С, не&amp;nbsp;беспокойтесь, мы&amp;nbsp;будем постепенно углубляться с&amp;nbsp;тем что&amp;nbsp;бы&amp;nbsp;вы поняли смысл.&lt;br />
В&amp;nbsp;файле clock.c с&amp;nbsp;помощью макроса зададим имя&amp;nbsp;нашего нового класса:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">G_DEFINE_TYPE (EggClockFace, egg_clock_face, GTK_TYPE_DRAWING_AREA);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->.&lt;br />
Теперь нам&amp;nbsp;нужно определить структуры для&amp;nbsp;нашего нового класса и&amp;nbsp;экземпляров этого класса. В&amp;nbsp;нашем примере эти&amp;nbsp;структуры достаточно просты. Если бы&amp;nbsp;мы хотели использовать общедоступные переменные и&amp;nbsp;структуры, то&amp;nbsp;объявили бы&amp;nbsp;их здесь. Локальные структуры определяются в&amp;nbsp;другом месте (рассмотрим это&amp;nbsp;позже). Так&amp;nbsp;что, в&amp;nbsp;clock.h пишем:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">typedef struct _EggClockFace            EggClockFace;
 typedef struct _EggClockFaceClass       EggClockFaceClass;

 struct _EggClockFace
 {
        GtkDrawingArea parent;

        /* private */
 };

 struct _EggClockFaceClass
 {
        GtkDrawingAreaClass parent_class;
 };&lt;/textarea>&lt;!--/notypo-->&lt;br />
Есть еще&amp;nbsp;несколько шаблонных строк, которые нужно включить в&amp;nbsp;заголовочный файл нового класса, они&amp;nbsp;позволят использовать те&amp;nbsp;удобные макросы, к&amp;nbsp;которым мы&amp;nbsp;привыкли при&amp;nbsp;использовании виджетов GTK+. Без&amp;nbsp;дальнейших объяснений, разместим это&amp;nbsp;в&amp;nbsp;начале файла clock.h:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">#define EGG_TYPE_CLOCK_FACE             (egg_clock_face_get_type ())
 #define EGG_CLOCK_FACE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_CLOCK_FACE, EggClockFace))
 #define EGG_CLOCK_FACE_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), EGG_CLOCK_FACE,  EggClockFaceClass))
 #define EGG_IS_CLOCK_FACE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_IS_CLOCK_FACE_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_CLOCK_FACE_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_CLOCK_FACE, EggClockFaceClass))&lt;/textarea>&lt;!--/notypo-->&lt;br />
Во&amp;nbsp;время инициализации класса, вызывается функция egg_clock_face_class_init(), которая позволяет задать функции и&amp;nbsp;свойства класса в&amp;nbsp;нашем новом классе. Так&amp;nbsp;как мы&amp;nbsp;выполняем рисование, нам&amp;nbsp;нужно переписать родительский обработчик показа виджета. Так&amp;nbsp;что пишем в&amp;nbsp;файле clock.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="10" readonly="readonly">static void
 egg_clock_face_class_init (EggClockFaceClass *class)
 {
        GtkWidgetClass *widget_class;

        widget_class = GTK_WIDGET_CLASS (class);

        widget_class-&amp;gt;expose_event = egg_clock_face_expose;
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Позже, в&amp;nbsp;функции class_init, с&amp;nbsp;помощью функции g_type_class_add_private() мы&amp;nbsp;сможем зарегистрировать локальные структуры класса.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;!--notypo-->GtkWidget&lt;!--/notypo--> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">static void
 egg_clock_face_init (EggClockFace *clock)
 { 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Обратите внимание на&amp;nbsp;то, что&amp;nbsp;рассмотренные до&amp;nbsp;сих пор&amp;nbsp;функции &amp;ndash; статические. Нужно запомнить, что&amp;nbsp;все эти&amp;nbsp;функции внутренние по&amp;nbsp;отношению к&amp;nbsp;объекту и&amp;nbsp;не описываются в&amp;nbsp;публичном API.&lt;br />
Нам&amp;nbsp;нужен какой-нибудь способ создания объекта, поэтому добавим функцию egg_clock_face_new().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="6" readonly="readonly">GtkWidget *
 egg_clock_face_new (void)
 {
        return g_object_new (EGG_TYPE_CLOCK_FACE, NULL); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Как&amp;nbsp;вы&amp;nbsp;видите эта&amp;nbsp;функция объявляется просто для&amp;nbsp;удобства.&lt;br />
В&amp;nbsp;конце концов, чтобы закончить, определим наш&amp;nbsp;обработчик рисования.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">static gboolean

 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь нужно написать главную функцию приложения main(). Вот&amp;nbsp;что получилось у&amp;nbsp;меня в&amp;nbsp;main.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">int
 main (int argc, char **argv)
 {
        GtkWidget *window;
        GtkWidget *clock;

        gtk_init (&amp;amp;argc, &amp;amp;argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        clock = egg_clock_face_new ();
        gtk_container_add (GTK_CONTAINER (window), clock);

        g_signal_connect (window, &amp;quot;destroy&amp;quot;,
                        G_CALLBACK (gtk_main_quit), NULL);

        gtk_widget_show_all (window);

        gtk_main ();
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы &lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex1.c, clock.h, and&amp;nbsp;main.c&lt;/a>.&lt;br />
Вы&amp;nbsp;можете скомпилировать все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex1.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
Запустив программу, вы&amp;nbsp;увидите окно, изображенное на&amp;nbsp;рисунке 1.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk1.png">file:cairogtk1.png&lt;/span>&lt;br />
Рисунок 1 &amp;ndash;  Пустое GTK&amp;nbsp;окно&lt;br />
Здорово, правда? Да&amp;nbsp;... может быть не&amp;nbsp;совсем. Теперь нам&amp;nbsp;нужно что-нибудь здесь нарисовать.&lt;br />
&lt;a name="h91-3">&lt;/a>&lt;h3>Шаг 2. Рисуем с&amp;nbsp;Cairo&lt;/h3>
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;!--notypo-->GdkEventExpose&lt;!--/notypo-->.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> и&amp;nbsp;&lt;!--notypo-->GtkWindow&lt;!--/notypo--> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;!--notypo-->GdkWindow&lt;!--/notypo--> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;br />
Получить доступ к&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> большинства виджетов (напр. &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->), можно обратившись к&amp;nbsp;свойству window структуры виджета, таким способом widget &amp;ndash; &amp;gt; window. Итак чтобы получить cairo_t в&amp;nbsp;нашем приложении, нужно немного дописать код:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE;

 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь виджет будет полностью перерисован, после каждого события перерисовки. Чтобы сделать перерисовку немного быстрее, определим область перерисовки.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        /* определяем область перерисовки */
        cairo_rectangle (cr,
                        event-&amp;gt;area.x, event-&amp;gt;area.y,
                        event-&amp;gt;area.width, event-&amp;gt;area.height);
        cairo_clip (cr);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь попробуем что-нибудь нарисовать внутри области перерисовки. С&amp;nbsp;Cairo процесс рисования представляет собой определение кривых, с&amp;nbsp;последующим их&amp;nbsp;вычерчиванием. Это&amp;nbsp;можно сравнить с&amp;nbsp;тем, как&amp;nbsp;будто вы&amp;nbsp;набрасываете рисунок простым карандашом, а&amp;nbsp;затем обрисовываете его&amp;nbsp;кистью. Вы&amp;nbsp;можете выбирать различные кисти с&amp;nbsp;различной толщиной линии и&amp;nbsp;цветом, однако каждое такое обрисовывание требует своей кисти. Вы&amp;nbsp;можете также делать другие вещи, например закрасить область цветом, внутри очерченной кривой и&amp;nbsp;только потом обвести ее&amp;nbsp;по контуру.&lt;br />
Вначале попробуем нарисовать циферблат часов, для&amp;nbsp;это потребуется немного вспомнить геометрию. Размер нашего холста (canvas), где&amp;nbsp;мы&amp;nbsp;будем рисовать, храниться в&amp;nbsp;структуре виджета под&amp;nbsp;названием &amp;#147;allocation&amp;#148;. Поэтому, найти центр нашего холста (x,y) достаточно просто:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double x, y;
 x = clock-&amp;gt;allocation.x + clock-&amp;gt;allocation.width / 2;
 y = clock-&amp;gt;allocation.y + clock-&amp;gt;allocation.height / 2;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Так&amp;nbsp;как нам&amp;nbsp;надо нарисовать круг, попробуем нарисовать его&amp;nbsp;максимального радиуса, исходя из&amp;nbsp;размеров нашего холста:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double radius;
 radius = MIN (clock-&amp;gt;allocation.width / 2,
              clock-&amp;gt;allocation.height / 2) - 5;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Чтобы нарисовать циферблат нужно определить дугу с&amp;nbsp;центром в&amp;nbsp;(x,y) и&amp;nbsp;поворотом межу 0 и&amp;nbsp;2Пи радиан:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">cairo_arc (cr, x, y, radius, 0, 2 * M_PI);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Заполним получившейся круг белым цветом, а&amp;nbsp;потом обведем его&amp;nbsp;черным цветом:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">cairo_set_source_rgb (cr, 1, 1, 1);
 cairo_fill_preserve (cr);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Скомпилировав и&amp;nbsp;запустив, увидим изображенную на&amp;nbsp;рисунке 2 форму.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk2.png">file:cairogtk2.png&lt;/span>&lt;br />
Рисунок 2 &amp;ndash; Заготовка для&amp;nbsp;циферблата&lt;br />
Теперь добавим отметку для&amp;nbsp;каждого часа на&amp;nbsp;циферблате. Снова вспомним немного геометрии, нам&amp;nbsp;нужно разделить 2Пи на&amp;nbsp;12 частей, получается &lt;!--notypo-->Пи/6&lt;!--/notypo--> радиан на&amp;nbsp;каждую отметку.&lt;br />
Теперь нужно нарисовать линии изнутри круга к&amp;nbsp;его границам, такие линии можно определить, с&amp;nbsp;помощью функций cairo_move_to() и&amp;nbsp;cairo_line_to().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        inset = 0.1 * radius;

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Очень удобно, когда отметки на&amp;nbsp;циферблате для&amp;nbsp;12, 3, 6, 9 часов выделяются из&amp;nbsp;обычных отметок, попробуем сделать также.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        cairo_save (cr); /* save pen size to stack */

        if (i % 3 == 0)
        {
                inset = 0.2 * radius;
        }
        else
        {
                inset = 0.1 * radius;
                cairo_set_line_width (cr, 0.5 *
                                cairo_get_line_width (cr));
        }

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr);
        cairo_restore (cr); /* recover pen size from stack */
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Может быть вы&amp;nbsp;заметили, что&amp;nbsp;в&amp;nbsp;этом примере мы&amp;nbsp;использовали две&amp;nbsp;новых функции Cairo_save() и&amp;nbsp;cairo_restore(). Эти&amp;nbsp;функции позволяют нам&amp;nbsp;управлять стеком состояний Cairo. Чтобы сохранить старые значения ширины используемой кисти, просто поместим их&amp;nbsp;в стек. Теперь мы&amp;nbsp;можем изменять значение толщины и&amp;nbsp;вырисовывать пути, когда потребуется можно снова восстановить старые значения из&amp;nbsp;стека. Это&amp;nbsp;простой способ не&amp;nbsp;отслеживать значения кистей при&amp;nbsp;выполнении операций рисования.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;&lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/clock-ex3.c" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex3.c&lt;/a>. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex3.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
увидите пустой циферблат часов, изображенный на&amp;nbsp;рисунке 3.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk3.png">file:cairogtk3.png&lt;/span>&lt;br />
Рисунок 3 &amp;ndash; Форма циферблата&lt;br />
Итак, мы&amp;nbsp;рассмотрели некоторые способы рисования на&amp;nbsp;холсте и&amp;nbsp;убедились, что&amp;nbsp;при возникновении события перерисовки рисунок обновляется. В&amp;nbsp;следующий раз&amp;nbsp;мы&amp;nbsp;рассмотрим, как&amp;nbsp;модифицировать наш&amp;nbsp;виджет, чтобы изобразить на&amp;nbsp;нем стрелку и&amp;nbsp;реализуем сигналы, обрабатывающие поступающую информацию.&lt;br />
Если вы&amp;nbsp;хотите узнать больше о&amp;nbsp;Cairo и&amp;nbsp;Cairo API, посетите сайт по&amp;nbsp;адресу: &lt;a href="http://www.cairographics.org/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.cairographics.org/&lt;/a>&lt;br />
&lt;br />&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">Perfect site! The&amp;nbsp;telling of&amp;nbsp;your story and&amp;nbsp;the story itself are&amp;nbsp;truly amazing bake macaroni and&amp;nbsp;cheese recipes Oh&amp;nbsp;yes, one&amp;nbsp;extra comment &amp;ndash; maybe you&amp;nbsp;could add&amp;nbsp;more pictures too! &lt;a href="http://babruiskanet.javabien.fr/new-year76/map.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://babruiskanet.javabien.fr/new-year76/map.html&lt;/a> aussie christmas recipes several, &lt;a href="http://nikuhivopol.ist-in-hamburg.de/fry-dadd8e/map.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://nikuhivopol.ist-in-hamburg.de/fry-dadd8e/map.html&lt;/a> nbc&amp;nbsp;today show holiday recipes,  Sincerely yours,&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2008-07-08 20:56:50</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2008-07-08+20%3A56%3A50</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-08+20%3A56%3A50">2008-07-08 20:56:50&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-26+11%3A50%3A56">2008-07-26 11:50:56&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">Perfect site! The&amp;nbsp;telling of&amp;nbsp;your story and&amp;nbsp;the story itself are&amp;nbsp;truly amazing bake macaroni and&amp;nbsp;cheese recipes Oh&amp;nbsp;yes, one&amp;nbsp;extra comment &amp;ndash; maybe you&amp;nbsp;could add&amp;nbsp;more pictures too! &lt;a href="http://babruiskanet.javabien.fr/new-year76/map.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://babruiskanet.javabien.fr/new-year76/map.html&lt;/a> aussie christmas recipes several, &lt;a href="http://nikuhivopol.ist-in-hamburg.de/fry-dadd8e/map.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://nikuhivopol.ist-in-hamburg.de/fry-dadd8e/map.html&lt;/a> nbc&amp;nbsp;today show holiday recipes,  Sincerely yours,&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">&lt;a name="h91-1">&lt;/a>&lt;h2>Создание виджетов с&amp;nbsp;использованием Cairo и&amp;nbsp;GTK+ 2.8, часть 1&lt;/h2>
Исходная статья по&amp;nbsp;адресу: &lt;a href="http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28&lt;/a>&lt;br />
2 декабря 2005, Дэвид Мадэли (Davyd Madeley)&lt;br />
4 января 2006, Безденежных Сергей (sib-mail@mtu-net.ru)&lt;br />
&lt;br />
Начиная с&amp;nbsp;версии 2.8, GTK+ отрисовывает все&amp;nbsp;свои элементы интерфейса с&amp;nbsp;помощью мощной библиотеки векторной графики Cairo. В&amp;nbsp;этой статье рассказывается как&amp;nbsp;можно самому создать виджет GTK+, используя библиотеки Cairo для&amp;nbsp;его отрисовки.&lt;br />
&lt;br />
Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;!--notypo-->OpenGL&lt;!--/notypo-->.&lt;br />
Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой &lt;a href="http://www.cairographics.org/introduction" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />Cairo 1.0&lt;/a>, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
&lt;a name="h91-2">&lt;/a>&lt;h3>Шаг 1. Пишем GObject&lt;/h3>
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Первый шаг&amp;nbsp;к&amp;nbsp;написанию своего собственного виджета – это&amp;nbsp;создание нового потомка универсального класса GObject. Всестороннее рассмотрение создания потомка GObject может стать сложной задачей, поэтому мы&amp;nbsp;остановимся на&amp;nbsp;рассмотрении ключевых моментов, необходимых для&amp;nbsp;написания нашего виджета.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;!--notypo-->GtkObject&lt;!--/notypo--> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo--> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Класс создается только один раз, тогда как&amp;nbsp;экземпляр класса создается каждый раз, когда мы&amp;nbsp;создаем новую копию виджета. Если все&amp;nbsp;это сбивает вас&amp;nbsp;с&amp;nbsp;толку или&amp;nbsp;вы&amp;nbsp;не знакомы с&amp;nbsp;объектно-ориентированным программированием в&amp;nbsp;С, не&amp;nbsp;беспокойтесь, мы&amp;nbsp;будем постепенно углубляться с&amp;nbsp;тем что&amp;nbsp;бы&amp;nbsp;вы поняли смысл.&lt;br />
В&amp;nbsp;файле clock.c с&amp;nbsp;помощью макроса зададим имя&amp;nbsp;нашего нового класса:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">G_DEFINE_TYPE (EggClockFace, egg_clock_face, GTK_TYPE_DRAWING_AREA);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->.&lt;br />
Теперь нам&amp;nbsp;нужно определить структуры для&amp;nbsp;нашего нового класса и&amp;nbsp;экземпляров этого класса. В&amp;nbsp;нашем примере эти&amp;nbsp;структуры достаточно просты. Если бы&amp;nbsp;мы хотели использовать общедоступные переменные и&amp;nbsp;структуры, то&amp;nbsp;объявили бы&amp;nbsp;их здесь. Локальные структуры определяются в&amp;nbsp;другом месте (рассмотрим это&amp;nbsp;позже). Так&amp;nbsp;что, в&amp;nbsp;clock.h пишем:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">typedef struct _EggClockFace            EggClockFace;
 typedef struct _EggClockFaceClass       EggClockFaceClass;

 struct _EggClockFace
 {
        GtkDrawingArea parent;

        /* private */
 };

 struct _EggClockFaceClass
 {
        GtkDrawingAreaClass parent_class;
 };&lt;/textarea>&lt;!--/notypo-->&lt;br />
Есть еще&amp;nbsp;несколько шаблонных строк, которые нужно включить в&amp;nbsp;заголовочный файл нового класса, они&amp;nbsp;позволят использовать те&amp;nbsp;удобные макросы, к&amp;nbsp;которым мы&amp;nbsp;привыкли при&amp;nbsp;использовании виджетов GTK+. Без&amp;nbsp;дальнейших объяснений, разместим это&amp;nbsp;в&amp;nbsp;начале файла clock.h:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">#define EGG_TYPE_CLOCK_FACE             (egg_clock_face_get_type ())
 #define EGG_CLOCK_FACE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_CLOCK_FACE, EggClockFace))
 #define EGG_CLOCK_FACE_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), EGG_CLOCK_FACE,  EggClockFaceClass))
 #define EGG_IS_CLOCK_FACE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_IS_CLOCK_FACE_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_CLOCK_FACE_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_CLOCK_FACE, EggClockFaceClass))&lt;/textarea>&lt;!--/notypo-->&lt;br />
Во&amp;nbsp;время инициализации класса, вызывается функция egg_clock_face_class_init(), которая позволяет задать функции и&amp;nbsp;свойства класса в&amp;nbsp;нашем новом классе. Так&amp;nbsp;как мы&amp;nbsp;выполняем рисование, нам&amp;nbsp;нужно переписать родительский обработчик показа виджета. Так&amp;nbsp;что пишем в&amp;nbsp;файле clock.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="10" readonly="readonly">static void
 egg_clock_face_class_init (EggClockFaceClass *class)
 {
        GtkWidgetClass *widget_class;

        widget_class = GTK_WIDGET_CLASS (class);

        widget_class-&amp;gt;expose_event = egg_clock_face_expose;
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Позже, в&amp;nbsp;функции class_init, с&amp;nbsp;помощью функции g_type_class_add_private() мы&amp;nbsp;сможем зарегистрировать локальные структуры класса.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;!--notypo-->GtkWidget&lt;!--/notypo--> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">static void
 egg_clock_face_init (EggClockFace *clock)
 { 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Обратите внимание на&amp;nbsp;то, что&amp;nbsp;рассмотренные до&amp;nbsp;сих пор&amp;nbsp;функции &amp;ndash; статические. Нужно запомнить, что&amp;nbsp;все эти&amp;nbsp;функции внутренние по&amp;nbsp;отношению к&amp;nbsp;объекту и&amp;nbsp;не описываются в&amp;nbsp;публичном API.&lt;br />
Нам&amp;nbsp;нужен какой-нибудь способ создания объекта, поэтому добавим функцию egg_clock_face_new().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="6" readonly="readonly">GtkWidget *
 egg_clock_face_new (void)
 {
        return g_object_new (EGG_TYPE_CLOCK_FACE, NULL); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Как&amp;nbsp;вы&amp;nbsp;видите эта&amp;nbsp;функция объявляется просто для&amp;nbsp;удобства.&lt;br />
В&amp;nbsp;конце концов, чтобы закончить, определим наш&amp;nbsp;обработчик рисования.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">static gboolean

 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь нужно написать главную функцию приложения main(). Вот&amp;nbsp;что получилось у&amp;nbsp;меня в&amp;nbsp;main.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">int
 main (int argc, char **argv)
 {
        GtkWidget *window;
        GtkWidget *clock;

        gtk_init (&amp;amp;argc, &amp;amp;argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        clock = egg_clock_face_new ();
        gtk_container_add (GTK_CONTAINER (window), clock);

        g_signal_connect (window, &amp;quot;destroy&amp;quot;,
                        G_CALLBACK (gtk_main_quit), NULL);

        gtk_widget_show_all (window);

        gtk_main ();
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы &lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex1.c, clock.h, and&amp;nbsp;main.c&lt;/a>.&lt;br />
Вы&amp;nbsp;можете скомпилировать все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex1.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
Запустив программу, вы&amp;nbsp;увидите окно, изображенное на&amp;nbsp;рисунке 1.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk1.png">file:cairogtk1.png&lt;/span>&lt;br />
Рисунок 1 &amp;ndash;  Пустое GTK&amp;nbsp;окно&lt;br />
Здорово, правда? Да&amp;nbsp;... может быть не&amp;nbsp;совсем. Теперь нам&amp;nbsp;нужно что-нибудь здесь нарисовать.&lt;br />
&lt;a name="h91-3">&lt;/a>&lt;h3>Шаг 2. Рисуем с&amp;nbsp;Cairo&lt;/h3>
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;!--notypo-->GdkEventExpose&lt;!--/notypo-->.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> и&amp;nbsp;&lt;!--notypo-->GtkWindow&lt;!--/notypo--> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;!--notypo-->GdkWindow&lt;!--/notypo--> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;br />
Получить доступ к&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> большинства виджетов (напр. &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->), можно обратившись к&amp;nbsp;свойству window структуры виджета, таким способом widget &amp;ndash; &amp;gt; window. Итак чтобы получить cairo_t в&amp;nbsp;нашем приложении, нужно немного дописать код:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE;

 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь виджет будет полностью перерисован, после каждого события перерисовки. Чтобы сделать перерисовку немного быстрее, определим область перерисовки.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        /* определяем область перерисовки */
        cairo_rectangle (cr,
                        event-&amp;gt;area.x, event-&amp;gt;area.y,
                        event-&amp;gt;area.width, event-&amp;gt;area.height);
        cairo_clip (cr);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь попробуем что-нибудь нарисовать внутри области перерисовки. С&amp;nbsp;Cairo процесс рисования представляет собой определение кривых, с&amp;nbsp;последующим их&amp;nbsp;вычерчиванием. Это&amp;nbsp;можно сравнить с&amp;nbsp;тем, как&amp;nbsp;будто вы&amp;nbsp;набрасываете рисунок простым карандашом, а&amp;nbsp;затем обрисовываете его&amp;nbsp;кистью. Вы&amp;nbsp;можете выбирать различные кисти с&amp;nbsp;различной толщиной линии и&amp;nbsp;цветом, однако каждое такое обрисовывание требует своей кисти. Вы&amp;nbsp;можете также делать другие вещи, например закрасить область цветом, внутри очерченной кривой и&amp;nbsp;только потом обвести ее&amp;nbsp;по контуру.&lt;br />
Вначале попробуем нарисовать циферблат часов, для&amp;nbsp;это потребуется немного вспомнить геометрию. Размер нашего холста (canvas), где&amp;nbsp;мы&amp;nbsp;будем рисовать, храниться в&amp;nbsp;структуре виджета под&amp;nbsp;названием &amp;#147;allocation&amp;#148;. Поэтому, найти центр нашего холста (x,y) достаточно просто:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double x, y;
 x = clock-&amp;gt;allocation.x + clock-&amp;gt;allocation.width / 2;
 y = clock-&amp;gt;allocation.y + clock-&amp;gt;allocation.height / 2;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Так&amp;nbsp;как нам&amp;nbsp;надо нарисовать круг, попробуем нарисовать его&amp;nbsp;максимального радиуса, исходя из&amp;nbsp;размеров нашего холста:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double radius;
 radius = MIN (clock-&amp;gt;allocation.width / 2,
              clock-&amp;gt;allocation.height / 2) - 5;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Чтобы нарисовать циферблат нужно определить дугу с&amp;nbsp;центром в&amp;nbsp;(x,y) и&amp;nbsp;поворотом межу 0 и&amp;nbsp;2Пи радиан:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">cairo_arc (cr, x, y, radius, 0, 2 * M_PI);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Заполним получившейся круг белым цветом, а&amp;nbsp;потом обведем его&amp;nbsp;черным цветом:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">cairo_set_source_rgb (cr, 1, 1, 1);
 cairo_fill_preserve (cr);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Скомпилировав и&amp;nbsp;запустив, увидим изображенную на&amp;nbsp;рисунке 2 форму.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk2.png">file:cairogtk2.png&lt;/span>&lt;br />
Рисунок 2 &amp;ndash; Заготовка для&amp;nbsp;циферблата&lt;br />
Теперь добавим отметку для&amp;nbsp;каждого часа на&amp;nbsp;циферблате. Снова вспомним немного геометрии, нам&amp;nbsp;нужно разделить 2Пи на&amp;nbsp;12 частей, получается &lt;!--notypo-->Пи/6&lt;!--/notypo--> радиан на&amp;nbsp;каждую отметку.&lt;br />
Теперь нужно нарисовать линии изнутри круга к&amp;nbsp;его границам, такие линии можно определить, с&amp;nbsp;помощью функций cairo_move_to() и&amp;nbsp;cairo_line_to().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        inset = 0.1 * radius;

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Очень удобно, когда отметки на&amp;nbsp;циферблате для&amp;nbsp;12, 3, 6, 9 часов выделяются из&amp;nbsp;обычных отметок, попробуем сделать также.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        cairo_save (cr); /* save pen size to stack */

        if (i % 3 == 0)
        {
                inset = 0.2 * radius;
        }
        else
        {
                inset = 0.1 * radius;
                cairo_set_line_width (cr, 0.5 *
                                cairo_get_line_width (cr));
        }

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr);
        cairo_restore (cr); /* recover pen size from stack */
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Может быть вы&amp;nbsp;заметили, что&amp;nbsp;в&amp;nbsp;этом примере мы&amp;nbsp;использовали две&amp;nbsp;новых функции Cairo_save() и&amp;nbsp;cairo_restore(). Эти&amp;nbsp;функции позволяют нам&amp;nbsp;управлять стеком состояний Cairo. Чтобы сохранить старые значения ширины используемой кисти, просто поместим их&amp;nbsp;в стек. Теперь мы&amp;nbsp;можем изменять значение толщины и&amp;nbsp;вырисовывать пути, когда потребуется можно снова восстановить старые значения из&amp;nbsp;стека. Это&amp;nbsp;простой способ не&amp;nbsp;отслеживать значения кистей при&amp;nbsp;выполнении операций рисования.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;&lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/clock-ex3.c" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex3.c&lt;/a>. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex3.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
увидите пустой циферблат часов, изображенный на&amp;nbsp;рисунке 3.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk3.png">file:cairogtk3.png&lt;/span>&lt;br />
Рисунок 3 &amp;ndash; Форма циферблата&lt;br />
Итак, мы&amp;nbsp;рассмотрели некоторые способы рисования на&amp;nbsp;холсте и&amp;nbsp;убедились, что&amp;nbsp;при возникновении события перерисовки рисунок обновляется. В&amp;nbsp;следующий раз&amp;nbsp;мы&amp;nbsp;рассмотрим, как&amp;nbsp;модифицировать наш&amp;nbsp;виджет, чтобы изобразить на&amp;nbsp;нем стрелку и&amp;nbsp;реализуем сигналы, обрабатывающие поступающую информацию.&lt;br />
Если вы&amp;nbsp;хотите узнать больше о&amp;nbsp;Cairo и&amp;nbsp;Cairo API, посетите сайт по&amp;nbsp;адресу: &lt;a href="http://www.cairographics.org/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.cairographics.org/&lt;/a>&lt;br />
&lt;br />&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2008-07-07 23:17:00</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2008-07-07+23%3A17%3A00</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-07+23%3A17%3A00">2008-07-07 23:17:00&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-08+20%3A56%3A50">2008-07-08 20:56:50&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">&lt;a name="h91-1">&lt;/a>&lt;h2>Создание виджетов с&amp;nbsp;использованием Cairo и&amp;nbsp;GTK+ 2.8, часть 1&lt;/h2>
Исходная статья по&amp;nbsp;адресу: &lt;a href="http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28&lt;/a>&lt;br />
2 декабря 2005, Дэвид Мадэли (Davyd Madeley)&lt;br />
4 января 2006, Безденежных Сергей (sib-mail@mtu-net.ru)&lt;br />
&lt;br />
Начиная с&amp;nbsp;версии 2.8, GTK+ отрисовывает все&amp;nbsp;свои элементы интерфейса с&amp;nbsp;помощью мощной библиотеки векторной графики Cairo. В&amp;nbsp;этой статье рассказывается как&amp;nbsp;можно самому создать виджет GTK+, используя библиотеки Cairo для&amp;nbsp;его отрисовки.&lt;br />
&lt;br />
Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;!--notypo-->OpenGL&lt;!--/notypo-->.&lt;br />
Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой &lt;a href="http://www.cairographics.org/introduction" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />Cairo 1.0&lt;/a>, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
&lt;a name="h91-2">&lt;/a>&lt;h3>Шаг 1. Пишем GObject&lt;/h3>
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Первый шаг&amp;nbsp;к&amp;nbsp;написанию своего собственного виджета – это&amp;nbsp;создание нового потомка универсального класса GObject. Всестороннее рассмотрение создания потомка GObject может стать сложной задачей, поэтому мы&amp;nbsp;остановимся на&amp;nbsp;рассмотрении ключевых моментов, необходимых для&amp;nbsp;написания нашего виджета.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;!--notypo-->GtkObject&lt;!--/notypo--> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo--> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Класс создается только один раз, тогда как&amp;nbsp;экземпляр класса создается каждый раз, когда мы&amp;nbsp;создаем новую копию виджета. Если все&amp;nbsp;это сбивает вас&amp;nbsp;с&amp;nbsp;толку или&amp;nbsp;вы&amp;nbsp;не знакомы с&amp;nbsp;объектно-ориентированным программированием в&amp;nbsp;С, не&amp;nbsp;беспокойтесь, мы&amp;nbsp;будем постепенно углубляться с&amp;nbsp;тем что&amp;nbsp;бы&amp;nbsp;вы поняли смысл.&lt;br />
В&amp;nbsp;файле clock.c с&amp;nbsp;помощью макроса зададим имя&amp;nbsp;нашего нового класса:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">G_DEFINE_TYPE (EggClockFace, egg_clock_face, GTK_TYPE_DRAWING_AREA);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->.&lt;br />
Теперь нам&amp;nbsp;нужно определить структуры для&amp;nbsp;нашего нового класса и&amp;nbsp;экземпляров этого класса. В&amp;nbsp;нашем примере эти&amp;nbsp;структуры достаточно просты. Если бы&amp;nbsp;мы хотели использовать общедоступные переменные и&amp;nbsp;структуры, то&amp;nbsp;объявили бы&amp;nbsp;их здесь. Локальные структуры определяются в&amp;nbsp;другом месте (рассмотрим это&amp;nbsp;позже). Так&amp;nbsp;что, в&amp;nbsp;clock.h пишем:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">typedef struct _EggClockFace            EggClockFace;
 typedef struct _EggClockFaceClass       EggClockFaceClass;

 struct _EggClockFace
 {
        GtkDrawingArea parent;

        /* private */
 };

 struct _EggClockFaceClass
 {
        GtkDrawingAreaClass parent_class;
 };&lt;/textarea>&lt;!--/notypo-->&lt;br />
Есть еще&amp;nbsp;несколько шаблонных строк, которые нужно включить в&amp;nbsp;заголовочный файл нового класса, они&amp;nbsp;позволят использовать те&amp;nbsp;удобные макросы, к&amp;nbsp;которым мы&amp;nbsp;привыкли при&amp;nbsp;использовании виджетов GTK+. Без&amp;nbsp;дальнейших объяснений, разместим это&amp;nbsp;в&amp;nbsp;начале файла clock.h:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">#define EGG_TYPE_CLOCK_FACE             (egg_clock_face_get_type ())
 #define EGG_CLOCK_FACE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_CLOCK_FACE, EggClockFace))
 #define EGG_CLOCK_FACE_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), EGG_CLOCK_FACE,  EggClockFaceClass))
 #define EGG_IS_CLOCK_FACE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_IS_CLOCK_FACE_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_CLOCK_FACE_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_CLOCK_FACE, EggClockFaceClass))&lt;/textarea>&lt;!--/notypo-->&lt;br />
Во&amp;nbsp;время инициализации класса, вызывается функция egg_clock_face_class_init(), которая позволяет задать функции и&amp;nbsp;свойства класса в&amp;nbsp;нашем новом классе. Так&amp;nbsp;как мы&amp;nbsp;выполняем рисование, нам&amp;nbsp;нужно переписать родительский обработчик показа виджета. Так&amp;nbsp;что пишем в&amp;nbsp;файле clock.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="10" readonly="readonly">static void
 egg_clock_face_class_init (EggClockFaceClass *class)
 {
        GtkWidgetClass *widget_class;

        widget_class = GTK_WIDGET_CLASS (class);

        widget_class-&amp;gt;expose_event = egg_clock_face_expose;
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Позже, в&amp;nbsp;функции class_init, с&amp;nbsp;помощью функции g_type_class_add_private() мы&amp;nbsp;сможем зарегистрировать локальные структуры класса.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;!--notypo-->GtkWidget&lt;!--/notypo--> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">static void
 egg_clock_face_init (EggClockFace *clock)
 { 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Обратите внимание на&amp;nbsp;то, что&amp;nbsp;рассмотренные до&amp;nbsp;сих пор&amp;nbsp;функции &amp;ndash; статические. Нужно запомнить, что&amp;nbsp;все эти&amp;nbsp;функции внутренние по&amp;nbsp;отношению к&amp;nbsp;объекту и&amp;nbsp;не описываются в&amp;nbsp;публичном API.&lt;br />
Нам&amp;nbsp;нужен какой-нибудь способ создания объекта, поэтому добавим функцию egg_clock_face_new().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="6" readonly="readonly">GtkWidget *
 egg_clock_face_new (void)
 {
        return g_object_new (EGG_TYPE_CLOCK_FACE, NULL); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Как&amp;nbsp;вы&amp;nbsp;видите эта&amp;nbsp;функция объявляется просто для&amp;nbsp;удобства.&lt;br />
В&amp;nbsp;конце концов, чтобы закончить, определим наш&amp;nbsp;обработчик рисования.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">static gboolean

 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь нужно написать главную функцию приложения main(). Вот&amp;nbsp;что получилось у&amp;nbsp;меня в&amp;nbsp;main.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">int
 main (int argc, char **argv)
 {
        GtkWidget *window;
        GtkWidget *clock;

        gtk_init (&amp;amp;argc, &amp;amp;argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        clock = egg_clock_face_new ();
        gtk_container_add (GTK_CONTAINER (window), clock);

        g_signal_connect (window, &amp;quot;destroy&amp;quot;,
                        G_CALLBACK (gtk_main_quit), NULL);

        gtk_widget_show_all (window);

        gtk_main ();
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы &lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex1.c, clock.h, and&amp;nbsp;main.c&lt;/a>.&lt;br />
Вы&amp;nbsp;можете скомпилировать все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex1.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
Запустив программу, вы&amp;nbsp;увидите окно, изображенное на&amp;nbsp;рисунке 1.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk1.png">file:cairogtk1.png&lt;/span>&lt;br />
Рисунок 1 &amp;ndash;  Пустое GTK&amp;nbsp;окно&lt;br />
Здорово, правда? Да&amp;nbsp;... может быть не&amp;nbsp;совсем. Теперь нам&amp;nbsp;нужно что-нибудь здесь нарисовать.&lt;br />
&lt;a name="h91-3">&lt;/a>&lt;h3>Шаг 2. Рисуем с&amp;nbsp;Cairo&lt;/h3>
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;!--notypo-->GdkEventExpose&lt;!--/notypo-->.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> и&amp;nbsp;&lt;!--notypo-->GtkWindow&lt;!--/notypo--> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;!--notypo-->GdkWindow&lt;!--/notypo--> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;br />
Получить доступ к&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> большинства виджетов (напр. &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->), можно обратившись к&amp;nbsp;свойству window структуры виджета, таким способом widget &amp;ndash; &amp;gt; window. Итак чтобы получить cairo_t в&amp;nbsp;нашем приложении, нужно немного дописать код:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE;

 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь виджет будет полностью перерисован, после каждого события перерисовки. Чтобы сделать перерисовку немного быстрее, определим область перерисовки.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        /* определяем область перерисовки */
        cairo_rectangle (cr,
                        event-&amp;gt;area.x, event-&amp;gt;area.y,
                        event-&amp;gt;area.width, event-&amp;gt;area.height);
        cairo_clip (cr);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь попробуем что-нибудь нарисовать внутри области перерисовки. С&amp;nbsp;Cairo процесс рисования представляет собой определение кривых, с&amp;nbsp;последующим их&amp;nbsp;вычерчиванием. Это&amp;nbsp;можно сравнить с&amp;nbsp;тем, как&amp;nbsp;будто вы&amp;nbsp;набрасываете рисунок простым карандашом, а&amp;nbsp;затем обрисовываете его&amp;nbsp;кистью. Вы&amp;nbsp;можете выбирать различные кисти с&amp;nbsp;различной толщиной линии и&amp;nbsp;цветом, однако каждое такое обрисовывание требует своей кисти. Вы&amp;nbsp;можете также делать другие вещи, например закрасить область цветом, внутри очерченной кривой и&amp;nbsp;только потом обвести ее&amp;nbsp;по контуру.&lt;br />
Вначале попробуем нарисовать циферблат часов, для&amp;nbsp;это потребуется немного вспомнить геометрию. Размер нашего холста (canvas), где&amp;nbsp;мы&amp;nbsp;будем рисовать, храниться в&amp;nbsp;структуре виджета под&amp;nbsp;названием &amp;#147;allocation&amp;#148;. Поэтому, найти центр нашего холста (x,y) достаточно просто:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double x, y;
 x = clock-&amp;gt;allocation.x + clock-&amp;gt;allocation.width / 2;
 y = clock-&amp;gt;allocation.y + clock-&amp;gt;allocation.height / 2;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Так&amp;nbsp;как нам&amp;nbsp;надо нарисовать круг, попробуем нарисовать его&amp;nbsp;максимального радиуса, исходя из&amp;nbsp;размеров нашего холста:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double radius;
 radius = MIN (clock-&amp;gt;allocation.width / 2,
              clock-&amp;gt;allocation.height / 2) - 5;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Чтобы нарисовать циферблат нужно определить дугу с&amp;nbsp;центром в&amp;nbsp;(x,y) и&amp;nbsp;поворотом межу 0 и&amp;nbsp;2Пи радиан:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">cairo_arc (cr, x, y, radius, 0, 2 * M_PI);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Заполним получившейся круг белым цветом, а&amp;nbsp;потом обведем его&amp;nbsp;черным цветом:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">cairo_set_source_rgb (cr, 1, 1, 1);
 cairo_fill_preserve (cr);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Скомпилировав и&amp;nbsp;запустив, увидим изображенную на&amp;nbsp;рисунке 2 форму.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk2.png">file:cairogtk2.png&lt;/span>&lt;br />
Рисунок 2 &amp;ndash; Заготовка для&amp;nbsp;циферблата&lt;br />
Теперь добавим отметку для&amp;nbsp;каждого часа на&amp;nbsp;циферблате. Снова вспомним немного геометрии, нам&amp;nbsp;нужно разделить 2Пи на&amp;nbsp;12 частей, получается &lt;!--notypo-->Пи/6&lt;!--/notypo--> радиан на&amp;nbsp;каждую отметку.&lt;br />
Теперь нужно нарисовать линии изнутри круга к&amp;nbsp;его границам, такие линии можно определить, с&amp;nbsp;помощью функций cairo_move_to() и&amp;nbsp;cairo_line_to().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        inset = 0.1 * radius;

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Очень удобно, когда отметки на&amp;nbsp;циферблате для&amp;nbsp;12, 3, 6, 9 часов выделяются из&amp;nbsp;обычных отметок, попробуем сделать также.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        cairo_save (cr); /* save pen size to stack */

        if (i % 3 == 0)
        {
                inset = 0.2 * radius;
        }
        else
        {
                inset = 0.1 * radius;
                cairo_set_line_width (cr, 0.5 *
                                cairo_get_line_width (cr));
        }

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr);
        cairo_restore (cr); /* recover pen size from stack */
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Может быть вы&amp;nbsp;заметили, что&amp;nbsp;в&amp;nbsp;этом примере мы&amp;nbsp;использовали две&amp;nbsp;новых функции Cairo_save() и&amp;nbsp;cairo_restore(). Эти&amp;nbsp;функции позволяют нам&amp;nbsp;управлять стеком состояний Cairo. Чтобы сохранить старые значения ширины используемой кисти, просто поместим их&amp;nbsp;в стек. Теперь мы&amp;nbsp;можем изменять значение толщины и&amp;nbsp;вырисовывать пути, когда потребуется можно снова восстановить старые значения из&amp;nbsp;стека. Это&amp;nbsp;простой способ не&amp;nbsp;отслеживать значения кистей при&amp;nbsp;выполнении операций рисования.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;&lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/clock-ex3.c" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex3.c&lt;/a>. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex3.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
увидите пустой циферблат часов, изображенный на&amp;nbsp;рисунке 3.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk3.png">file:cairogtk3.png&lt;/span>&lt;br />
Рисунок 3 &amp;ndash; Форма циферблата&lt;br />
Итак, мы&amp;nbsp;рассмотрели некоторые способы рисования на&amp;nbsp;холсте и&amp;nbsp;убедились, что&amp;nbsp;при возникновении события перерисовки рисунок обновляется. В&amp;nbsp;следующий раз&amp;nbsp;мы&amp;nbsp;рассмотрим, как&amp;nbsp;модифицировать наш&amp;nbsp;виджет, чтобы изобразить на&amp;nbsp;нем стрелку и&amp;nbsp;реализуем сигналы, обрабатывающие поступающую информацию.&lt;br />
Если вы&amp;nbsp;хотите узнать больше о&amp;nbsp;Cairo и&amp;nbsp;Cairo API, посетите сайт по&amp;nbsp;адресу: &lt;a href="http://www.cairographics.org/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.cairographics.org/&lt;/a>&lt;br />
&lt;br />&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">well,  In&amp;nbsp;some ways it&amp;nbsp;must have been an&amp;nbsp;emotional thing to&amp;nbsp;tell the&amp;nbsp;story, for&amp;nbsp;anyone to&amp;nbsp;read, as&amp;nbsp;the person may&amp;nbsp;or&amp;nbsp;may not&amp;nbsp;know you&amp;nbsp;com Brilliant but&amp;nbsp;simple idea. &lt;a href="http://kasonoli.white.prohosting.com/com3236.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://kasonoli.white.prohosting.com/com3236.html&lt;/a> com&amp;nbsp;I, &lt;a href="http://kasonolia.calimerou.fr/com7879.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://kasonolia.calimerou.fr/com7879.html&lt;/a> com,  Thanks&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:38:17</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A38%3A17</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A38%3A17">2006-04-09 12:38:17&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2008-07-07+23%3A17%3A00">2008-07-07 23:17:00&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">well,  In&amp;nbsp;some ways it&amp;nbsp;must have been an&amp;nbsp;emotional thing to&amp;nbsp;tell the&amp;nbsp;story, for&amp;nbsp;anyone to&amp;nbsp;read, as&amp;nbsp;the person may&amp;nbsp;or&amp;nbsp;may not&amp;nbsp;know you&amp;nbsp;com Brilliant but&amp;nbsp;simple idea. &lt;a href="http://kasonoli.white.prohosting.com/com3236.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://kasonoli.white.prohosting.com/com3236.html&lt;/a> com&amp;nbsp;I, &lt;a href="http://kasonolia.calimerou.fr/com7879.html" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://kasonolia.calimerou.fr/com7879.html&lt;/a> com,  Thanks&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">&lt;a name="h91-1">&lt;/a>&lt;h2>Создание виджетов с&amp;nbsp;использованием Cairo и&amp;nbsp;GTK+ 2.8, часть 1&lt;/h2>
Исходная статья по&amp;nbsp;адресу: &lt;a href="http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.gnomejournal.org/article/34/writing-a-widget-using-cairo-and-gtk28&lt;/a>&lt;br />
2 декабря 2005, Дэвид Мадэли (Davyd Madeley)&lt;br />
4 января 2006, Безденежных Сергей (sib-mail@mtu-net.ru)&lt;br />
&lt;br />
Начиная с&amp;nbsp;версии 2.8, GTK+ отрисовывает все&amp;nbsp;свои элементы интерфейса с&amp;nbsp;помощью мощной библиотеки векторной графики Cairo. В&amp;nbsp;этой статье рассказывается как&amp;nbsp;можно самому создать виджет GTK+, используя библиотеки Cairo для&amp;nbsp;его отрисовки.&lt;br />
&lt;br />
Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;!--notypo-->OpenGL&lt;!--/notypo-->.&lt;br />
Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой &lt;a href="http://www.cairographics.org/introduction" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />Cairo 1.0&lt;/a>, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
&lt;a name="h91-2">&lt;/a>&lt;h3>Шаг 1. Пишем GObject&lt;/h3>
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Первый шаг&amp;nbsp;к&amp;nbsp;написанию своего собственного виджета – это&amp;nbsp;создание нового потомка универсального класса GObject. Всестороннее рассмотрение создания потомка GObject может стать сложной задачей, поэтому мы&amp;nbsp;остановимся на&amp;nbsp;рассмотрении ключевых моментов, необходимых для&amp;nbsp;написания нашего виджета.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;!--notypo-->GtkObject&lt;!--/notypo--> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo--> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Класс создается только один раз, тогда как&amp;nbsp;экземпляр класса создается каждый раз, когда мы&amp;nbsp;создаем новую копию виджета. Если все&amp;nbsp;это сбивает вас&amp;nbsp;с&amp;nbsp;толку или&amp;nbsp;вы&amp;nbsp;не знакомы с&amp;nbsp;объектно-ориентированным программированием в&amp;nbsp;С, не&amp;nbsp;беспокойтесь, мы&amp;nbsp;будем постепенно углубляться с&amp;nbsp;тем что&amp;nbsp;бы&amp;nbsp;вы поняли смысл.&lt;br />
В&amp;nbsp;файле clock.c с&amp;nbsp;помощью макроса зададим имя&amp;nbsp;нашего нового класса:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">G_DEFINE_TYPE (EggClockFace, egg_clock_face, GTK_TYPE_DRAWING_AREA);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->.&lt;br />
Теперь нам&amp;nbsp;нужно определить структуры для&amp;nbsp;нашего нового класса и&amp;nbsp;экземпляров этого класса. В&amp;nbsp;нашем примере эти&amp;nbsp;структуры достаточно просты. Если бы&amp;nbsp;мы хотели использовать общедоступные переменные и&amp;nbsp;структуры, то&amp;nbsp;объявили бы&amp;nbsp;их здесь. Локальные структуры определяются в&amp;nbsp;другом месте (рассмотрим это&amp;nbsp;позже). Так&amp;nbsp;что, в&amp;nbsp;clock.h пишем:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">typedef struct _EggClockFace            EggClockFace;
 typedef struct _EggClockFaceClass       EggClockFaceClass;

 struct _EggClockFace
 {
        GtkDrawingArea parent;

        /* private */
 };

 struct _EggClockFaceClass
 {
        GtkDrawingAreaClass parent_class;
 };&lt;/textarea>&lt;!--/notypo-->&lt;br />
Есть еще&amp;nbsp;несколько шаблонных строк, которые нужно включить в&amp;nbsp;заголовочный файл нового класса, они&amp;nbsp;позволят использовать те&amp;nbsp;удобные макросы, к&amp;nbsp;которым мы&amp;nbsp;привыкли при&amp;nbsp;использовании виджетов GTK+. Без&amp;nbsp;дальнейших объяснений, разместим это&amp;nbsp;в&amp;nbsp;начале файла clock.h:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">#define EGG_TYPE_CLOCK_FACE             (egg_clock_face_get_type ())
 #define EGG_CLOCK_FACE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_CLOCK_FACE, EggClockFace))
 #define EGG_CLOCK_FACE_CLASS(obj)       (G_TYPE_CHECK_CLASS_CAST ((obj), EGG_CLOCK_FACE,  EggClockFaceClass))
 #define EGG_IS_CLOCK_FACE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_IS_CLOCK_FACE_CLASS(obj)    (G_TYPE_CHECK_CLASS_TYPE ((obj), EGG_TYPE_CLOCK_FACE))
 #define EGG_CLOCK_FACE_GET_CLASS        (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_CLOCK_FACE, EggClockFaceClass))&lt;/textarea>&lt;!--/notypo-->&lt;br />
Во&amp;nbsp;время инициализации класса, вызывается функция egg_clock_face_class_init(), которая позволяет задать функции и&amp;nbsp;свойства класса в&amp;nbsp;нашем новом классе. Так&amp;nbsp;как мы&amp;nbsp;выполняем рисование, нам&amp;nbsp;нужно переписать родительский обработчик показа виджета. Так&amp;nbsp;что пишем в&amp;nbsp;файле clock.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="10" readonly="readonly">static void
 egg_clock_face_class_init (EggClockFaceClass *class)
 {
        GtkWidgetClass *widget_class;

        widget_class = GTK_WIDGET_CLASS (class);

        widget_class-&amp;gt;expose_event = egg_clock_face_expose;
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Позже, в&amp;nbsp;функции class_init, с&amp;nbsp;помощью функции g_type_class_add_private() мы&amp;nbsp;сможем зарегистрировать локальные структуры класса.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;!--notypo-->GtkWidget&lt;!--/notypo--> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">static void
 egg_clock_face_init (EggClockFace *clock)
 { 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Обратите внимание на&amp;nbsp;то, что&amp;nbsp;рассмотренные до&amp;nbsp;сих пор&amp;nbsp;функции &amp;ndash; статические. Нужно запомнить, что&amp;nbsp;все эти&amp;nbsp;функции внутренние по&amp;nbsp;отношению к&amp;nbsp;объекту и&amp;nbsp;не описываются в&amp;nbsp;публичном API.&lt;br />
Нам&amp;nbsp;нужен какой-нибудь способ создания объекта, поэтому добавим функцию egg_clock_face_new().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="6" readonly="readonly">GtkWidget *
 egg_clock_face_new (void)
 {
        return g_object_new (EGG_TYPE_CLOCK_FACE, NULL); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Как&amp;nbsp;вы&amp;nbsp;видите эта&amp;nbsp;функция объявляется просто для&amp;nbsp;удобства.&lt;br />
В&amp;nbsp;конце концов, чтобы закончить, определим наш&amp;nbsp;обработчик рисования.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="7" readonly="readonly">static gboolean

 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь нужно написать главную функцию приложения main(). Вот&amp;nbsp;что получилось у&amp;nbsp;меня в&amp;nbsp;main.c:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">int
 main (int argc, char **argv)
 {
        GtkWidget *window;
        GtkWidget *clock;

        gtk_init (&amp;amp;argc, &amp;amp;argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        clock = egg_clock_face_new ();
        gtk_container_add (GTK_CONTAINER (window), clock);

        g_signal_connect (window, &amp;quot;destroy&amp;quot;,
                        G_CALLBACK (gtk_main_quit), NULL);

        gtk_widget_show_all (window);

        gtk_main ();
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы &lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex1.c, clock.h, and&amp;nbsp;main.c&lt;/a>.&lt;br />
Вы&amp;nbsp;можете скомпилировать все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex1.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
Запустив программу, вы&amp;nbsp;увидите окно, изображенное на&amp;nbsp;рисунке 1.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk1.png">file:cairogtk1.png&lt;/span>&lt;br />
Рисунок 1 &amp;ndash;  Пустое GTK&amp;nbsp;окно&lt;br />
Здорово, правда? Да&amp;nbsp;... может быть не&amp;nbsp;совсем. Теперь нам&amp;nbsp;нужно что-нибудь здесь нарисовать.&lt;br />
&lt;a name="h91-3">&lt;/a>&lt;h3>Шаг 2. Рисуем с&amp;nbsp;Cairo&lt;/h3>
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;!--notypo-->GdkEventExpose&lt;!--/notypo-->.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> и&amp;nbsp;&lt;!--notypo-->GtkWindow&lt;!--/notypo--> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;!--notypo-->GdkWindow&lt;!--/notypo--> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;br />
Получить доступ к&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> большинства виджетов (напр. &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->), можно обратившись к&amp;nbsp;свойству window структуры виджета, таким способом widget &amp;ndash; &amp;gt; window. Итак чтобы получить cairo_t в&amp;nbsp;нашем приложении, нужно немного дописать код:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE;

 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь виджет будет полностью перерисован, после каждого события перерисовки. Чтобы сделать перерисовку немного быстрее, определим область перерисовки.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">static gboolean
 egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
 {
        cairo_t *cr;

        /* получаем cairo_t */
        cr = gdk_cairo_create (clock-&amp;gt;window);

        /* определяем область перерисовки */
        cairo_rectangle (cr,
                        event-&amp;gt;area.x, event-&amp;gt;area.y,
                        event-&amp;gt;area.width, event-&amp;gt;area.height);
        cairo_clip (cr);

        draw (clock, cr);

        cairo_destroy (cr);

        return FALSE; 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Теперь попробуем что-нибудь нарисовать внутри области перерисовки. С&amp;nbsp;Cairo процесс рисования представляет собой определение кривых, с&amp;nbsp;последующим их&amp;nbsp;вычерчиванием. Это&amp;nbsp;можно сравнить с&amp;nbsp;тем, как&amp;nbsp;будто вы&amp;nbsp;набрасываете рисунок простым карандашом, а&amp;nbsp;затем обрисовываете его&amp;nbsp;кистью. Вы&amp;nbsp;можете выбирать различные кисти с&amp;nbsp;различной толщиной линии и&amp;nbsp;цветом, однако каждое такое обрисовывание требует своей кисти. Вы&amp;nbsp;можете также делать другие вещи, например закрасить область цветом, внутри очерченной кривой и&amp;nbsp;только потом обвести ее&amp;nbsp;по контуру.&lt;br />
Вначале попробуем нарисовать циферблат часов, для&amp;nbsp;это потребуется немного вспомнить геометрию. Размер нашего холста (canvas), где&amp;nbsp;мы&amp;nbsp;будем рисовать, храниться в&amp;nbsp;структуре виджета под&amp;nbsp;названием &amp;#147;allocation&amp;#148;. Поэтому, найти центр нашего холста (x,y) достаточно просто:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double x, y;
 x = clock-&amp;gt;allocation.x + clock-&amp;gt;allocation.width / 2;
 y = clock-&amp;gt;allocation.y + clock-&amp;gt;allocation.height / 2;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Так&amp;nbsp;как нам&amp;nbsp;надо нарисовать круг, попробуем нарисовать его&amp;nbsp;максимального радиуса, исходя из&amp;nbsp;размеров нашего холста:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="4" readonly="readonly">double radius;
 radius = MIN (clock-&amp;gt;allocation.width / 2,
              clock-&amp;gt;allocation.height / 2) - 5;&lt;/textarea>&lt;!--/notypo-->&lt;br />
Чтобы нарисовать циферблат нужно определить дугу с&amp;nbsp;центром в&amp;nbsp;(x,y) и&amp;nbsp;поворотом межу 0 и&amp;nbsp;2Пи радиан:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">cairo_arc (cr, x, y, radius, 0, 2 * M_PI);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Заполним получившейся круг белым цветом, а&amp;nbsp;потом обведем его&amp;nbsp;черным цветом:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="5" readonly="readonly">cairo_set_source_rgb (cr, 1, 1, 1);
 cairo_fill_preserve (cr);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);&lt;/textarea>&lt;!--/notypo-->&lt;br />
Скомпилировав и&amp;nbsp;запустив, увидим изображенную на&amp;nbsp;рисунке 2 форму.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk2.png">file:cairogtk2.png&lt;/span>&lt;br />
Рисунок 2 &amp;ndash; Заготовка для&amp;nbsp;циферблата&lt;br />
Теперь добавим отметку для&amp;nbsp;каждого часа на&amp;nbsp;циферблате. Снова вспомним немного геометрии, нам&amp;nbsp;нужно разделить 2Пи на&amp;nbsp;12 частей, получается &lt;!--notypo-->Пи/6&lt;!--/notypo--> радиан на&amp;nbsp;каждую отметку.&lt;br />
Теперь нужно нарисовать линии изнутри круга к&amp;nbsp;его границам, такие линии можно определить, с&amp;nbsp;помощью функций cairo_move_to() и&amp;nbsp;cairo_line_to().&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        inset = 0.1 * radius;

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr); 
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Очень удобно, когда отметки на&amp;nbsp;циферблате для&amp;nbsp;12, 3, 6, 9 часов выделяются из&amp;nbsp;обычных отметок, попробуем сделать также.&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="15" readonly="readonly">for (i = 0; i &amp;lt; 12; i++)
 {
        int inset;

        cairo_save (cr); /* save pen size to stack */

        if (i % 3 == 0)
        {
                inset = 0.2 * radius;
        }
        else
        {
                inset = 0.1 * radius;
                cairo_set_line_width (cr, 0.5 *
                                cairo_get_line_width (cr));
        }

        cairo_move_to (cr,
                        x + (radius - inset) * cos (i * M_PI / 6),
                        y + (radius - inset) * sin (i * M_PI / 6));
        cairo_line_to (cr,
                        x + radius * cos (i * M_PI / 6),
                        y + radius * sin (i * M_PI / 6));
        cairo_stroke (cr);
        cairo_restore (cr); /* recover pen size from stack */
 }&lt;/textarea>&lt;!--/notypo-->&lt;br />
Может быть вы&amp;nbsp;заметили, что&amp;nbsp;в&amp;nbsp;этом примере мы&amp;nbsp;использовали две&amp;nbsp;новых функции Cairo_save() и&amp;nbsp;cairo_restore(). Эти&amp;nbsp;функции позволяют нам&amp;nbsp;управлять стеком состояний Cairo. Чтобы сохранить старые значения ширины используемой кисти, просто поместим их&amp;nbsp;в стек. Теперь мы&amp;nbsp;можем изменять значение толщины и&amp;nbsp;вырисовывать пути, когда потребуется можно снова восстановить старые значения из&amp;nbsp;стека. Это&amp;nbsp;простой способ не&amp;nbsp;отслеживать значения кистей при&amp;nbsp;выполнении операций рисования.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;&lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/clock-ex3.c" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex3.c&lt;/a>. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;br />
&lt;!--notypo-->&lt;textarea class="code" rows="2" readonly="readonly">gcc -o clock `pkg-config --cflags --libs gtk+-2.0` clock.h clock-ex3.c main.c&lt;/textarea>&lt;!--/notypo-->&lt;br />
увидите пустой циферблат часов, изображенный на&amp;nbsp;рисунке 3.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk3.png">file:cairogtk3.png&lt;/span>&lt;br />
Рисунок 3 &amp;ndash; Форма циферблата&lt;br />
Итак, мы&amp;nbsp;рассмотрели некоторые способы рисования на&amp;nbsp;холсте и&amp;nbsp;убедились, что&amp;nbsp;при возникновении события перерисовки рисунок обновляется. В&amp;nbsp;следующий раз&amp;nbsp;мы&amp;nbsp;рассмотрим, как&amp;nbsp;модифицировать наш&amp;nbsp;виджет, чтобы изобразить на&amp;nbsp;нем стрелку и&amp;nbsp;реализуем сигналы, обрабатывающие поступающую информацию.&lt;br />
Если вы&amp;nbsp;хотите узнать больше о&amp;nbsp;Cairo и&amp;nbsp;Cairo API, посетите сайт по&amp;nbsp;адресу: &lt;a href="http://www.cairographics.org/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />http://www.cairographics.org/&lt;/a>&lt;br />
&lt;br />&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:34:26</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A34%3A26</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A34%3A26">2006-04-09 12:34:26&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A38%3A17">2006-04-09 12:38:17&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой &lt;a href="http://www.cairographics.org/introduction" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />Cairo 1.0&lt;/a>, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы &lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex1.c, clock.h, and&amp;nbsp;main.c&lt;/a>.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;&lt;a href="http://www.gnome.org/%7Edavyd/gnome-journal-cairo-article/clock-ex3.c" target="_blank" title="Внешняя ссылка (откроется в новом окне)" class="outerlink">&lt;img src="http://gnome.org.ru/wacko/themes/gnome/icons/web.gif" alt="" border="0" />clock-ex3.c&lt;/a>. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">Начиная с&amp;nbsp;версии 2.8, грaфический инструментарий GTK+ интегрирован с&amp;nbsp;библиотекой Cairo 1.0, предоставляя разработчикам доступ к&amp;nbsp;этому гибкому графическому API.&lt;br />
Итак, если вы&amp;nbsp;все сделали правильно, у&amp;nbsp;вас должны получится следующие файлы clock-ex1.c, clock.h, and&amp;nbsp;main.c.&lt;br />
Теперь файл с&amp;nbsp;инструкциями рисования будет иметь вид&amp;nbsp;like clock-ex3.c. Если вы&amp;nbsp;скомпилируете все&amp;nbsp;это с&amp;nbsp;помощью команды:&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:31:11</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A31%3A11</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A31%3A11">2006-04-09 12:31:11&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A34%3A26">2006-04-09 12:34:26&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;!--notypo-->GtkObject&lt;!--/notypo--> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo--> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;span class="missingpage">Gtk&amp;nbsp;Object&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkObject/edit?add=1" title="Создать эту страницу">?&lt;/a> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:30:01</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A30%3A01</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A30%3A01">2006-04-09 12:30:01&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A31%3A11">2006-04-09 12:31:11&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;!--notypo-->GdkWindow&lt;!--/notypo--> и&amp;nbsp;&lt;!--notypo-->GtkWindow&lt;!--/notypo--> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;!--notypo-->GdkWindow&lt;!--/notypo--> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;"'GdkWindow&lt;!--notypo--> (куда собственно мы будем рисовать). Нужно обратить внимание, что &lt;!--/notypo-->&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> и &lt;!--/notypo-->&lt;span class="missingpage">Gtk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> - разные вещи, все виды виджетов содержат в себе &lt;!--/notypo-->&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&amp;quot;&amp;quot; для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:18:37</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A18%3A37</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A18%3A37">2006-04-09 12:18:37&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A30%3A01">2006-04-09 12:30:01&lt;/a>&lt;/b>&lt;br />
&lt;br />
&lt;b>Добавлено:&lt;/b>&lt;br />
&lt;div class="additions">Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;!--notypo-->OpenGL&lt;!--/notypo-->.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>, который наследует свойства &lt;!--notypo-->GtkWidget&lt;!--/notypo-->, &lt;span class="missingpage">Gtk&amp;nbsp;Object&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkObject/edit?add=1" title="Создать эту страницу">?&lt;/a> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;!--notypo-->GtkDrawingArea&lt;!--/notypo-->.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;!--notypo-->EggClockFace&lt;!--/notypo-->, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;!--notypo-->GtkWidget&lt;!--/notypo--> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk1.png">file:cairogtk1.png&lt;/span>&lt;br />
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;!--notypo-->GdkEventExpose&lt;!--/notypo-->.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;"'GdkWindow&lt;!--notypo--> (куда собственно мы будем рисовать). Нужно обратить внимание, что &lt;!--/notypo-->&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> и &lt;!--/notypo-->&lt;span class="missingpage">Gtk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> - разные вещи, все виды виджетов содержат в себе &lt;!--/notypo-->&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> для рисования. Нестрашно, если вы сразу не запомните что куда, со временем вы поймете суть.&lt;br />Получить доступ к &lt;!--/notypo-->&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo--> большинства виджетов (напр. &lt;!--/notypo-->&lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>&lt;!--notypo-->), можно обратившись к свойству window структуры виджета, таким способом widget - &amp;gt; window. Итак чтобы получить cairo_t в нашем приложении, нужно немного дописать код:&lt;br />file:cairogtk2.png&lt;br />Теперь добавим отметку для каждого часа на циферблате. Снова вспомним немного геометрии, нам нужно разделить 2Пи на 12 частей, получается &lt;!--/notypo-->&lt;span class="missingpage">Пи&amp;nbsp;/&amp;nbsp;6&lt;/span>&lt;a href="http://gnome.org.ru/wacko/Пи/6/edit?add=1" title="Создать эту страницу">?&lt;/a>&amp;quot;&amp;quot; радиан на&amp;nbsp;каждую отметку.&lt;br />
&lt;span class="missingpage" title="404: //files?get=cairogtk3.png">file:cairogtk3.png&lt;/span>&lt;/div>&lt;br />
&lt;b>Удалено:&lt;/b>&lt;br />
&lt;div class="deletions">Cairo это&amp;nbsp;мощный двухмерный графический инструментарий, поддерживающий большое число современных графических функций, включая alpha-blending и&amp;nbsp;сглаживание. Он&amp;nbsp;поддерживает множество графических форматов, позволяя разработчикам использовать один и&amp;nbsp;тот же&amp;nbsp;код для&amp;nbsp;отображения графики на&amp;nbsp;экране, печати на&amp;nbsp;принтере и&amp;nbsp;ускорения обработки графики с&amp;nbsp;помощью &lt;span class="missingpage">Open&amp;nbsp;GL&lt;/span>&lt;a href="http://gnome.org.ru/wacko/OpenGL/edit?add=1" title="Создать эту страницу">?&lt;/a>.&lt;br />
Первая часть этой статьи посвящена рассмотрению кода, необходимого при&amp;nbsp;создании виджетов GTK+, использующих Cairo. Во&amp;nbsp;второй части рассказано, как&amp;nbsp;использовать Cairo для&amp;nbsp;того, чтобы выполнять собственно рисование. Если вы&amp;nbsp;хотите просто рисовать внутри существующих виджетов или&amp;nbsp;внутри &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>, вы&amp;nbsp;можете пропустить первую часть и&amp;nbsp;перейти сразу ко&amp;nbsp;второй. Будущие статьи будут посвящены рассмотрению способов реализации сигналов виджета и&amp;nbsp;некоторым другим возможностям Cairo API.&lt;br />
Можно просто начать рисовать, с&amp;nbsp;помощью Cairo внутри площадки для&amp;nbsp;рисования &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>, однако если нужно рисовать много раз&amp;nbsp;одно и&amp;nbsp;тоже, вы&amp;nbsp;наверное захотите создать собственный виджет, который можно будет использовать многократно. Большая часть этой главы будет полезна при&amp;nbsp;создании любых других виджетов, не&amp;nbsp;обязательно использующих для&amp;nbsp;отрисовки графическую библиотеку Cairo.&lt;br />
Как&amp;nbsp;известно GTK+ &amp;ndash; объектно-ориентированная среда, это&amp;nbsp;означает что&amp;nbsp;существует две&amp;nbsp;структуры данных, на&amp;nbsp;которые придется потратить время: класс и&amp;nbsp;его экземпляр. Экземпляр это&amp;nbsp;наиболее привычная нам&amp;nbsp;стрктура данных типа &lt;span class="missingpage">Gtk&amp;nbsp;Widget&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWidget/edit?add=1" title="Создать эту страницу">?&lt;/a>, к&amp;nbsp;которой мы&amp;nbsp;будем постоянно обращаться внутри программы.&lt;br />
Классы наследуют свойства других классов. Так&amp;nbsp;как мы&amp;nbsp;пишем виджет, который будет отрисовываться с&amp;nbsp;помощью Cairo, наиболее удобно будет создать класс основанный на&amp;nbsp;&lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>, который наследует свойства &lt;span class="missingpage">Gtk&amp;nbsp;Widget&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWidget/edit?add=1" title="Создать эту страницу">?&lt;/a>, &lt;span class="missingpage">Gtk&amp;nbsp;Object&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkObject/edit?add=1" title="Создать эту страницу">?&lt;/a> и&amp;nbsp;в конце GObject. Тем&amp;nbsp;более, что&amp;nbsp;в&amp;nbsp;классе &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a> уже&amp;nbsp;реализовано множество функций, которые нужны для&amp;nbsp;нашего виджета, это&amp;nbsp;поможет нам&amp;nbsp;избавится от&amp;nbsp;написания большого количества ненужного кода.&lt;br />
Мы&amp;nbsp;назвали наш&amp;nbsp;класс &lt;span class="missingpage">Egg&amp;nbsp;Clock&amp;nbsp;Face&lt;/span>&lt;a href="http://gnome.org.ru/wacko/EggClockFace/edit?add=1" title="Создать эту страницу">?&lt;/a>, все&amp;nbsp;наши функции будем начинать с&amp;nbsp;префикса egg_clock_face, при&amp;nbsp;этом мы&amp;nbsp;унаследовали класс &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>.&lt;br />
Когда кто-нибудь создает новый экземпляр &lt;span class="missingpage">Egg&amp;nbsp;Clock&amp;nbsp;Face&lt;/span>&lt;a href="http://gnome.org.ru/wacko/EggClockFace/edit?add=1" title="Создать эту страницу">?&lt;/a>, вызывается функция egg_clock_face_init(). Нам&amp;nbsp;не&amp;nbsp;нужно беспокоиться о&amp;nbsp;создании экземпляра &lt;span class="missingpage">Gtk&amp;nbsp;Widget&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWidget/edit?add=1" title="Создать эту страницу">?&lt;/a> или&amp;nbsp;о&amp;nbsp;выделении памяти, все&amp;nbsp;это будет сделано за&amp;nbsp;нас. Не&amp;nbsp;надолго оставим пустой эту&amp;nbsp;функцию:&lt;br />
Пустое GTK&amp;nbsp;окно&lt;br />
Если какой-нибудь элемент GTK+ требует перерисовки, возникает событие перерисовки expose-event. Если вы&amp;nbsp;пропустили шаг&amp;nbsp;1, скажу, что&amp;nbsp;сейчас мы&amp;nbsp;будем писать код&amp;nbsp;обработчика для&amp;nbsp;этого события. Когда возникает событие перерисовки, GTK+ передает для&amp;nbsp;обработки некоторую информацию, включая площадь виджета, которую нужно перерисовать. Вся&amp;nbsp;эта информация передается в&amp;nbsp;структуре &lt;span class="missingpage">Gdk&amp;nbsp;Event&amp;nbsp;Expose&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkEventExpose/edit?add=1" title="Создать эту страницу">?&lt;/a>.&lt;br />
Чтобы начать рисовать с&amp;nbsp;Cairo нам&amp;nbsp;нужно получить контекст Cairo (обычно называемый cairo_t). Мы&amp;nbsp;можем получить cairo_t для&amp;nbsp;&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a> (куда собственно мы&amp;nbsp;будем рисовать). Нужно обратить внимание, что&amp;nbsp;&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a> и&amp;nbsp;&lt;span class="missingpage">Gtk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a> &amp;ndash; разные вещи, все&amp;nbsp;виды виджетов содержат в&amp;nbsp;себе &lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a> для&amp;nbsp;рисования. Нестрашно, если вы&amp;nbsp;сразу не&amp;nbsp;запомните что&amp;nbsp;куда, со&amp;nbsp;временем вы&amp;nbsp;поймете суть.&lt;br />
Получить доступ к&amp;nbsp;&lt;span class="missingpage">Gdk&amp;nbsp;Window&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GdkWindow/edit?add=1" title="Создать эту страницу">?&lt;/a> большинства виджетов (напр. &lt;span class="missingpage">Gtk&amp;nbsp;Drawing&amp;nbsp;Area&lt;/span>&lt;a href="http://gnome.org.ru/wacko/GtkDrawingArea/edit?add=1" title="Создать эту страницу">?&lt;/a>), можно обратившись к&amp;nbsp;свойству window структуры виджета, таким способом widget &amp;ndash; &amp;gt; window. Итак чтобы получить cairo_t в&amp;nbsp;нашем приложении, нужно немного дописать код:&lt;br />
Заготовка для&amp;nbsp;циферблата&lt;br />
Теперь добавим отметку для&amp;nbsp;каждого часа на&amp;nbsp;циферблате. Снова вспомним немного геометрии, нам&amp;nbsp;нужно разделить 2Пи на&amp;nbsp;12 частей, получается &lt;span class="missingpage">Пи&amp;nbsp;/&amp;nbsp;6&lt;/span>&lt;a href="http://gnome.org.ru/wacko/Пи/6/edit?add=1" title="Создать эту страницу">?&lt;/a> радиан на&amp;nbsp;каждую отметку.&lt;br />
Форма циферблата&lt;/div>&lt;/div>
</description>
</item>
<item>
<title>2006-04-09 12:17:11</title>
<link>http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1/show?time=2006-04-09+12%3A17%3A11</link>
<description>&lt;div class="pageBefore">&lt;img src="http://gnome.org.ru/wacko/images/z.gif" width="1" height="1" border="0" alt="" style="display:block" align="top" />&lt;/div>&lt;div class="page">
&lt;b>Сравнение версий &lt;a  href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1" class="">/Разработка&amp;nbsp;/&amp;nbsp;Виджеты&amp;nbsp;Cairo&amp;nbsp;/&amp;nbsp;часть&amp;nbsp;1&lt;/a> за &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A17%3A11">2006-04-09 12:17:11&lt;/a> и &lt;a href="http://gnome.org.ru/wacko/Razrabotka/VidzhetyCairo/chast'1?time=2006-04-09+12%3A18%3A37">2006-04-09 12:18:37&lt;/a>&lt;/b>&lt;br />
&lt;br />
No differences.&lt;/div>
</description>
</item>
</channel>
</rss>
