⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairotwisted.c

📁 Pango is a library for layout and rendering of text, with an emphasis on internationalization. Pang
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Example code to show how to use pangocairo to render text * projected on a path. * * * Written by Behdad Esfahbod, 2006..2007 * * Permission to use, copy, modify, distribute, and sell this example * for any purpose is hereby granted without fee. * It is provided "as is" without express or implied warranty. */#include <math.h>#include <stdlib.h>#include <pango/pangocairo.h>void fancy_cairo_stroke (cairo_t *cr);void fancy_cairo_stroke_preserve (cairo_t *cr);/* A fancy cairo_stroke[_preserve]() that draws points and control * points, and connects them together. */static void_fancy_cairo_stroke (cairo_t *cr, cairo_bool_t preserve){  int i;  double line_width;  cairo_path_t *path;  cairo_path_data_t *data;  const double dash[] = {10, 10};  cairo_save (cr);  cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);  line_width = cairo_get_line_width (cr);  path = cairo_copy_path (cr);  cairo_new_path (cr);  cairo_save (cr);  cairo_set_line_width (cr, line_width / 3);  cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0);  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    switch (data->header.type) {    case CAIRO_PATH_MOVE_TO:    case CAIRO_PATH_LINE_TO:	cairo_move_to (cr, data[1].point.x, data[1].point.y);	break;    case CAIRO_PATH_CURVE_TO:	cairo_line_to (cr, data[1].point.x, data[1].point.y);	cairo_move_to (cr, data[2].point.x, data[2].point.y);	cairo_line_to (cr, data[3].point.x, data[3].point.y);	break;    case CAIRO_PATH_CLOSE_PATH:	break;    default:	g_assert_not_reached ();    }  }  cairo_stroke (cr);  cairo_restore (cr);  cairo_save (cr);  cairo_set_line_width (cr, line_width * 4);  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    switch (data->header.type) {    case CAIRO_PATH_MOVE_TO:	cairo_move_to (cr, data[1].point.x, data[1].point.y);	break;    case CAIRO_PATH_LINE_TO:	cairo_rel_line_to (cr, 0, 0);	cairo_move_to (cr, data[1].point.x, data[1].point.y);	break;    case CAIRO_PATH_CURVE_TO:	cairo_rel_line_to (cr, 0, 0);	cairo_move_to (cr, data[1].point.x, data[1].point.y);	cairo_rel_line_to (cr, 0, 0);	cairo_move_to (cr, data[2].point.x, data[2].point.y);	cairo_rel_line_to (cr, 0, 0);	cairo_move_to (cr, data[3].point.x, data[3].point.y);	break;    case CAIRO_PATH_CLOSE_PATH:	cairo_rel_line_to (cr, 0, 0);	break;    default:	g_assert_not_reached ();    }  }  cairo_rel_line_to (cr, 0, 0);  cairo_stroke (cr);  cairo_restore (cr);  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    switch (data->header.type) {    case CAIRO_PATH_MOVE_TO:	cairo_move_to (cr, data[1].point.x, data[1].point.y);	break;    case CAIRO_PATH_LINE_TO:	cairo_line_to (cr, data[1].point.x, data[1].point.y);	break;    case CAIRO_PATH_CURVE_TO:	cairo_curve_to (cr, data[1].point.x, data[1].point.y,			    data[2].point.x, data[2].point.y,			    data[3].point.x, data[3].point.y);	break;    case CAIRO_PATH_CLOSE_PATH:	cairo_close_path (cr);	break;    default:	g_assert_not_reached ();    }  }  cairo_stroke (cr);  if (preserve)    cairo_append_path (cr, path);  cairo_path_destroy (path);  cairo_restore (cr);}/* A fancy cairo_stroke() that draws points and control points, and * connects them together. */voidfancy_cairo_stroke (cairo_t *cr){  _fancy_cairo_stroke (cr, FALSE);}/* A fancy cairo_stroke_preserve() that draws points and control * points, and connects them together. */voidfancy_cairo_stroke_preserve (cairo_t *cr){  _fancy_cairo_stroke (cr, TRUE);}/* Returns Euclidean distance between two points */static doubletwo_points_distance (cairo_path_data_t *a, cairo_path_data_t *b){  double dx, dy;  dx = b->point.x - a->point.x;  dy = b->point.y - a->point.y;  return sqrt (dx * dx + dy * dy);}/* Returns length of a Bezier curve. * Seems like computing that analytically is not easy.  The * code just flattens the curve using cairo and adds the length * of segments. */static doublecurve_length (double x0, double y0,	      double x1, double y1,	      double x2, double y2,	      double x3, double y3){  cairo_surface_t *surface;  cairo_t *cr;  cairo_path_t *path;  cairo_path_data_t *data, current_point;  int i;  double length;  surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 0, 0);  cr = cairo_create (surface);  cairo_surface_destroy (surface);  cairo_move_to (cr, x0, y0);  cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);  length = 0;  path = cairo_copy_path_flat (cr);  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    switch (data->header.type) {    case CAIRO_PATH_MOVE_TO:	current_point = data[1];	break;    case CAIRO_PATH_LINE_TO:	length += two_points_distance (&current_point, &data[1]);	current_point = data[1];	break;    default:    case CAIRO_PATH_CURVE_TO:    case CAIRO_PATH_CLOSE_PATH:	g_assert_not_reached ();    }  }  cairo_path_destroy (path);  cairo_destroy (cr);  return length;}typedef double parametrization_t;/* Compute parametrization info.  That is, for each part of the  * cairo path, tags it with its length. */static parametrization_t *parametrize_path (cairo_path_t *path){  int i;  cairo_path_data_t *data, current_point;  parametrization_t *parametrization;  parametrization = malloc (path->num_data * sizeof (parametrization[0]));  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    parametrization[i] = 0.0;    switch (data->header.type) {    case CAIRO_PATH_MOVE_TO:	current_point = data[1];	break;    case CAIRO_PATH_LINE_TO:	parametrization[i] = two_points_distance (&current_point, &data[1]);	current_point = data[1];	break;    case CAIRO_PATH_CURVE_TO:	/* naive curve-length, treating bezier as three line segments:	parametrization[i] = two_points_distance (&current_point, &data[1])			   + two_points_distance (&data[1], &data[2])			   + two_points_distance (&data[2], &data[3]);	*/	parametrization[i] = curve_length (current_point.point.x, current_point.point.x,					   data[1].point.x, data[1].point.y,					   data[2].point.x, data[2].point.y,					   data[3].point.x, data[3].point.y);	current_point = data[3];	break;    case CAIRO_PATH_CLOSE_PATH:	break;    default:	g_assert_not_reached ();    }  }  return parametrization;}typedef void (*transform_point_func_t) (void *closure, double *x, double *y);/* Project a path using a function.  Each point of the path (including * Bezier control points) is passed to the function for transformation. */static voidtransform_path (cairo_path_t *path, transform_point_func_t f, void *closure){  int i;  cairo_path_data_t *data;  for (i=0; i < path->num_data; i += path->data[i].header.length) {    data = &path->data[i];    switch (data->header.type) {    case CAIRO_PATH_CURVE_TO:      f (closure, &data[3].point.x, &data[3].point.y);      f (closure, &data[2].point.x, &data[2].point.y);    case CAIRO_PATH_MOVE_TO:    case CAIRO_PATH_LINE_TO:      f (closure, &data[1].point.x, &data[1].point.y);      break;    case CAIRO_PATH_CLOSE_PATH:      break;    default:	g_assert_not_reached ();    }  }}/* Simple struct to hold a path and its parametrization */typedef struct {  cairo_path_t *path;  parametrization_t *parametrization;} parametrized_path_t;/* Project a point X,Y onto a parameterized path.  The final point is * where you get if you walk on the path forward from the beginning for X * units, then stop there and walk another Y units perpendicular to the * path at that point.  In more detail: * * There's three pieces of math involved: * *   - The parametric form of the Line equation *     http://en.wikipedia.org/wiki/Line * *   - The parametric form of the Cubic Bézier curve equation

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -