Merge in origin/master, (a few changes in parallel to 1.6.2 release)

This commit is contained in:
Carl Worth 2008-04-11 10:08:14 -07:00
commit 75001079c1
19 changed files with 279 additions and 41 deletions

View file

@ -68,16 +68,22 @@
#include <ctype.h>
#include <assert.h>
cairo_content_t
cairo_boilerplate_content (cairo_content_t content)
{
if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
content = CAIRO_CONTENT_COLOR_ALPHA;
return content;
}
const char *
cairo_boilerplate_content_name (cairo_content_t content)
{
/* For the purpose of the content name, we don't distinguish the
* flattened content value.
*/
if (content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
content = CAIRO_CONTENT_COLOR_ALPHA;
switch (content) {
switch (cairo_boilerplate_content (content)) {
case CAIRO_CONTENT_COLOR:
return "rgb24";
case CAIRO_CONTENT_COLOR_ALPHA:

View file

@ -95,6 +95,9 @@
* PDF surfaces. */
#define CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED ((unsigned int) -1)
cairo_content_t
cairo_boilerplate_content (cairo_content_t content);
const char *
cairo_boilerplate_content_name (cairo_content_t content);

158
doc/tutorial/src/singular.c Normal file
View file

@ -0,0 +1,158 @@
/**
* Uses Singular values of transformation matrix to find the length of the
* major and minor axes of the scaled pen.
*
* Put this file in cairo/doc/tutorial/src and type "make"
*/
#define WIDTH 300
#define HEIGHT 300
#include "cairo-tutorial.h"
#include <math.h>
/*
* Finds the singular values of the non-translation part of matrix.
*
* Let M be the cairo transformation matrix in question:
*
* xx xy
* M = |yx yy|
* x0 y0
*
* The non-translation part is:
*
* A = xx xy
* yx yy
*
* The non-zero singular values of A are the square roots of the non-zero
* eigenvalues of A A, where A is A-transpose.
*
* A A = xx yxxx xy = xx²+yx² xx*xy+yx*yy
* xy yyyx yy xx*xy+yx*yy xy²+yy²
*
* Name those:
*
* B = A A = a k
* k b
*
* The eigenvalues of B satisfy:
*
* λ² - (a+b).λ + a.b - k² = 0
*
* The eigenvalues are:
* __________________
* (a+b) ± (a+b)² - 4(a.b-k²)
* λ = ---------------------------
* 2
* that simplifies to:
* _______________
* λ = (a+b)/2 ± ((a-b)/2)² + k²
*
* And the Singular values are the root of λs.
*
*/
static void
get_singular_values (const cairo_matrix_t *matrix,
double *major,
double *minor)
{
double xx = matrix->xx, xy = matrix->xy;
double yx = matrix->yx, yy = matrix->yy;
double a = xx*xx+yx*yx;
double b = xy*xy+yy*yy;
double k = xx*xy+yx*yy;
double f = (a+b) * .5;
double g = (a-b) * .5;
double delta = sqrt (g + k*k);
*major = sqrt (f + delta);
*minor = sqrt (f - delta);
}
/*
* Finds the length of the major and minor axes of the pen for a cairo_t,
* identified by the current transformation matrix and line width.
*
* Returned values are in device units.
*/
static void
get_pen_axes (cairo_t *cr,
double *major,
double *minor)
{
double width;
cairo_matrix_t matrix;
width = cairo_get_line_width (cr);
cairo_get_matrix (cr, &matrix);
get_singular_values (&matrix, major, minor);
*major *= width;
*minor *= width;
}
static void
draw (cairo_t *cr, int width, int height)
{
double major_width, minor_width;
/* clear background */
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
cairo_paint (cr);
#define W width
#define H height
#define B ((width+height)/16)
/* the spline we want to stroke */
cairo_move_to (cr, W-B, B);
cairo_curve_to (cr, -W, B,
2*W, H-B,
B, H-B);
/* the effect is show better with round caps */
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
/* set the skewed pen */
cairo_rotate (cr, +.7);
cairo_scale (cr, .5, 2.);
cairo_rotate (cr, -.7);
cairo_set_line_width (cr, B);
get_pen_axes (cr, &major_width, &minor_width);
/* stroke with "major" pen in translucent red */
cairo_save (cr);
cairo_identity_matrix (cr);
cairo_set_line_width (cr, major_width);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, .9);
cairo_stroke_preserve (cr);
cairo_restore (cr);
/* stroke with skewed pen in translucent black */
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, .9);
cairo_stroke_preserve (cr);
/* stroke with "minor" pen in translucent yellow */
cairo_save (cr);
cairo_identity_matrix (cr);
cairo_set_line_width (cr, minor_width);
cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, .9);
cairo_stroke_preserve (cr);
cairo_restore (cr);
/* stroke with hairline in black */
cairo_save (cr);
cairo_identity_matrix (cr);
cairo_set_line_width (cr, 1);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_stroke_preserve (cr);
cairo_restore (cr);
cairo_new_path (cr);
}

View file

@ -176,7 +176,8 @@ cairo_perf_run (cairo_perf_t *perf,
/* We run one iteration in advance to warm caches, etc. */
cairo_perf_yield ();
if (similar)
cairo_push_group_with_content (perf->cr, perf->target->content);
cairo_push_group_with_content (perf->cr,
cairo_boilerplate_content (perf->target->content));
(perf_func) (perf->cr, perf->size, perf->size);
if (similar)
cairo_pattern_destroy (cairo_pop_group (perf->cr));
@ -185,7 +186,8 @@ cairo_perf_run (cairo_perf_t *perf,
for (i =0; i < perf->iterations; i++) {
cairo_perf_yield ();
if (similar)
cairo_push_group_with_content (perf->cr, perf->target->content);
cairo_push_group_with_content (perf->cr,
cairo_boilerplate_content (perf->target->content));
times[i] = (perf_func) (perf->cr, perf->size, perf->size);
if (similar)
cairo_pattern_destroy (cairo_pop_group (perf->cr));

View file

@ -181,6 +181,9 @@ _cairo_arc_in_direction (cairo_t *cr,
double angle_max,
cairo_direction_t dir)
{
if (cairo_status (cr))
return;
while (angle_max - angle_min > 4 * M_PI)
angle_max -= 2 * M_PI;

View file

@ -95,7 +95,6 @@ cairo_font_options_create (void)
return options;
}
slim_hidden_def (cairo_font_options_create);
/**
* cairo_font_options_copy:
@ -144,7 +143,6 @@ cairo_font_options_destroy (cairo_font_options_t *options)
free (options);
}
slim_hidden_def (cairo_font_options_destroy);
/**
* cairo_font_options_status:

View file

@ -713,6 +713,10 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
(Note that the minor axis length is at the minimum of the above solution,
which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
For another derivation of the same result, using Singular Value Decomposition,
see doc/tutorial/src/singular.c.
*/
/* determine the length of the major axis of a circle of the given radius

View file

@ -351,6 +351,12 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
{
struct png_write_closure_t png_closure;
if (surface->status)
return surface->status;
if (surface->finished)
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
png_closure.write_func = write_func;
png_closure.closure = closure;

View file

@ -2120,19 +2120,16 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (_cairo_surface_has_device_transform (surface) &&
! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
{
cairo_font_options_t *font_options;
cairo_font_options_t font_options;
cairo_matrix_t dev_ctm;
font_options = cairo_font_options_create ();
cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
cairo_scaled_font_get_font_options (scaled_font, font_options);
cairo_scaled_font_get_font_options (scaled_font, &font_options);
dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
&font_matrix,
&dev_ctm,
font_options);
cairo_font_options_destroy (font_options);
&font_options);
}
status = cairo_scaled_font_status (dev_scaled_font);
if (status) {

View file

@ -254,6 +254,7 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
{
cairo_xlib_visual_info_t **visuals;
int i;
CAIRO_MUTEX_LOCK (info->mutex);
@ -263,6 +264,12 @@ _cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
info->gc[i] = NULL;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
_cairo_array_truncate (&info->visuals, 0);
CAIRO_MUTEX_UNLOCK (info->mutex);
}
@ -271,8 +278,6 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
{
cairo_xlib_screen_info_t **prev;
cairo_xlib_screen_info_t *list;
cairo_xlib_visual_info_t **visuals;
int i;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
@ -286,9 +291,6 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
break;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
_cairo_xlib_screen_info_close_display (info);
@ -438,11 +440,12 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
Visual *visual,
cairo_xlib_visual_info_t **out)
{
Display *dpy = info->display->display;
cairo_xlib_visual_info_t **visuals, *ret = NULL;
cairo_status_t status;
int i, n_visuals;
CAIRO_MUTEX_LOCK (info->display->mutex);
CAIRO_MUTEX_LOCK (info->mutex);
visuals = _cairo_array_index (&info->visuals, 0);
n_visuals = _cairo_array_num_elements (&info->visuals);
for (i = 0; i < n_visuals; i++) {
@ -451,28 +454,28 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
break;
}
}
CAIRO_MUTEX_UNLOCK (info->display->mutex);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (ret != NULL) {
*out = ret;
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_xlib_visual_info_create (info->display->display,
status = _cairo_xlib_visual_info_create (dpy,
XScreenNumberOfScreen (info->screen),
visual->visualid,
&ret);
if (status)
return status;
CAIRO_MUTEX_LOCK (info->display->mutex);
CAIRO_MUTEX_LOCK (info->mutex);
if (n_visuals != _cairo_array_num_elements (&info->visuals)) {
/* check that another thread has not added our visual */
int new_visuals = _cairo_array_num_elements (&info->visuals);
visuals = _cairo_array_index (&info->visuals, 0);
for (i = n_visuals; i < new_visuals; i++) {
if (visuals[i]->visualid == visual->visualid) {
_cairo_xlib_visual_info_destroy (info->display->display, ret);
_cairo_xlib_visual_info_destroy (dpy, ret);
ret = visuals[i];
break;
}
@ -481,10 +484,10 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
status = _cairo_array_append (&info->visuals, &ret);
} else
status = _cairo_array_append (&info->visuals, &ret);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (status) {
_cairo_xlib_visual_info_destroy (info->display->display, ret);
_cairo_xlib_visual_info_destroy (dpy, ret);
return status;
}

View file

@ -3258,7 +3258,7 @@ cairo_operator_t
cairo_get_operator (cairo_t *cr)
{
if (cr->status)
return (cairo_operator_t) 0;
return CAIRO_GSTATE_OPERATOR_DEFAULT;
return _cairo_gstate_get_operator (cr->gstate);
}
@ -3275,7 +3275,7 @@ double
cairo_get_tolerance (cairo_t *cr)
{
if (cr->status)
return 0.;
return CAIRO_GSTATE_TOLERANCE_DEFAULT;
return _cairo_gstate_get_tolerance (cr->gstate);
}
@ -3293,7 +3293,7 @@ cairo_antialias_t
cairo_get_antialias (cairo_t *cr)
{
if (cr->status)
return (cairo_antialias_t) 0;
return CAIRO_ANTIALIAS_DEFAULT;
return _cairo_gstate_get_antialias (cr->gstate);
}
@ -3386,7 +3386,7 @@ cairo_fill_rule_t
cairo_get_fill_rule (cairo_t *cr)
{
if (cr->status)
return (cairo_fill_rule_t) 0;
return CAIRO_GSTATE_FILL_RULE_DEFAULT;
return _cairo_gstate_get_fill_rule (cr->gstate);
}
@ -3406,7 +3406,7 @@ double
cairo_get_line_width (cairo_t *cr)
{
if (cr->status)
return 0.;
return CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
return _cairo_gstate_get_line_width (cr->gstate);
}
@ -3423,7 +3423,7 @@ cairo_line_cap_t
cairo_get_line_cap (cairo_t *cr)
{
if (cr->status)
return (cairo_line_cap_t) 0;
return CAIRO_GSTATE_LINE_CAP_DEFAULT;
return _cairo_gstate_get_line_cap (cr->gstate);
}
@ -3440,7 +3440,7 @@ cairo_line_join_t
cairo_get_line_join (cairo_t *cr)
{
if (cr->status)
return (cairo_line_join_t) 0;
return CAIRO_GSTATE_LINE_JOIN_DEFAULT;
return _cairo_gstate_get_line_join (cr->gstate);
}
@ -3457,7 +3457,7 @@ double
cairo_get_miter_limit (cairo_t *cr)
{
if (cr->status)
return 0.;
return CAIRO_GSTATE_MITER_LIMIT_DEFAULT;
return _cairo_gstate_get_miter_limit (cr->gstate);
}

View file

@ -2258,8 +2258,6 @@ slim_hidden_proto (cairo_destroy);
slim_hidden_proto (cairo_fill_preserve);
slim_hidden_proto (cairo_font_face_destroy);
slim_hidden_proto_no_warn (cairo_font_face_reference);
slim_hidden_proto (cairo_font_options_create);
slim_hidden_proto (cairo_font_options_destroy);
slim_hidden_proto (cairo_font_options_equal);
slim_hidden_proto (cairo_font_options_hash);
slim_hidden_proto (cairo_font_options_merge);

1
test/.gitignore vendored
View file

@ -84,6 +84,7 @@ glitz-surface-source
glyph-cache-pressure
gradient-alpha
gradient-zero-stops
group-paint
imagediff
image-surface-source
infinite-join

View file

@ -64,6 +64,7 @@ get-group-target$(EXEEXT) \
get-path-extents$(EXEEXT) \
gradient-alpha$(EXEEXT) \
gradient-zero-stops$(EXEEXT) \
group-paint$(EXEEXT) \
image-surface-source$(EXEEXT) \
infinite-join$(EXEEXT) \
in-fill-empty-trapezoid$(EXEEXT) \
@ -425,6 +426,7 @@ REFERENCE_IMAGES = \
gradient-alpha-rgb24-ref.png \
gradient-zero-stops-ref.png \
gradient-zero-stops-rgb24-ref.png \
group-paint-ref.png \
image-surface-source-ref.png \
infinite-join-ref.png \
infinite-join-ps-ref.png \

View file

@ -242,7 +242,7 @@ cairo_test_target_has_similar (const cairo_test_t *test, cairo_boilerplate_targe
if (surface != NULL) {
cairo_t * cr = cairo_create (surface);
cairo_surface_t *similar;
cairo_push_group_with_content (cr, target->content);
cairo_push_group_with_content (cr, cairo_boilerplate_content (target->content));
similar = cairo_get_group_target (cr);
has_similar = cairo_surface_get_type (similar) == cairo_surface_get_type (surface);
@ -342,9 +342,7 @@ cairo_test_for_target (cairo_test_t *test,
* (ignore the articifical
* CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value).
*/
expected_content = target->content;
if (expected_content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
expected_content = CAIRO_CONTENT_COLOR_ALPHA;
expected_content = cairo_boilerplate_content (target->content);
if (cairo_surface_get_content (surface) != expected_content) {
cairo_test_log ("Error: Created surface has content %d (expected %d)\n",
@ -357,7 +355,7 @@ cairo_test_for_target (cairo_test_t *test,
cr = cairo_create (surface);
if (similar)
cairo_push_group_with_content (cr, target->content);
cairo_push_group_with_content (cr, expected_content);
/* Clear to transparent (or black) depending on whether the target
* surface supports alpha. */

View file

@ -81,6 +81,8 @@ draw (cairo_t *cr, int width, int height)
cairo_paint (cr);
cairo_restore (cr);
cairo_surface_destroy (checker);
return CAIRO_TEST_SUCCESS;
}

BIN
test/group-paint-ref.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

57
test/group-paint.c Normal file
View file

@ -0,0 +1,57 @@
/*
* Copyright © Chris Wilson, 2008
*
* 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
* Chris Wilson 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.
*
* CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL CHRIS WILSON 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.
*
* Authors: Chris Wilson <chris@chris-wilson.co.uk>
*/
#include "cairo-test.h"
static cairo_test_draw_function_t draw;
cairo_test_t test = {
"group-paint",
"test push_group(); pop_group_to_source(); set_operator(SOURCE); paint();",
10, 10,
draw
};
static cairo_test_status_t
draw (cairo_t *cr, int dst_width, int dst_height)
{
cairo_push_group (cr);
cairo_set_source_rgb (cr, 0, 0, 1);
cairo_paint (cr);
cairo_pop_group_to_source (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB