Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions
cairo-pen.c File Reference
#include "cairoint.h"
#include "cairo-gstate-private.h"

Go to the source code of this file.

Defines

#define PEN_MAX_VERTICES   0xffff

Functions

static int _cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix)
static void _cairo_pen_compute_slopes (cairo_pen_t *pen)
static cairo_status_t _cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon)
cairo_status_t _cairo_pen_init_empty (cairo_pen_t *pen)
cairo_status_t _cairo_pen_init (cairo_pen_t *pen, double radius, cairo_gstate_t *gstate)
void _cairo_pen_fini (cairo_pen_t *pen)
cairo_status_t _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
cairo_status_t _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
cairo_status_t _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active)
cairo_status_t _cairo_pen_find_active_ccw_vertex_index (cairo_pen_t *pen, cairo_slope_t *slope, int *active)
cairo_status_t _cairo_pen_stroke_spline (cairo_pen_t *pen, cairo_spline_t *spline, double tolerance, cairo_traps_t *traps)

Define Documentation

#define PEN_MAX_VERTICES   0xffff

Definition at line 41 of file cairo-pen.c.


Function Documentation

cairo_status_t _cairo_pen_add_points ( cairo_pen_t pen,
cairo_point_t point,
int  num_points 
)

Definition at line 153 of file cairo-pen.c.

{
    cairo_pen_vertex_t *vertices;
    int num_vertices;
    int i;

    if (num_points <= 0 || num_points > PEN_MAX_VERTICES)
       return CAIRO_STATUS_NO_MEMORY;

    if (pen->num_vertices < 0 || pen->num_vertices > PEN_MAX_VERTICES)
       return CAIRO_STATUS_NO_MEMORY;

    num_vertices = pen->num_vertices + num_points;

    if (num_vertices > PEN_MAX_VERTICES)
       return CAIRO_STATUS_NO_MEMORY;

    vertices = realloc (pen->vertices, num_vertices * sizeof (cairo_pen_vertex_t));
    if (vertices == NULL)
       return CAIRO_STATUS_NO_MEMORY;

    pen->vertices = vertices;
    pen->num_vertices = num_vertices;

    /* initialize new vertices */
    for (i=0; i < num_points; i++)
       pen->vertices[pen->num_vertices-num_points+i].point = point[i];

    _cairo_hull_compute (pen->vertices, &pen->num_vertices);

    _cairo_pen_compute_slopes (pen);

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void _cairo_pen_compute_slopes ( cairo_pen_t pen) [static]

Definition at line 306 of file cairo-pen.c.

{
    int i, i_prev;
    cairo_pen_vertex_t *prev, *v, *next;

    for (i=0, i_prev = pen->num_vertices - 1;
        i < pen->num_vertices;
        i_prev = i++) {
       prev = &pen->vertices[i_prev];
       v = &pen->vertices[i];
       next = &pen->vertices[(i + 1) % pen->num_vertices];

       _cairo_slope_init (&v->slope_cw, &prev->point, &v->point);
       _cairo_slope_init (&v->slope_ccw, &v->point, &next->point);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 357 of file cairo-pen.c.

{
    int i;
    cairo_slope_t slope_reverse;

    slope_reverse = *slope;
    slope_reverse.dx = -slope_reverse.dx;
    slope_reverse.dy = -slope_reverse.dy;

    for (i=pen->num_vertices-1; i >= 0; i--) {
       if (_cairo_slope_counter_clockwise (&pen->vertices[i].slope_ccw, &slope_reverse)
           && _cairo_slope_clockwise (&pen->vertices[i].slope_cw, &slope_reverse))
           break;
    }

    *active = i;

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 334 of file cairo-pen.c.

{
    int i;

    for (i=0; i < pen->num_vertices; i++) {
       if (_cairo_slope_clockwise (slope, &pen->vertices[i].slope_ccw)
           && _cairo_slope_counter_clockwise (slope, &pen->vertices[i].slope_cw))
           break;
    }

    *active = i;

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 127 of file cairo-pen.c.

{
    free (pen->vertices);
    pen->vertices = NULL;

    _cairo_pen_init_empty (pen);
}

Here is the call graph for this function:

Here is the caller graph for this function:

cairo_status_t _cairo_pen_init ( cairo_pen_t pen,
double  radius,
cairo_gstate_t *  gstate 
)

Definition at line 64 of file cairo-pen.c.

{
    int i;
    int reflect;
    double  det;

    if (pen->num_vertices) {
       /* XXX: It would be nice to notice that the pen is already properly constructed.
          However, this test would also have to account for possible changes in the transformation
          matrix.
          if (pen->radius == radius && pen->tolerance == tolerance)
          return CAIRO_STATUS_SUCCESS;
       */
       _cairo_pen_fini (pen);
    }

    pen->radius = radius;
    pen->tolerance = gstate->tolerance;

    _cairo_matrix_compute_determinant (&gstate->ctm, &det);
    if (det >= 0) {
       reflect = 0;
    } else {
       reflect = 1;
    }

    pen->num_vertices = _cairo_pen_vertices_needed (gstate->tolerance,
                                              radius,
                                              &gstate->ctm);

    if ((pen->num_vertices <= 0) || (pen->num_vertices > PEN_MAX_VERTICES)) {
       pen->num_vertices = 0;
       return CAIRO_STATUS_NO_MEMORY;
    }

    pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
    if (pen->vertices == NULL) {
       pen->num_vertices = 0;
       return CAIRO_STATUS_NO_MEMORY;
    }

    /*
     * Compute pen coordinates.  To generate the right ellipse, compute points around
     * a circle in user space and transform them to device space.  To get a consistent
     * orientation in device space, flip the pen if the transformation matrix
     * is reflecting
     */
    for (i=0; i < pen->num_vertices; i++) {
       double theta = 2 * M_PI * i / (double) pen->num_vertices;
       double dx = radius * cos (reflect ? -theta : theta);
       double dy = radius * sin (reflect ? -theta : theta);
       cairo_pen_vertex_t *v = &pen->vertices[i];
       cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
       v->point.x = _cairo_fixed_from_double (dx);
       v->point.y = _cairo_fixed_from_double (dy);
    }

    _cairo_pen_compute_slopes (pen);

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 136 of file cairo-pen.c.

{
    *pen = *other;

    if (pen->num_vertices) {
       pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
       if (pen->vertices == NULL) {
           pen->num_vertices = 0;
           return CAIRO_STATUS_NO_MEMORY;
       }
       memcpy (pen->vertices, other->vertices, pen->num_vertices * sizeof (cairo_pen_vertex_t));
    }

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 53 of file cairo-pen.c.

{
    pen->radius = 0;
    pen->tolerance = 0;
    pen->vertices = NULL;
    pen->num_vertices = 0;

    return CAIRO_STATUS_SUCCESS;
}

Here is the caller graph for this function:

cairo_status_t _cairo_pen_stroke_spline ( cairo_pen_t pen,
cairo_spline_t spline,
double  tolerance,
cairo_traps_t traps 
)

Definition at line 444 of file cairo-pen.c.

{
    cairo_status_t status;
    cairo_polygon_t polygon;

    /* If the line width is so small that the pen is reduced to a
       single point, then we have nothing to do. */
    if (pen->num_vertices <= 1)
       return CAIRO_STATUS_SUCCESS;

    _cairo_polygon_init (&polygon);

    status = _cairo_spline_decompose (spline, tolerance);
    if (status)
       return status;

    status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
    if (status)
       return status;

    status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
    if (status)
       return status;

    _cairo_polygon_close (&polygon);
    _cairo_traps_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
    _cairo_polygon_fini (&polygon);
    
    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static cairo_status_t _cairo_pen_stroke_spline_half ( cairo_pen_t pen,
cairo_spline_t spline,
cairo_direction_t  dir,
cairo_polygon_t polygon 
) [static]

Definition at line 380 of file cairo-pen.c.

{
    int i;
    cairo_status_t status;
    int start, stop, step;
    int active = 0;
    cairo_point_t hull_point;
    cairo_slope_t slope, initial_slope, final_slope;
    cairo_point_t *point = spline->points;
    int num_points = spline->num_points;

    if (dir == CAIRO_DIRECTION_FORWARD) {
       start = 0;
       stop = num_points;
       step = 1;
       initial_slope = spline->initial_slope;
       final_slope = spline->final_slope;
    } else {
       start = num_points - 1;
       stop = -1;
       step = -1;
       initial_slope = spline->final_slope;
       initial_slope.dx = -initial_slope.dx;
       initial_slope.dy = -initial_slope.dy;
       final_slope = spline->initial_slope;
       final_slope.dx = -final_slope.dx; 
       final_slope.dy = -final_slope.dy; 
    }

    _cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active);

    i = start;
    while (i != stop) {
       hull_point.x = point[i].x + pen->vertices[active].point.x;
       hull_point.y = point[i].y + pen->vertices[active].point.y;
       status = _cairo_polygon_line_to (polygon, &hull_point);
       if (status)
           return status;

       if (i + step == stop)
           slope = final_slope;
       else
           _cairo_slope_init (&slope, &point[i], &point[i+step]);
       if (_cairo_slope_counter_clockwise (&slope, &pen->vertices[active].slope_ccw)) {
           if (++active == pen->num_vertices)
              active = 0;
       } else if (_cairo_slope_clockwise (&slope, &pen->vertices[active].slope_cw)) {
           if (--active == -1)
              active = pen->num_vertices - 1;
       } else {
           i += step;
       }
    }

    return CAIRO_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int _cairo_pen_vertices_needed ( double  tolerance,
double  radius,
cairo_matrix_t matrix 
) [static]

Definition at line 274 of file cairo-pen.c.

{
    /* 
     * the pen is a circle that gets transformed to an ellipse by matrix.
     * compute major axis length for a pen with the specified radius.
     * we don't need the minor axis length.
     */
    
    double  major_axis = _cairo_matrix_transformed_circle_major_axis(matrix, radius);

    /*
     * compute number of vertices needed
     */
    int           num_vertices;
    
    /* Where tolerance / M is > 1, we use 4 points */
    if (tolerance >= major_axis) {
       num_vertices = 4;
    } else {
       double delta = acos (1 - tolerance / major_axis);
       num_vertices = ceil (M_PI / delta);
       
       /* number of vertices must be even */
       if (num_vertices % 2)
           num_vertices++;
    }
    return num_vertices;
}

Here is the call graph for this function:

Here is the caller graph for this function: