关闭

The Cairo graphics tutorial -------Text in Cairo

174人阅读 评论(0) 收藏 举报

In this part of the Cairo graphics tutorial, we will work with text.


Soulmate

In the first example, we will display some lyrics on the GTK+ window.

#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, "Purisa",
      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;
}

In this example, we display part of the lyrics from the Natasha Bedingfields Soulmate song.

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

Here we select the font face. The function takes three parameters, the font family, font slant and the font weight.

 cairo_set_font_size(cr, 13);

Here we specify the font size.

 cairo_move_to(cr, 20, 30);
 cairo_show_text(cr, "Most relationships seem so transitory"); 

We display the text on the window by specifying the position of the text and calling the cairo_show_text() function.


Soulmate
Figure: Soulmate

Letter by letter

In this effect, we will display a text letter by letter. The letters will be drawn with some delay.

#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[i], &extents);
      x += extents.width + 2;
      cairo_move_to(cr, x + 30, 50);
      cairo_show_text(cr, text[i]);  
  }

  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;
}

In our example, we will draw the "ZetCode" string onto the GTK+ window letter by letter with some delay.

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

We create an array of strings.

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

We select a Courier font face.

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

Here we draw the text letter by letter. The extents.width gives us the width of the current letter.


ZetCode
Figure: ZetCode

Puff

In the following example, we create a puff effect. The example will display a growing centered text, that will gradully fade out from some point. This is a very common effect, which you can often see in flash animations.

#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;
}

The example creates a growing and fading text on the GTK+ window.

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

Coordinates of the middle point.

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

We set the background color to dark red color.

 size += 0.8;

Each cycle, the font size will grow by 0.8 units.

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

The fading out begins after the font size is bigger than 20.

 cairo_text_extents(cr, "ZetCode", &extents);

We get the text metrics.

 cairo_move_to(cr, x - extents.width/2, y);

We use the text metrics to center the text on the window.

 cairo_text_path(cr, "ZetCode");
 cairo_clip(cr);

We get the path of the text and set the current clip region to it.

 cairo_stroke(cr);
 cairo_paint_with_alpha(cr, alpha);

We paint the current path with and take alpha value into account.


Puff
Figure: Puff

This chapter covered text in Cairo.



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:19605次
    • 积分:281
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:42篇
    • 译文:0篇
    • 评论:0条
    文章分类