Added some documentation, so we get some churn here.

New functions: cairo_copy_path_data, cairo_copy_path_data_flat, and cairo_append_path_data.
Add new implementation for cairo_copy_path_data and cairo_append_path_data.
New test for new path_data functions.
This commit is contained in:
Carl Worth 2005-03-11 14:29:15 +00:00
parent db616356c1
commit a98430092f
14 changed files with 1210 additions and 8 deletions

View file

@ -1,3 +1,22 @@
2005-03-11 Carl Worth <cworth@cworth.org>
* doc/public/cairo-sections.txt:
* doc/public/tmpl/cairo-surface.sgml:
* doc/public/tmpl/cairo.sgml: Added some documentation, so we get
some churn here.
* src/cairo.c:
* src/cairo.h: New functions: cairo_copy_path_data,
cairo_copy_path_data_flat, and cairo_append_path_data.
* src/Makefile.am:
* src/cairo-path-data-private.h:
* src/cairo_path_data.c: Add new implementation for
cairo_copy_path_data and cairo_append_path_data.
* test/Makefile.am:
* test/path_data.c: New test for new path_data functions.
2005-03-10 Kristian Høgsberg <krh@redhat.com>
* src/cairo_surface.c (_destroy_user_data): Add this function and

View file

@ -86,6 +86,8 @@ cairo_surface_set_matrix
cairo_surface_get_matrix
cairo_surface_set_filter
cairo_surface_get_filter
cairo_surface_set_user_data
cairo_surface_get_user_data
</SECTION>
<SECTION>
@ -225,12 +227,17 @@ cairo_get_matrix
cairo_get_target_surface
cairo_get_path
cairo_get_path_flat
cairo_copy_path_data
cairo_copy_path_data_flat
cairo_append_path_data
cairo_status_t
cairo_status
cairo_status_string
cairo_filter_t
cairo_image_surface_create
cairo_image_surface_create_for_data
cairo_destroy_func_t
cairo_user_data_key_t
<SUBSECTION Private>
CAIRO_API_SHAKEUP_FLAG_DAY
CAIRO_BEGIN_DECLS
@ -247,6 +254,10 @@ cairo_current_line_join
cairo_current_miter_limit
cairo_current_matrix
cairo_current_target_surface
cairo_current_path
cairo_current_path_flat
cairo_current_font
cairo_current_font_extents
cairo_get_status
cairo_get_status_string
</SECTION>

View file

@ -113,3 +113,25 @@ cairo_surface_t
@Returns:
<!-- ##### FUNCTION cairo_surface_set_user_data ##### -->
<para>
</para>
@surface:
@key:
@data:
@destroy:
@Returns:
<!-- ##### FUNCTION cairo_surface_get_user_data ##### -->
<para>
</para>
@surface:
@key:
@Returns:

View file

@ -953,6 +953,33 @@ Drawing contexts.
@closure:
<!-- ##### FUNCTION cairo_copy_path_data ##### -->
<para>
</para>
@cr:
@Returns:
<!-- ##### FUNCTION cairo_copy_path_data_flat ##### -->
<para>
</para>
@cr:
@Returns:
<!-- ##### FUNCTION cairo_append_path_data ##### -->
<para>
</para>
@cr:
@path_data:
<!-- ##### ENUM cairo_status_t ##### -->
<para>
@ -967,6 +994,7 @@ Drawing contexts.
@CAIRO_STATUS_NO_TARGET_SURFACE:
@CAIRO_STATUS_NULL_POINTER:
@CAIRO_STATUS_INVALID_STRING:
@CAIRO_STATUS_INVALID_PATH_DATA:
<!-- ##### FUNCTION cairo_status ##### -->
<para>
@ -1031,3 +1059,18 @@ End:
-->
<!-- ##### USER_FUNCTION cairo_destroy_func_t ##### -->
<para>
</para>
@data:
<!-- ##### STRUCT cairo_user_data_key_t ##### -->
<para>
</para>
@unused:

View file

@ -91,6 +91,8 @@ libcairo_la_SOURCES = \
cairo_matrix.c \
cairo_path.c \
cairo_path_bounds.c \
cairo_path_data.c \
cairo-path-data-private.h \
cairo_path_fill.c \
cairo_path_stroke.c \
cairo_pen.c \

View file

@ -0,0 +1,57 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@redhat.com>
*/
#ifndef CAIRO_PATH_DATA_PRIVATE_H
#define CAIRO_PATH_DATA_PRIVATE_H
#include "cairoint.h"
extern cairo_path_data_t _cairo_path_data_nil;
CAIRO_BEGIN_DECLS
cairo_path_data_t *
_cairo_path_data_create (cairo_gstate_t *gstate);
cairo_path_data_t *
_cairo_path_data_create_flat (cairo_gstate_t *gstate);
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_data_t *path_data,
cairo_t *cr);
CAIRO_END_DECLS
#endif /* CAIRO_PATH_DATA_PRIVATE_H */

268
src/cairo-path-data.c Normal file
View file

@ -0,0 +1,268 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@redhat.com>
*/
#include "cairo-path-data-private.h"
cairo_path_data_t
_cairo_path_data_nil = { {0} };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
int count;
} cpdc_t;
static void
_cpdc_move_to (void *closure, double x, double y)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
}
static void
_cpdc_line_to (void *closure, double x, double y)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
}
static void
_cpdc_curve_to (void *closure,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cpdc_t *cpdc = closure;
cpdc->count += 4;
}
static void
_cpdc_close_path (void *closure)
{
cpdc_t *cpdc = closure;
cpdc->count += 1;
}
static int
_cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten)
{
cpdc_t cpdc;
cpdc.count = 0;
_cairo_gstate_interpret_path (gstate,
_cpdc_move_to,
_cpdc_line_to,
flatten ? NULL : _cpdc_curve_to,
_cpdc_close_path,
&cpdc);
/* Add 1 for the final CAIRO_PATH_END */
cpdc.count++;
return cpdc.count;
}
/* Closure for path interpretation. */
typedef struct cairo_path_data_populate {
cairo_path_data_t *data;
} cpdp_t;
static void
_cpdp_move_to (void *closure, double x, double y)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_MOVE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
}
static void
_cpdp_line_to (void *closure, double x, double y)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_LINE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
}
static void
_cpdp_curve_to (void *closure,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_CURVE_TO;
data->header.length = 4;
/* We index from 1 to leave room for data->header */
data[1].point.x = x1;
data[1].point.y = y1;
data[2].point.x = x2;
data[2].point.y = y2;
data[3].point.x = x3;
data[3].point.y = y3;
cpdp->data += data->header.length;
}
static void
_cpdp_close_path (void *closure)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_CLOSE_PATH;
data->header.length = 1;
cpdp->data += data->header.length;
}
static void
_cairo_path_data_populate (cairo_path_data_t *data,
int count,
cairo_gstate_t *gstate,
cairo_bool_t flatten)
{
cpdp_t cpdp;
cpdp.data = data;
_cairo_gstate_interpret_path (gstate,
_cpdp_move_to,
_cpdp_line_to,
flatten ? NULL : _cpdp_curve_to,
_cpdp_close_path,
&cpdp);
cpdp.data->header.type = CAIRO_PATH_END;
cpdp.data->header.length = 0;
cpdp.data++;
/* Sanity check the count */
assert (cpdp.data - data == count);
}
static cairo_path_data_t *
_cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
{
int count;
cairo_path_data_t *data;
count = _cairo_path_data_count (gstate, flatten);
data = malloc (count * sizeof (cairo_path_data_t));
if (data == NULL)
return &_cairo_path_data_nil;
_cairo_path_data_populate (data, count, gstate, flatten);
return data;
}
cairo_path_data_t *
_cairo_path_data_create (cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (gstate, FALSE);
}
cairo_path_data_t *
_cairo_path_data_create_flat (cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (gstate, TRUE);
}
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_data_t *path_data,
cairo_t *cr)
{
cairo_path_data_t *p;
for (p = path_data; p->header.type != CAIRO_PATH_END; p += p->header.length) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
cairo_move_to (cr,
p[1].point.x, p[1].point.y);
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_LINE_TO:
cairo_line_to (cr,
p[1].point.x, p[1].point.y);
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_CURVE_TO:
cairo_curve_to (cr,
p[1].point.x, p[1].point.y,
p[2].point.x, p[2].point.y,
p[3].point.x, p[3].point.y);
if (p->header.length != 4)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
if (p->header.length != 1)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
default:
return CAIRO_STATUS_INVALID_PATH_DATA;
}
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -34,8 +34,8 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include "cairo-path-data-private.h"
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
@ -56,6 +56,8 @@ cairo_sane_state (cairo_t *cr)
case CAIRO_STATUS_INVALID_MATRIX:
case CAIRO_STATUS_NO_TARGET_SURFACE:
case CAIRO_STATUS_NULL_POINTER:
case CAIRO_STATUS_INVALID_STRING:
case CAIRO_STATUS_INVALID_PATH_DATA:
break;
default:
return 0;
@ -1705,6 +1707,88 @@ cairo_get_path_flat (cairo_t *cr,
}
DEPRECATE (cairo_current_path_flat, cairo_get_path_flat);
/**
* cairo_copy_path_data:
* @cr: a cairo context
*
* Creates a copy of the current path and returns it to the user as an
* array of #cairo_path_data_t. See #cairo_path_data_t for hints on
* how to iterate over the returned data structure.
*
* Return value: the copy of the current path. The caller is
* responsible for the returned memory and should free() it when
* finished.
**/
cairo_path_data_t *
cairo_copy_path_data (cairo_t *cr)
{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return &_cairo_path_data_nil;
return _cairo_path_data_create (cr->gstate);
}
/**
* cairo_copy_path_data_flat:
* @cr: a cairo context
*
* Gets a flattened copy of the current path and returns it to the
* user an an array of #cairo_path_data_t. See #cairo_path_data_t for hints on
* how to iterate over the returned data structure.
*
* This function is like cairo_copy_path_data() except that any curves
* in the path will be approximated with piecewise-linear
* approximations, (accurate to within the current tolerance
* value). That is, the result is guaranteed to not have any elements
* of type CAIRO_PATH_CURVE_TO which will instead be replaced by a
* series of CAIRO_PATH_LINE_TO elements.
*
* Return value: the copy of the current path. The caller is
* responsible for the returned memory and should free() it when
* finished.
**/
cairo_path_data_t *
cairo_copy_path_data_flat (cairo_t *cr)
{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return &_cairo_path_data_nil;
return _cairo_path_data_create_flat (cr->gstate);
}
/**
* cairo_append_path_data:
* @cr: a cairo context
* @path_data: path data to be appended
*
* Append the @path_data onto the current path. See #cairo_path_data_t
* for details on how the path data array must be initialized.
**/
void
cairo_append_path_data (cairo_t *cr,
cairo_path_data_t *path_data)
{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
if (!path_data) {
cr->status = CAIRO_STATUS_NULL_POINTER;
return;
}
if (path_data == &_cairo_path_data_nil) {
cr->status = CAIRO_STATUS_NO_MEMORY;
return;
}
cr->status = _cairo_path_data_append_to_context (path_data, cr);
CAIRO_CHECK_SANITY (cr);
}
cairo_status_t
cairo_status (cairo_t *cr)
{
@ -1735,6 +1819,8 @@ cairo_status_string (cairo_t *cr)
return "NULL pointer";
case CAIRO_STATUS_INVALID_STRING:
return "input string not valid UTF-8";
case CAIRO_STATUS_INVALID_PATH_DATA:
return "input path data not valid";
}
return "<unknown error status>";

View file

@ -55,7 +55,7 @@ CAIRO_BEGIN_DECLS
*
* #cairo_bool_t is used for boolean values. Returns of type
* #cairo_bool_t will always be either 0 or 1, but testing against
* these values explicitely is not encouraged; just use the
* these values explicitly is not encouraged; just use the
* value as a boolean condition.
*
* <informalexample><programlisting>
@ -106,7 +106,8 @@ typedef enum cairo_status {
CAIRO_STATUS_INVALID_MATRIX,
CAIRO_STATUS_NO_TARGET_SURFACE,
CAIRO_STATUS_NULL_POINTER,
CAIRO_STATUS_INVALID_STRING
CAIRO_STATUS_INVALID_STRING,
CAIRO_STATUS_INVALID_PATH_DATA
} cairo_status_t;
/* Functions for manipulating state objects */
@ -145,7 +146,7 @@ cairo_set_target_surface (cairo_t *cr, cairo_surface_t *surface);
* cairo_format_t
* @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with
* alpha in the upper 8 bits, then red, then green, then blue.
* The 32-bit quanties are stored native-endian. Pre-multiplied
* The 32-bit quantities are stored native-endian. Pre-multiplied
* alpha is used. (That is, 50% transparent red is 0x80800000,
* not 0x80ff0000.)
* @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with
@ -664,7 +665,7 @@ cairo_get_miter_limit (cairo_t *cr);
void
cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
/* XXX: Need to decide the memory mangement semantics of this
/* XXX: Need to decide the memory management semantics of this
function. Should it reference the surface again? */
cairo_surface_t *
cairo_get_target_surface (cairo_t *cr);
@ -682,7 +683,7 @@ typedef void (cairo_curve_to_func_t) (void *closure,
typedef void (cairo_close_path_func_t) (void *closure);
extern void
void
cairo_get_path (cairo_t *cr,
cairo_move_to_func_t *move_to,
cairo_line_to_func_t *line_to,
@ -690,13 +691,98 @@ cairo_get_path (cairo_t *cr,
cairo_close_path_func_t *close_path,
void *closure);
extern void
void
cairo_get_path_flat (cairo_t *cr,
cairo_move_to_func_t *move_to,
cairo_line_to_func_t *line_to,
cairo_close_path_func_t *close_path,
void *closure);
/**
* cairo_path_data_t:
*
* A data structure for holding path data. This data structure is used
* as the return value for cairo_copy_path_data() and
* cairo_copy_path_data_flat() as well the input value for
* cairo_append_path_data().
*
* The data structure is designed to try to balance the demands of
* efficiency and ease-of-use. A path is represented as an array of
* cairo_path_data_t which is a union of headers and points. The array
* must be terminated by a header element of type CAIRO_PATH_END_PATH.
*
* Each portion of the path is represented by one or more elements in
* the array, (one header followed by 0 or more points). The length
* value of the header is the number of array elements for the current
* portion including the header, (ie. length == 1 + # of points), and
* where the number of points for each element type must be as
* follows:
*
* CAIRO_PATH_MOVE_TO: 1 point
* CAIRO_PATH_LINE_TO: 1 point
* CAIRO_PATH_CURVE_TO: 3 points
* CAIRO_PATH_CLOSE_PATH: 0 points
*
* The semantics and ordering of the coordinate values are consistent
* with cairo_move_to(), cairo_line_to(), cairo_curve_to(), and
* cairo_close_path().
*
* Here is sample code for iterating through a cairo_path_data_t
* array:
*
* <informalexample><programlisting>
* cairo_path_data_t *path, *p;
*
* path = cairo_copy_path_data (cr);
*
* for (p = path; p->header.type != CAIRO_PATH_END; p += p->header.length) {
* switch (p->header.type) {
* case CAIRO_PATH_MOVE_TO:
* do_move_to_things (p[1].point.x, p[1].point.y);
* break;
* case CAIRO_PATH_LINE_TO:
* do_line_to_things (p[1].point.x, p[1].point.y);
* break;
* case CAIRO_PATH_CURVE_TO:
* do_curve_to_things (p[1].point.x, p[1].point.y,
* p[2].point.x, p[2].point.y,
* p[3].point.x, p[3].point.y);
* break;
* case CAIRO_PATH_CLOSE_PATH:
* do_close_path_things ();
* break;
* }
* }
*
* free (path);
* </programlisting></informalexample>
*/
typedef union {
struct {
enum {
CAIRO_PATH_MOVE_TO,
CAIRO_PATH_LINE_TO,
CAIRO_PATH_CURVE_TO,
CAIRO_PATH_CLOSE_PATH,
CAIRO_PATH_END
} type;
int length;
} header;
struct {
double x, y;
} point;
} cairo_path_data_t;
cairo_path_data_t *
cairo_copy_path_data (cairo_t *cr);
cairo_path_data_t *
cairo_copy_path_data_flat (cairo_t *cr);
void
cairo_append_path_data (cairo_t *cr,
cairo_path_data_t *path_data);
/* Error status queries */
cairo_status_t
@ -921,7 +1007,7 @@ cairo_matrix_transform_point (cairo_matrix_t *matrix, double *x, double *y);
#define cairo_current_rgb_color cairo_current_rgb_color_DEPRECATED_BY_cairo_get_rgb_color
#define cairo_current_alpha cairo_current_alpha_DEPRECATED_BY_cairo_get_alpha
#define cairo_current_tolerance cairo_current_tolerance_DEPRECATED_BY_cairo_get_tolerance
#define cairo_current_point cairo_current_point_DEPRECTATED_BY_cairo_get_current_point
#define cairo_current_point cairo_current_point_DEPRECATED_BY_cairo_get_current_point
#define cairo_current_fill_rule cairo_current_fill_rule_DEPRECATED_BY_cairo_get_fill_rule
#define cairo_current_line_width cairo_current_line_width_DEPRECATED_BY_cairo_get_line_width
#define cairo_current_line_cap cairo_current_line_cap_DEPRECATED_BY_cairo_get_line_cap

268
src/cairo_path_data.c Normal file
View file

@ -0,0 +1,268 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@redhat.com>
*/
#include "cairo-path-data-private.h"
cairo_path_data_t
_cairo_path_data_nil = { {0} };
/* Closure for path interpretation. */
typedef struct cairo_path_data_count {
int count;
} cpdc_t;
static void
_cpdc_move_to (void *closure, double x, double y)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
}
static void
_cpdc_line_to (void *closure, double x, double y)
{
cpdc_t *cpdc = closure;
cpdc->count += 2;
}
static void
_cpdc_curve_to (void *closure,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cpdc_t *cpdc = closure;
cpdc->count += 4;
}
static void
_cpdc_close_path (void *closure)
{
cpdc_t *cpdc = closure;
cpdc->count += 1;
}
static int
_cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten)
{
cpdc_t cpdc;
cpdc.count = 0;
_cairo_gstate_interpret_path (gstate,
_cpdc_move_to,
_cpdc_line_to,
flatten ? NULL : _cpdc_curve_to,
_cpdc_close_path,
&cpdc);
/* Add 1 for the final CAIRO_PATH_END */
cpdc.count++;
return cpdc.count;
}
/* Closure for path interpretation. */
typedef struct cairo_path_data_populate {
cairo_path_data_t *data;
} cpdp_t;
static void
_cpdp_move_to (void *closure, double x, double y)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_MOVE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
}
static void
_cpdp_line_to (void *closure, double x, double y)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_LINE_TO;
data->header.length = 2;
/* We index from 1 to leave room for data->header */
data[1].point.x = x;
data[1].point.y = y;
cpdp->data += data->header.length;
}
static void
_cpdp_curve_to (void *closure,
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_CURVE_TO;
data->header.length = 4;
/* We index from 1 to leave room for data->header */
data[1].point.x = x1;
data[1].point.y = y1;
data[2].point.x = x2;
data[2].point.y = y2;
data[3].point.x = x3;
data[3].point.y = y3;
cpdp->data += data->header.length;
}
static void
_cpdp_close_path (void *closure)
{
cpdp_t *cpdp = closure;
cairo_path_data_t *data = cpdp->data;
data->header.type = CAIRO_PATH_CLOSE_PATH;
data->header.length = 1;
cpdp->data += data->header.length;
}
static void
_cairo_path_data_populate (cairo_path_data_t *data,
int count,
cairo_gstate_t *gstate,
cairo_bool_t flatten)
{
cpdp_t cpdp;
cpdp.data = data;
_cairo_gstate_interpret_path (gstate,
_cpdp_move_to,
_cpdp_line_to,
flatten ? NULL : _cpdp_curve_to,
_cpdp_close_path,
&cpdp);
cpdp.data->header.type = CAIRO_PATH_END;
cpdp.data->header.length = 0;
cpdp.data++;
/* Sanity check the count */
assert (cpdp.data - data == count);
}
static cairo_path_data_t *
_cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
{
int count;
cairo_path_data_t *data;
count = _cairo_path_data_count (gstate, flatten);
data = malloc (count * sizeof (cairo_path_data_t));
if (data == NULL)
return &_cairo_path_data_nil;
_cairo_path_data_populate (data, count, gstate, flatten);
return data;
}
cairo_path_data_t *
_cairo_path_data_create (cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (gstate, FALSE);
}
cairo_path_data_t *
_cairo_path_data_create_flat (cairo_gstate_t *gstate)
{
return _cairo_path_data_create_real (gstate, TRUE);
}
cairo_status_t
_cairo_path_data_append_to_context (cairo_path_data_t *path_data,
cairo_t *cr)
{
cairo_path_data_t *p;
for (p = path_data; p->header.type != CAIRO_PATH_END; p += p->header.length) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
cairo_move_to (cr,
p[1].point.x, p[1].point.y);
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_LINE_TO:
cairo_line_to (cr,
p[1].point.x, p[1].point.y);
if (p->header.length != 2)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_CURVE_TO:
cairo_curve_to (cr,
p[1].point.x, p[1].point.y,
p[2].point.x, p[2].point.y,
p[3].point.x, p[3].point.y);
if (p->header.length != 4)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
if (p->header.length != 1)
return CAIRO_STATUS_INVALID_PATH_DATA;
break;
default:
return CAIRO_STATUS_INVALID_PATH_DATA;
}
}
return CAIRO_STATUS_SUCCESS;
}

View file

@ -5,10 +5,13 @@ Makefile.in
clip_twice
coverage
fill_rule
get_and_set
imagediff
leaky_polygon
line_width
linear_gradient
move_to_show_surface
path_data
pixman_rotate
text_cache_crash
text_rotate

View file

@ -8,6 +8,7 @@ leaky_polygon \
line_width \
linear_gradient \
move_to_show_surface \
path_data \
pixman_rotate \
text_cache_crash \
text_rotate \
@ -24,6 +25,7 @@ linear_gradient-ref.png \
move_to_show_surface-ref.png \
coverage-ref.png \
clip_twice-ref.png \
path_data-ref.png \
pixman_rotate-ref.png \
romedalen.png
@ -76,6 +78,7 @@ leaky_polygon_SOURCES = leaky_polygon.c $(cairo_test_lib)
line_width_SOURCES = line_width.c $(cairo_test_lib)
linear_gradient_SOURCES = linear_gradient.c $(cairo_test_lib)
move_to_show_surface_SOURCES = move_to_show_surface.c $(cairo_test_lib)
path_data_SOURCES = path_data.c $(cairo_test_lib)
pixman_rotate_SOURCES = pixman_rotate.c $(cairo_test_lib)
text_cache_crash_SOURCES = text_cache_crash.c $(cairo_test_lib)
text_rotate_SOURCES = text_rotate.c $(cairo_test_lib)

167
test/path-data.c Normal file
View file

@ -0,0 +1,167 @@
/*
* Copyright © 2005 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairo_test.h"
cairo_test_t test = {
"path_data",
"Tests calls to path_data functions: cairo_copy_path_data, cairo_copy_path_data_flat, and cairo_append_path_data",
45, 53
};
static void
scale_by_two (double *x, double *y)
{
*x = *x * 2.0;
*y = *y * 2.0;
}
typedef void (*munge_func_t) (double *x, double *y);
static void
munge_and_set_path (cairo_t *cr,
cairo_path_data_t *path,
munge_func_t munge)
{
cairo_path_data_t *p;
double x1, y1, x2, y2, x3, y3;
p = path;
while (1) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
(munge) (&x1, &y1);
cairo_move_to (cr, x1, y1);
break;
case CAIRO_PATH_LINE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
(munge) (&x1, &y1);
cairo_line_to (cr, x1, y1);
break;
case CAIRO_PATH_CURVE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
x2 = p[2].point.x; y2 = p[2].point.y;
x3 = p[3].point.x; y3 = p[3].point.y;
(munge) (&x1, &y1);
(munge) (&x2, &y2);
(munge) (&x3, &y3);
cairo_curve_to (cr,
x1, y1,
x2, y2,
x3, y3);
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
break;
case CAIRO_PATH_END:
return;
}
p += p->header.length;
}
}
static void
make_path (cairo_t *cr)
{
cairo_rectangle (cr, 0, 0, 5, 5);
cairo_move_to (cr, 15, 2.5);
cairo_arc (cr, 12.5, 2.5, 2.5, 0, 2 * M_PI);
}
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_path_data_t *path;
/* copy path, munge, and fill */
cairo_translate (cr, 5, 5);
make_path (cr);
path = cairo_copy_path_data (cr);
cairo_new_path (cr);
munge_and_set_path (cr, path, scale_by_two);
free (path);
cairo_fill (cr);
/* copy flattened path, munge, and fill */
cairo_translate (cr, 0, 15);
make_path (cr);
path = cairo_copy_path_data_flat (cr);
cairo_new_path (cr);
munge_and_set_path (cr, path, scale_by_two);
free (path);
cairo_fill (cr);
/* append two copies of path, and fill */
cairo_translate (cr, 0, 15);
cairo_scale (cr, 2.0, 2.0);
make_path (cr);
path = cairo_copy_path_data (cr);
cairo_new_path (cr);
cairo_append_path_data (cr, path);
cairo_translate (cr, 2.5, 2.5);
cairo_append_path_data (cr, path);
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_fill (cr);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
cairo_t *cr;
cairo_path_data_t bogus_path_data;
/* Test a couple error conditions for cairo_append_path_data */
cr = cairo_create ();
cairo_append_path_data (cr, NULL);
if (cairo_status (cr) != CAIRO_STATUS_NULL_POINTER)
return 1;
cairo_destroy (cr);
cr = cairo_create ();
bogus_path_data.header.type = CAIRO_PATH_MOVE_TO;
bogus_path_data.header.length = 1;
cairo_append_path_data (cr, &bogus_path_data);
if (cairo_status (cr) != CAIRO_STATUS_INVALID_PATH_DATA)
return 1;
cairo_destroy (cr);
/* And test the degnerate case */
cr = cairo_create ();
bogus_path_data.header.type = CAIRO_PATH_END;
cairo_append_path_data (cr, &bogus_path_data);
if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
return 1;
cairo_destroy (cr);
return cairo_test (&test, draw);
}

167
test/path_data.c Normal file
View file

@ -0,0 +1,167 @@
/*
* Copyright © 2005 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairo_test.h"
cairo_test_t test = {
"path_data",
"Tests calls to path_data functions: cairo_copy_path_data, cairo_copy_path_data_flat, and cairo_append_path_data",
45, 53
};
static void
scale_by_two (double *x, double *y)
{
*x = *x * 2.0;
*y = *y * 2.0;
}
typedef void (*munge_func_t) (double *x, double *y);
static void
munge_and_set_path (cairo_t *cr,
cairo_path_data_t *path,
munge_func_t munge)
{
cairo_path_data_t *p;
double x1, y1, x2, y2, x3, y3;
p = path;
while (1) {
switch (p->header.type) {
case CAIRO_PATH_MOVE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
(munge) (&x1, &y1);
cairo_move_to (cr, x1, y1);
break;
case CAIRO_PATH_LINE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
(munge) (&x1, &y1);
cairo_line_to (cr, x1, y1);
break;
case CAIRO_PATH_CURVE_TO:
x1 = p[1].point.x; y1 = p[1].point.y;
x2 = p[2].point.x; y2 = p[2].point.y;
x3 = p[3].point.x; y3 = p[3].point.y;
(munge) (&x1, &y1);
(munge) (&x2, &y2);
(munge) (&x3, &y3);
cairo_curve_to (cr,
x1, y1,
x2, y2,
x3, y3);
break;
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
break;
case CAIRO_PATH_END:
return;
}
p += p->header.length;
}
}
static void
make_path (cairo_t *cr)
{
cairo_rectangle (cr, 0, 0, 5, 5);
cairo_move_to (cr, 15, 2.5);
cairo_arc (cr, 12.5, 2.5, 2.5, 0, 2 * M_PI);
}
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_path_data_t *path;
/* copy path, munge, and fill */
cairo_translate (cr, 5, 5);
make_path (cr);
path = cairo_copy_path_data (cr);
cairo_new_path (cr);
munge_and_set_path (cr, path, scale_by_two);
free (path);
cairo_fill (cr);
/* copy flattened path, munge, and fill */
cairo_translate (cr, 0, 15);
make_path (cr);
path = cairo_copy_path_data_flat (cr);
cairo_new_path (cr);
munge_and_set_path (cr, path, scale_by_two);
free (path);
cairo_fill (cr);
/* append two copies of path, and fill */
cairo_translate (cr, 0, 15);
cairo_scale (cr, 2.0, 2.0);
make_path (cr);
path = cairo_copy_path_data (cr);
cairo_new_path (cr);
cairo_append_path_data (cr, path);
cairo_translate (cr, 2.5, 2.5);
cairo_append_path_data (cr, path);
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_fill (cr);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
cairo_t *cr;
cairo_path_data_t bogus_path_data;
/* Test a couple error conditions for cairo_append_path_data */
cr = cairo_create ();
cairo_append_path_data (cr, NULL);
if (cairo_status (cr) != CAIRO_STATUS_NULL_POINTER)
return 1;
cairo_destroy (cr);
cr = cairo_create ();
bogus_path_data.header.type = CAIRO_PATH_MOVE_TO;
bogus_path_data.header.length = 1;
cairo_append_path_data (cr, &bogus_path_data);
if (cairo_status (cr) != CAIRO_STATUS_INVALID_PATH_DATA)
return 1;
cairo_destroy (cr);
/* And test the degnerate case */
cr = cairo_create ();
bogus_path_data.header.type = CAIRO_PATH_END;
cairo_append_path_data (cr, &bogus_path_data);
if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
return 1;
cairo_destroy (cr);
return cairo_test (&test, draw);
}