GTK+中文社区(gtk.awaysoft.com)

 找回密码
 马上加入

QQ登录

只需一步,快速开始

查看: 3837|回复: 0

[转]Cairo 图形指南 (10) —— 文本

[复制链接]
  • TA的每日心情
    奋斗
    2021-11-19 13:15
  • 签到天数: 20 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2011-2-3 02:20:24 | 显示全部楼层 |阅读模式
       

    本篇讲述如何处理文本。
    灵魂伙伴
    第一个示例是在 GTK+ 窗口中显示《灵魂伙伴》的部分歌词。
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include <cairo.h>
    #include <gtk/gtk.h>


    static gboolean
    on_expose_event(GtkWidget *widget,
        GdkEventExpose *event,
        gpointer data)
    {
      cairo_t *cr;

      cr = gdk_cairo_create(widget->window);

      cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);

      cairo_select_font_face(cr, &quoturisa",
          CAIRO_FONT_SLANT_NORMAL,
          CAIRO_FONT_WEIGHT_BOLD);

      cairo_set_font_size(cr, 13);

      cairo_move_to(cr, 20, 30);
      cairo_show_text(cr, "Most relationships seem so transitory");  
      cairo_move_to(cr, 20, 60);
      cairo_show_text(cr, "They're all good but not the permanent one");

      cairo_move_to(cr, 20, 120);
      cairo_show_text(cr, "Who doesn't long for someone to hold");

      cairo_move_to(cr, 20, 150);
      cairo_show_text(cr, "Who knows how to love you without being told");
      cairo_move_to(cr, 20, 180);
      cairo_show_text(cr, "Somebody tell me why I'm on my own");
      cairo_move_to(cr, 20, 210);
      cairo_show_text(cr, "If there's a soulmate for everyone");

      cairo_destroy(cr);

      return FALSE;
    }



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

      gtk_init(&argc, &argv);

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      g_signal_connect(window, "expose-event",
          G_CALLBACK(on_expose_event), NULL);
      g_signal_connect(window, "destroy",
          G_CALLBACK(gtk_main_quit), NULL);

      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 420, 250);
      gtk_window_set_title(GTK_WINDOW(window), "Soulmate");
      gtk_widget_set_app_paintable(window, TRUE);

      gtk_widget_show_all(window);

      gtk_main();

      return 0;
    }



    在这个示例中,显示了 Natasha Bedingfield 的《灵魂伙伴》的部分歌词。(在这里,可以听这首歌,很美妙)
    ?
    1
    2
    3
    cairo_select_font_face(cr, &quoturisa",
       CAIRO_FONT_SLANT_NORMAL,
       CAIRO_FONT_WEIGHT_BOLD);



    这里设置字体。这个函数接受了三个字体参数的传入,字体的名称、样式与轻重。
    ?
    1
    cairo_set_font_size(cr, 13);



    这里设定字号。
    ?
    1
    2
    cairo_move_to(cr, 20, 30);
    cairo_show_text(cr, "Most relationships seem so transitory");



    通过在窗口中指定位置并调用 cairo_show_text() 函数显示文本。


    一个字接一个字……
    这种效果就是一个字一个字的显示,这些字的绘制存有时间差。
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    #include <cairo.h>
    #include <gtk/gtk.h>

    gpointer text[7] = { "Z", "e", "t", "C", "o", "d", "e" };
    gboolean timer = TRUE;


    static gboolean
    on_expose_event(GtkWidget *widget,
        GdkEventExpose *event,
        gpointer data)
    {
      cairo_t *cr;
      cairo_text_extents_t extents;
      static gint count = 0;

      cr = gdk_cairo_create(widget->window);

      cairo_select_font_face(cr, "Courier",
          CAIRO_FONT_SLANT_NORMAL,
          CAIRO_FONT_WEIGHT_BOLD);

      cairo_set_font_size(cr, 35);  
      cairo_set_source_rgb(cr, 0.2, 0.2, 0.2);

      gint i;
      gint x = 0;

      for (i = 0; i < count; i++) {
          cairo_text_extents(cr, text, &extents);
          x += extents.width + 2;
          cairo_move_to(cr, x + 30, 50);
          cairo_show_text(cr, text);  
      }

      count++;

      if (count == 8) {
          timer = FALSE;
          count = 0;
      }

      cairo_destroy(cr);

      return FALSE;
    }

    static gboolean
    time_handler (GtkWidget *widget)
    {
      if (widget->window == NULL) return FALSE;

      if (!timer) return FALSE;

      gtk_widget_queue_draw(widget);
      return TRUE;
    }


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

      gtk_init(&argc, &argv);

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      g_signal_connect(window, "expose-event",
          G_CALLBACK(on_expose_event), NULL);
      g_signal_connect(window, "destroy",
          G_CALLBACK(gtk_main_quit), NULL);

      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 300, 90);
      gtk_window_set_title(GTK_WINDOW(window), "ZetCode");
      gtk_widget_set_app_paintable(window, TRUE);

      g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window);

      gtk_widget_show_all(window);


      gtk_main();

      return 0;
    }



    在这个示例中,我们在 GTK+ 窗口中画了“ZetCode”这个字串,并让逐个字母伴随一定的时间差逐一显示。
    ?
    1
    gpointer text[7] = { "Z", "e", "t", "C", "o", "d", "e" };



    构造一个字符数组。
    ?
    1
    2
    3
    cairo_select_font_face(cr, "Courier",
       CAIRO_FONT_SLANT_NORMAL,
       CAIRO_FONT_WEIGHT_BOLD);



    将字体设置为 Courier。
    ?
    1
    2
    3
    4
    5
    6
    for (i = 0; i < count; i++) {
       cairo_text_extents(cr, text, &extents);
       x += extents.width + 2;
       cairo_move_to(cr, x + 30, 50);
       cairo_show_text(cr, text);  
    }



    开始逐个字的绘制。extents.width 给出了当前字符的宽度。


    膨胀
    下面这个示例中,我们制造了一种膨胀的效果。这个示例显示了一串在膨胀的居中文本,并且伴有淡出现象。这是很常见的效果,在 flash 动画里经常见到。
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #include <cairo.h>
    #include <gtk/gtk.h>


    gpointer text[7] = { "Z", "e", "t", "C", "o", "d", "e" };
    gboolean timer = TRUE;


    static gboolean
    on_expose_event(GtkWidget *widget,
        GdkEventExpose *event,
        gpointer data)
    {
      cairo_t *cr;
      cairo_text_extents_t extents;

      static gdouble alpha = 1.0;
      static gdouble size = 1;


      gint x = widget->allocation.width / 2;
      gint y = widget->allocation.height / 2;

      cr = gdk_cairo_create(widget->window);

      cairo_set_source_rgb(cr, 0.5, 0, 0);
      cairo_paint(cr);

      cairo_select_font_face(cr, "Courier",
          CAIRO_FONT_SLANT_NORMAL,
          CAIRO_FONT_WEIGHT_BOLD);

      size += 0.8;

      if (size > 20) {
          alpha -= 0.01;
      }

      cairo_set_font_size(cr, size);

      cairo_set_source_rgb(cr, 1, 1, 1);

      cairo_text_extents(cr, "ZetCode", &extents);
      cairo_move_to(cr, x - extents.width/2, y);
      cairo_text_path(cr, "ZetCode");
      cairo_clip(cr);
      cairo_stroke(cr);
      cairo_paint_with_alpha(cr, alpha);

      if (alpha <= 0) {
          timer = FALSE;
      }

      cairo_destroy(cr);

      return FALSE;
    }

    static gboolean
    time_handler (GtkWidget *widget)
    {
      if (widget->window == NULL) return FALSE;

      if (!timer) return FALSE;

      gtk_widget_queue_draw(widget);

      return TRUE;
    }


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

      gtk_init(&argc, &argv);

      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      g_signal_connect(window, "expose-event",
          G_CALLBACK(on_expose_event), NULL);
      g_signal_connect(window, "destroy",
          G_CALLBACK(gtk_main_quit), NULL);

      gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
      gtk_window_set_default_size(GTK_WINDOW(window), 350, 200);
      gtk_window_set_title(GTK_WINDOW(window), "puff");
      gtk_widget_set_app_paintable(window, TRUE);

      g_timeout_add(14, (GSourceFunc) time_handler, (gpointer) window);

      gtk_widget_show_all(window);

      gtk_main();

      return 0;
    }



    这个示例在 GTK+ 窗口中制造了一种膨胀并且淡出的文本渲染效果。
    ?
    1
    2
    gint x = widget->allocation.width / 2;
    gint y = widget->allocation.height / 2;



    获取窗口中心坐标。
    ?
    1
    2
    cairo_set_source_rgb(cr, 0.5, 0, 0);
    cairo_paint(cr);



    将背景设为暗红色。
    ?
    1
    size += 0.8;



    每轮循环,字号都增长 0.8 个单位。
    ?
    1
    2
    3
    if (size > 20) {
        alpha -= 0.01;
    }



    当字号大于 20 的时候,就开始淡出。
    ?
    1
    cairo_text_extents(cr, "ZetCode", &extents);



    获取文本尺寸。
    ?
    1
    cairo_move_to(cr, x - extents.width/2, y);



    根据文本尺寸来将文本定位在窗口的中心位置。
    ?
    1
    2
    cairo_text_path(cr, "ZetCode");
    cairo_clip(cr);



    获取文本的的路径,并将其设为当前的裁剪域。
    ?
    1
    2
    cairo_stroke(cr);
    cairo_paint_with_alpha(cr, alpha);



    绘制当前的路径,并为之添加 alpha 值(可实现淡出效果)。

    原文地址:http://liyanrui.is-programmer.com/2010/4/7/cairo-text.16643.html


      
    *滑块验证:
    您需要登录后才可以回帖 登录 | 马上加入

    本版积分规则

    申请友链|Archiver|小黑屋|手机版|GTK+中文社区 ( 粤ICP备13080851号 )

    我要啦免费统计

    GMT+8, 2024-3-29 15:17 , Processed in 0.275185 second(s), 7 queries , Redis On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表