Cairo FAQ Transparency

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: In this part of the Cairo C API tutorial, we will talk about transparency. We will provide some basic definitions and two interesting transparency effects. Transparency is the quality o...)
(Удалено по требованию автора...)
 
Строка 1: Строка 1:
-
In this part of the Cairo C API tutorial, we will talk about transparency. We will provide some basic definitions and two interesting transparency effects.
 
-
Transparency is the quality of being able to see through a material.
 
-
The easiest way to understand transparency is to imagine a piece of glass or water. Technically, the rays of light can go through the glass and this way we can see objects behind the glass.
 
-
 
-
In computer graphics, we can achieve transparency effects using <b>alpha compositing</b>.
 
-
Alpha compositing is the process of combining an image with a background to create the appearance of partial transparency.
 
-
 
-
The composition process uses an <b>alpha channel</b>.
 
-
Alpha channel is an 8-bit layer in a graphics file format that is used for expressing translucency (transparency). The extra eight bits per pixel serves as a mask and represents 256 levels of translucency.
 
-
<br>(answers.com, wikipedia.org)
 
-
 
-
== Transparent rectangles ==
 
-
 
-
The first example will draw ten rectangles with different levels of transparency.
 
-
 
-
<source lang="cpp">
 
-
#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);
 
-
 
-
  gint i;
 
-
  for ( i = 1; i <= 10; i++) {
 
-
      cairo_set_source_rgba(cr, 0, 0, 1, i*0.1);
 
-
      cairo_rectangle(cr, 50*i, 20, 40, 40);
 
-
      cairo_fill(cr); 
 
-
  }
 
-
 
-
 
-
  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(G_OBJECT(window), "expose-event",
 
-
      G_CALLBACK(on_expose_event), NULL);
 
-
  g_signal_connect(G_OBJECT(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), 590, 90);
 
-
  gtk_window_set_title(GTK_WINDOW(window), "transparency");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
The <b>cairo_set_source_rgba()</b> has an optional alpha parameter to provide transparency.
 
-
 
-
<source lang="cpp">
 
-
gint i;
 
-
for ( i = 1; i <= 10; i++) {
 
-
    cairo_set_source_rgba(cr, 0, 0, 1, i*0.1);
 
-
    cairo_rectangle(cr, 50*i, 20, 40, 40);
 
-
    cairo_fill(cr); 
 
-
}
 
-
</source>
 
-
 
-
This code creates ten rectangles with alpha values from 0.1 ... 1.
 
-
 
-
[[image: cairo_faq_transparency.png | center]]
 
-
 
-
== Fade out effect ==
 
-
 
-
In the next example, we will fade out an image. The image will gradually get more transparent until it is completely invisible.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
 
-
#include <gtk/gtk.h>
 
-
 
-
 
-
cairo_surface_t *image;
 
-
gboolean timer = TRUE;
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  static double alpha = 1;
 
-
  double const delta = 0.01;
 
-
 
-
  cairo_set_source_surface(cr, image, 10, 10);
 
-
  cairo_paint_with_alpha(cr, alpha);
 
-
 
-
  alpha -= delta;
 
-
 
-
  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;
 
-
  GtkWidget *darea;
 
-
 
-
  gint width, height;
 
-
 
-
  image = cairo_image_surface_create_from_png("turnacastle.png");
 
-
  width = cairo_image_surface_get_width(image);
 
-
  height = cairo_image_surface_get_height(image);
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  darea = gtk_drawing_area_new();
 
-
  gtk_container_add(GTK_CONTAINER (window), darea);
 
-
 
-
  g_signal_connect(darea, "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), width+20, height+20);
 
-
 
-
  gtk_window_set_title(GTK_WINDOW(window), "fade out");
 
-
  g_timeout_add(50, (GSourceFunc) time_handler, (gpointer) window);
 
-
  gtk_widget_show_all(window);
 
-
 
-
  gtk_main();
 
-
 
-
  cairo_surface_destroy(image);
 
-
 
-
  return 0;
 
-
}
 
-
</source>
 
-
 
-
In our example we display an image that will gradually fade out. We use a photo of ruins of a Turna Castle, located in east part of Slovakia.
 
-
 
-
<source lang="cpp">
 
-
image = cairo_image_surface_create_from_png("turnacastle.png");
 
-
</source>
 
-
 
-
For efficiency reasons, the creation of the image surface is placed inside the main function.
 
-
 
-
<source lang="cpp">
 
-
cairo_set_source_surface(cr, image, 10, 10);
 
-
</source>
 
-
 
-
Here we set the source for painting.
 
-
 
-
<source lang="cpp">
 
-
cairo_paint_with_alpha(cr, alpha);
 
-
</source>
 
-
 
-
The fade out effect is created using the <b>cairo_paint_with_alpha()</b> function call. This function uses transparency value as a mask.
 
-
 
-
<source lang="cpp">
 
-
alpha -= delta;
 
-
</source>
 
-
 
-
We decrease the alpha value each time, the <b>on_expose_event()</b> function is executed.
 
-
 
-
<source lang="cpp">
 
-
if (alpha <= 0) timer = FALSE;
 
-
</source>
 
-
 
-
If the alpha value is less or equal to zero, we finished our fade out effect. We set the timer value to FALSE. We do not need our timer function anymore.
 
-
 
-
<source lang="cpp">
 
-
g_timeout_add(50, (GSourceFunc) time_handler, (gpointer) window);
 
-
</source>
 
-
 
-
We create a timer function. This function will call <b>time_handler</b> every 50 ms.
 
-
 
-
<source lang="cpp">
 
-
static gboolean
 
-
time_handler (GtkWidget *widget)
 
-
{
 
-
  if (widget->window == NULL) return FALSE;
 
-
 
-
  if (!timer) return FALSE;
 
-
 
-
  gtk_widget_queue_draw(widget);
 
-
  return TRUE;
 
-
}
 
-
 
-
</source>
 
-
 
-
The main function of the <b>time_handler</b> call is to redraw the window regularly.
 
-
When the function returns FALSE, the timeout function will cease to work.
 
-
 
-
<source lang="cpp">
 
-
if (widget->window == NULL) return FALSE;
 
-
</source>
 
-
 
-
You might wonder, what this code line is there for. It is a simple check. If the timeout value is too small, like 5 ms, it happens that while closing the application, the window is already destroyed but still we get the timeout function executed.
 
-
This code line prevents from manipulating with a window in such cases.
 
-
 
-
[[image: cairo_faq_fadeout.png | center]]
 
-
 
-
== Waiting demo ==
 
-
 
-
In this examle, we use transparency effect to create a waiting demo. We will draw 8 lines that will gradually  fade out creating an illusion, that a line is moving. Such effects are often used to inform users, that a  lengthy task is going on behind the scenes. An example is streaming video over the internet.
 
-
 
-
<source lang="cpp">
 
-
#include <cairo.h>
 
-
 
-
#include <gtk/gtk.h>
 
-
#include <math.h>
 
-
 
-
static gushort count = 0;
 
-
 
-
static gboolean
 
-
on_expose_event(GtkWidget *widget,
 
-
    GdkEventExpose *event,
 
-
    gpointer data)
 
-
{
 
-
  cairo_t *cr;
 
-
 
-
  cr = gdk_cairo_create(widget->window);
 
-
 
-
  static gdouble const trs[8][8] = {
 
-
      { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
 
-
      { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
 
-
      { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
 
-
      { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
 
-
      { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
 
-
      { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
 
-
      { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
 
-
      { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
 
-
  };
 
-
 
-
 
-
  gint width, height;
 
-
  gtk_window_get_size(GTK_WINDOW(widget), &width, &height);
 
-
 
-
  cairo_translate(cr, width / 2, height /2);
 
-
 
-
  gint i = 0;
 
-
  for (i = 0; i < 8; i++) {
 
-
      cairo_set_line_width(cr, 3);
 
-
      cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
 
-
      cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);
 
-
 
-
      cairo_move_to(cr, 0.0, -10.0);
 
-
      cairo_line_to(cr, 0.0, -40.0);
 
-
      cairo_rotate(cr, M_PI/4);
 
-
 
-
      cairo_stroke(cr);
 
-
  }
 
-
 
-
  cairo_destroy(cr);
 
-
 
-
  return FALSE;
 
-
}
 
-
 
-
static gboolean
 
-
time_handler (GtkWidget *widget)
 
-
{
 
-
  count += 1;
 
-
  gtk_widget_queue_draw(widget);
 
-
  return TRUE;
 
-
}
 
-
 
-
int main(int argc, char *argv[])
 
-
{
 
-
  GtkWidget *window;
 
-
  GtkWidget *darea; 
 
-
 
-
  gtk_init(&argc, &argv);
 
-
 
-
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
-
 
-
  g_signal_connect(G_OBJECT(window), "expose-event",
 
-
      G_CALLBACK(on_expose_event), NULL);
 
-
  g_signal_connect(G_OBJECT(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), 250, 150);
 
-
 
-
  gtk_window_set_title(GTK_WINDOW(window), "waiting demo");
 
-
 
-
  gtk_widget_set_app_paintable(window, TRUE);
 
-
  gtk_widget_show_all(window);
 
-
  g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);
 
-
 
-
  gtk_main();
 
-
 
-
  return 0;
 
-
}
 
-
 
-
</source>
 
-
 
-
We draw eight lines with eight different alpha values.
 
-
 
-
<source lang="cpp">
 
-
static gdouble const trs[8][8] = {
 
-
    { 0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0 },
 
-
    { 1.0, 0.0,  0.15, 0.30, 0.5, 0.65, 0.8, 0.9 },
 
-
    { 0.9, 1.0,  0.0,  0.15, 0.3, 0.5, 0.65, 0.8 },
 
-
    { 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5, 0.65},
 
-
    { 0.65, 0.8, 0.9,  1.0,  0.0,  0.15, 0.3, 0.5 },
 
-
    { 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15, 0.3 },
 
-
    { 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0,  0.15 },
 
-
    { 0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0,  0.0, }
 
-
};
 
-
</source>
 
-
 
-
This is a two dimensional array of transparency values used in this demo. There are 8 rows, each for one  state. Each of the 8 lines will continuosly use these values.
 
-
 
-
<source lang="cpp">
 
-
cairo_set_line_width(cr, 3);
 
-
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
 
-
</source>
 
-
 
-
We make the lines a bit thicker, so that they are better visible. We draw the lines with rouded caps.
 
-
 
-
<source lang="cpp">
 
-
cairo_set_source_rgba(cr, 0, 0, 0, trs[count%8][i]);
 
-
</source>
 
-
 
-
Here we define the transparency value for a line.
 
-
 
-
<source lang="cpp">
 
-
cairo_move_to(cr, 0.0, -10.0);
 
-
cairo_line_to(cr, 0.0, -40.0);
 
-
cairo_rotate(cr, M_PI/4);
 
-
</source>
 
-
 
-
These code will draw each of the eight lines.
 
-
 
-
<source lang="cpp">
 
-
g_timeout_add(100, (GSourceFunc) time_handler, (gpointer) window);
 
-
</source>
 
-
 
-
We use a timer function to create animation.
 
-
 
-
[[image: cairo_faq_waitingdemo.gif | center]]
 
-
 
-
 
-
[[Категория:GTK+]]
 
-
[[Категория:Cairo]]
 

Текущая версия на 11:30, 7 апреля 2009