Introduced cairo_fixed_*_t types. Converted several functions from floating to fixed point.

This commit is contained in:
Carl Worth 2003-07-23 21:20:24 +00:00
parent 6ef8b5cdf4
commit ee146c4740
7 changed files with 124 additions and 70 deletions

View file

@ -1,3 +1,21 @@
2003-07-23 Carl Worth <cworth@isi.edu>
* src/cairoint.h: Introduced some cairo_fixed_*_t types. This is
the first baby step toward ripping X dependencies out of the Cairo
headers.
* src/cairo_traps.c (_compute_x): Converted from floating point to
fixed point.
(_line_seg_intersection_ceil): Now increments y value once if the
initial y value computed is less than the actual intersection
point.
* src/cairo_traps.c (_compare_cairo_edge_by_slope): Converted from
floating point to fixed point.
* src/cairo_pen.c (_slope_clockwise): Converted from floating
point to fixed point.
2003-07-19 Carl Worth <cworth@isi.edu>
* src/cairo_traps.c (cairo_traps_tessellate_polygon): Fixed some

View file

@ -233,12 +233,8 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen)
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
{
double a_dx = XFixedToDouble (a->dx);
double a_dy = XFixedToDouble (a->dy);
double b_dx = XFixedToDouble (b->dx);
double b_dy = XFixedToDouble (b->dy);
return b_dy * a_dx > a_dy * b_dx;
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
static int

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
* Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -46,7 +46,7 @@ _compare_point_fixed_by_y (const void *av, const void *bv);
static int
_compare_cairo_edge_by_top (const void *av, const void *bv);
static XFixed
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y);
static double
@ -56,7 +56,7 @@ static double
_compute_x_intercept (XLineFixed *l, double inverse_slope);
static XFixed
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *intersection);
_line_seg_intersection_ceil (XLineFixed *left, XLineFixed *right, XFixed *intersection);
void
cairo_traps_init (cairo_traps_t *traps)
@ -164,7 +164,7 @@ cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
{
cairo_status_t status;
XLineFixed line;
double intersect;
cairo_fixed_16_16_t intersect;
XPointFixed tsort[3];
memcpy (tsort, t, 3 * sizeof (XPointFixed));
@ -281,17 +281,25 @@ static int
_compare_cairo_edge_by_slope (const void *av, const void *bv)
{
const cairo_edge_t *a = av, *b = bv;
cairo_fixed_32_32_t d;
double a_dx = XFixedToDouble (a->edge.p2.x - a->edge.p1.x);
double a_dy = XFixedToDouble (a->edge.p2.y - a->edge.p1.y);
double b_dx = XFixedToDouble (b->edge.p2.x - b->edge.p1.x);
double b_dy = XFixedToDouble (b->edge.p2.y - b->edge.p1.y);
cairo_fixed_48_16_t a_dx = a->edge.p2.x - a->edge.p1.x;
cairo_fixed_48_16_t a_dy = a->edge.p2.y - a->edge.p1.y;
cairo_fixed_48_16_t b_dx = b->edge.p2.x - b->edge.p1.x;
cairo_fixed_48_16_t b_dy = b->edge.p2.y - b->edge.p1.y;
return b_dy * a_dx - a_dy * b_dx;
d = b_dy * a_dx - a_dy * b_dx;
if (d > 0)
return 1;
else if (d == 0)
return 0;
else
return -1;
}
static int
_compare_cairo_edge_by_current_xthen_slope (const void *av, const void *bv)
_compare_cairo_edge_by_current_x_then_slope (const void *av, const void *bv)
{
const cairo_edge_t *a = av, *b = bv;
int ret;
@ -354,12 +362,12 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
return 1;
}
*/
static XFixed
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y)
{
XFixed dx = line->p2.x - line->p1.x;
double ex = (double) (y - line->p1.y) * (double) dx;
XFixed dy = line->p2.y - line->p1.y;
cairo_fixed_16_16_t dx = line->p2.x - line->p1.x;
cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx;
cairo_fixed_16_16_t dy = line->p2.y - line->p1.y;
return line->p1.x + (ex / dy);
}
@ -378,7 +386,7 @@ _compute_x_intercept (XLineFixed *l, double inverse_slope)
}
static int
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
_line_seg_intersection_ceil (XLineFixed *left, XLineFixed *right, XFixed *y_intersection)
{
/*
* x = m1y + b1
@ -387,15 +395,22 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
* y * (m1 - m2) = b2 - b1
* y = (b2 - b1) / (m1 - m2)
*/
double m1 = _compute_inverse_slope (l1);
double b1 = _compute_x_intercept (l1, m1);
double m2 = _compute_inverse_slope (l2);
double b2 = _compute_x_intercept (l2, m2);
cairo_fixed_16_16_t y;
double m1 = _compute_inverse_slope (left);
double b1 = _compute_x_intercept (left, m1);
double m2 = _compute_inverse_slope (right);
double b2 = _compute_x_intercept (right, m2);
if (m1 == m2)
return 0;
*y_intersection = XDoubleToFixed ((b2 - b1) / (m1 - m2));
y = XDoubleToFixed ((b2 - b1) / (m1 - m2));
if (_compute_x (right, y) < _compute_x (left, y))
y++;
*y_intersection = y;
return 1;
}
@ -414,7 +429,7 @@ _SortEdgeList (cairo_edge_t **active)
*/
for (en = next; en; en = en->next)
{
if (_compare_cairo_edge_by_current_xthen_slope (e, en) > 0)
if (_compare_cairo_edge_by_current_x_then_slope (e, en) > 0)
{
/*
* insert en before e
@ -531,14 +546,9 @@ cairo_traps_tessellate_polygon (cairo_traps_t *traps,
next_y = e->edge.p2.y;
/* check intersect */
if (en && e->current_x != en->current_x)
if (_lines_intersect (&e->edge, &en->edge, &intersect)) {
/* Need to make sure that when we next compute X
values for these two edges, that they will sort
as if after the intersection. */
intersect++;
if (_line_seg_intersection_ceil (&e->edge, &en->edge, &intersect))
if (intersect > y && intersect < next_y)
next_y = intersect;
}
}
/* check next inactive point */
if (inactive < num_edges && edges[inactive].edge.p1.y < next_y)

View file

@ -667,15 +667,15 @@ cairo_show_text (cairo_t *cr, const unsigned char *utf8)
void
cairo_show_surface (cairo_t *cr,
cairo_surface_t *surface,
int width,
int height)
cairo_surface_t *surface,
int width,
int height)
{
if (cr->status)
return;
cr->status = _cairo_gstate_show_surface (cr->gstate,
surface, width, height);
surface, width, height);
}
cairo_status_t

View file

@ -233,12 +233,8 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen)
static int
_slope_clockwise (cairo_slope_fixed_t *a, cairo_slope_fixed_t *b)
{
double a_dx = XFixedToDouble (a->dx);
double a_dy = XFixedToDouble (a->dy);
double b_dx = XFixedToDouble (b->dx);
double b_dy = XFixedToDouble (b->dy);
return b_dy * a_dx > a_dy * b_dx;
return ((cairo_fixed_48_16_t) b->dy * (cairo_fixed_48_16_t) a->dx
> (cairo_fixed_48_16_t) a->dy * (cairo_fixed_48_16_t) b->dx);
}
static int

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
* Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@ -46,7 +46,7 @@ _compare_point_fixed_by_y (const void *av, const void *bv);
static int
_compare_cairo_edge_by_top (const void *av, const void *bv);
static XFixed
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y);
static double
@ -56,7 +56,7 @@ static double
_compute_x_intercept (XLineFixed *l, double inverse_slope);
static XFixed
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *intersection);
_line_seg_intersection_ceil (XLineFixed *left, XLineFixed *right, XFixed *intersection);
void
cairo_traps_init (cairo_traps_t *traps)
@ -164,7 +164,7 @@ cairo_traps_tessellate_triangle (cairo_traps_t *traps, XPointFixed t[3])
{
cairo_status_t status;
XLineFixed line;
double intersect;
cairo_fixed_16_16_t intersect;
XPointFixed tsort[3];
memcpy (tsort, t, 3 * sizeof (XPointFixed));
@ -281,17 +281,25 @@ static int
_compare_cairo_edge_by_slope (const void *av, const void *bv)
{
const cairo_edge_t *a = av, *b = bv;
cairo_fixed_32_32_t d;
double a_dx = XFixedToDouble (a->edge.p2.x - a->edge.p1.x);
double a_dy = XFixedToDouble (a->edge.p2.y - a->edge.p1.y);
double b_dx = XFixedToDouble (b->edge.p2.x - b->edge.p1.x);
double b_dy = XFixedToDouble (b->edge.p2.y - b->edge.p1.y);
cairo_fixed_48_16_t a_dx = a->edge.p2.x - a->edge.p1.x;
cairo_fixed_48_16_t a_dy = a->edge.p2.y - a->edge.p1.y;
cairo_fixed_48_16_t b_dx = b->edge.p2.x - b->edge.p1.x;
cairo_fixed_48_16_t b_dy = b->edge.p2.y - b->edge.p1.y;
return b_dy * a_dx - a_dy * b_dx;
d = b_dy * a_dx - a_dy * b_dx;
if (d > 0)
return 1;
else if (d == 0)
return 0;
else
return -1;
}
static int
_compare_cairo_edge_by_current_xthen_slope (const void *av, const void *bv)
_compare_cairo_edge_by_current_x_then_slope (const void *av, const void *bv)
{
const cairo_edge_t *a = av, *b = bv;
int ret;
@ -354,12 +362,12 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
return 1;
}
*/
static XFixed
static cairo_fixed_16_16_t
_compute_x (XLineFixed *line, XFixed y)
{
XFixed dx = line->p2.x - line->p1.x;
double ex = (double) (y - line->p1.y) * (double) dx;
XFixed dy = line->p2.y - line->p1.y;
cairo_fixed_16_16_t dx = line->p2.x - line->p1.x;
cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx;
cairo_fixed_16_16_t dy = line->p2.y - line->p1.y;
return line->p1.x + (ex / dy);
}
@ -378,7 +386,7 @@ _compute_x_intercept (XLineFixed *l, double inverse_slope)
}
static int
_lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
_line_seg_intersection_ceil (XLineFixed *left, XLineFixed *right, XFixed *y_intersection)
{
/*
* x = m1y + b1
@ -387,15 +395,22 @@ _lines_intersect (XLineFixed *l1, XLineFixed *l2, XFixed *y_intersection)
* y * (m1 - m2) = b2 - b1
* y = (b2 - b1) / (m1 - m2)
*/
double m1 = _compute_inverse_slope (l1);
double b1 = _compute_x_intercept (l1, m1);
double m2 = _compute_inverse_slope (l2);
double b2 = _compute_x_intercept (l2, m2);
cairo_fixed_16_16_t y;
double m1 = _compute_inverse_slope (left);
double b1 = _compute_x_intercept (left, m1);
double m2 = _compute_inverse_slope (right);
double b2 = _compute_x_intercept (right, m2);
if (m1 == m2)
return 0;
*y_intersection = XDoubleToFixed ((b2 - b1) / (m1 - m2));
y = XDoubleToFixed ((b2 - b1) / (m1 - m2));
if (_compute_x (right, y) < _compute_x (left, y))
y++;
*y_intersection = y;
return 1;
}
@ -414,7 +429,7 @@ _SortEdgeList (cairo_edge_t **active)
*/
for (en = next; en; en = en->next)
{
if (_compare_cairo_edge_by_current_xthen_slope (e, en) > 0)
if (_compare_cairo_edge_by_current_x_then_slope (e, en) > 0)
{
/*
* insert en before e
@ -531,14 +546,9 @@ cairo_traps_tessellate_polygon (cairo_traps_t *traps,
next_y = e->edge.p2.y;
/* check intersect */
if (en && e->current_x != en->current_x)
if (_lines_intersect (&e->edge, &en->edge, &intersect)) {
/* Need to make sure that when we next compute X
values for these two edges, that they will sort
as if after the intersection. */
intersect++;
if (_line_seg_intersection_ceil (&e->edge, &en->edge, &intersect))
if (intersect > y && intersect < next_y)
next_y = intersect;
}
}
/* check next inactive point */
if (inactive < num_edges && edges[inactive].edge.p1.y < next_y)

View file

@ -36,6 +36,8 @@
#ifndef _CAIROINT_H_
#define _CAIROINT_H_
#include <assert.h>
#include <math.h>
#include <X11/Xlibint.h>
#include <X11/Xft/Xft.h>
@ -46,6 +48,28 @@
#define __attribute__(x)
#endif
#ifdef WIN32
typedef __int64 cairo_fixed_32_32_t;
#else
# if defined(__alpha__) || defined(__alpha) || \
defined(ia64) || defined(__ia64__) || \
defined(__sparc64__) || \
defined(__s390x__) || \
defined(x86_64) || defined (__x86_64__)
typedef long cairo_fixed_32_32_t;
# else
# if defined(__GNUC__) && \
((__GNUC__ > 2) || \
((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ > 7)))
__extension__
# endif
typedef long long int cairo_fixed_32_32_t;
# endif
#endif
typedef cairo_fixed_32_32_t cairo_fixed_48_16_t;
typedef int32_t cairo_fixed_16_16_t;
/* Sure wish C had a real enum type so that this would be distinct
from cairo_status_t. Oh well, without that, I'll use this bogus 1000
offset */