mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-18 17:40:43 +01:00
Corrected XrPenVerticesNeeded for handling transformed pens
This commit is contained in:
parent
34ab06281f
commit
bc362fc2e4
6 changed files with 102 additions and 20 deletions
|
|
@ -564,6 +564,9 @@ XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
|
|||
void
|
||||
XrTransformPoint(XrTransform *transform, XPointDouble *pt);
|
||||
|
||||
void
|
||||
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
|
||||
|
||||
/* xrtraps.c */
|
||||
void
|
||||
XrTrapsInit(XrTraps *traps);
|
||||
|
|
|
|||
26
src/xrpen.c
26
src/xrpen.c
|
|
@ -26,7 +26,7 @@
|
|||
#include "xrint.h"
|
||||
|
||||
static int
|
||||
_XrPenVerticesNeeded(double radius, double tolerance);
|
||||
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix);
|
||||
|
||||
static void
|
||||
_XrPenComputeSlopes(XrPen *pen);
|
||||
|
|
@ -77,7 +77,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
|
|||
pen->radius = radius;
|
||||
pen->tolerance = gstate->tolerance;
|
||||
|
||||
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance);
|
||||
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
|
||||
|
||||
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
|
||||
if (pen->vertex == NULL) {
|
||||
|
|
@ -199,17 +199,23 @@ XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
|
|||
}
|
||||
|
||||
static int
|
||||
_XrPenVerticesNeeded(double radius, double tolerance)
|
||||
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
|
||||
{
|
||||
/* XXX: BUG: This calculation needs to be corrected to account for
|
||||
the fact that the radius is specified in user space, while the
|
||||
tolerance is specified in device space. */
|
||||
double e1, e2, emax, theta;
|
||||
|
||||
if (tolerance > radius) {
|
||||
return 4;
|
||||
} else {
|
||||
double theta = acos(1 - tolerance/radius);
|
||||
return ceil(M_PI / theta);
|
||||
}
|
||||
}
|
||||
|
||||
XrTransformEigenValues(matrix, &e1, &e2);
|
||||
|
||||
if (fabs(e1) > fabs(e2))
|
||||
emax = fabs(e1);
|
||||
else
|
||||
emax = fabs(e2);
|
||||
|
||||
theta = acos(1 - tolerance/(emax * radius));
|
||||
return ceil(M_PI / theta);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -151,3 +151,35 @@ XrTransformPoint(XrTransform *transform, XPointDouble *pt)
|
|||
pt->x += transform->m[2][0];
|
||||
pt->y += transform->m[2][1];
|
||||
}
|
||||
|
||||
void
|
||||
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
|
||||
{
|
||||
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
|
||||
|
||||
det(M - lI) = 0
|
||||
|
||||
which for our 2x2 matrix:
|
||||
|
||||
M = a b
|
||||
c d
|
||||
|
||||
gives:
|
||||
|
||||
l^2 - (a+d)l + (ad - bc) = 0
|
||||
|
||||
l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2;
|
||||
*/
|
||||
|
||||
double a, b, c, d, rad;
|
||||
|
||||
a = transform->m[0][0];
|
||||
b = transform->m[0][1];
|
||||
c = transform->m[1][0];
|
||||
d = transform->m[1][1];
|
||||
|
||||
rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c));
|
||||
*lambda1 = (a + d + rad) / 2.0;
|
||||
*lambda2 = (a + d - rad) / 2.0;
|
||||
}
|
||||
|
||||
|
|
|
|||
3
xrint.h
3
xrint.h
|
|
@ -564,6 +564,9 @@ XrTransformPointWithoutTranslate(XrTransform *transform, XPointDouble *pt);
|
|||
void
|
||||
XrTransformPoint(XrTransform *transform, XPointDouble *pt);
|
||||
|
||||
void
|
||||
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2);
|
||||
|
||||
/* xrtraps.c */
|
||||
void
|
||||
XrTrapsInit(XrTraps *traps);
|
||||
|
|
|
|||
26
xrpen.c
26
xrpen.c
|
|
@ -26,7 +26,7 @@
|
|||
#include "xrint.h"
|
||||
|
||||
static int
|
||||
_XrPenVerticesNeeded(double radius, double tolerance);
|
||||
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix);
|
||||
|
||||
static void
|
||||
_XrPenComputeSlopes(XrPen *pen);
|
||||
|
|
@ -77,7 +77,7 @@ XrPenInit(XrPen *pen, double radius, XrGState *gstate)
|
|||
pen->radius = radius;
|
||||
pen->tolerance = gstate->tolerance;
|
||||
|
||||
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance);
|
||||
pen->num_vertices = _XrPenVerticesNeeded(radius, gstate->tolerance, &gstate->ctm);
|
||||
|
||||
pen->vertex = malloc(pen->num_vertices * sizeof(XrPenVertex));
|
||||
if (pen->vertex == NULL) {
|
||||
|
|
@ -199,17 +199,23 @@ XrPenAddPoints(XrPen *pen, XrPenTaggedPoint *pt, int num_pts)
|
|||
}
|
||||
|
||||
static int
|
||||
_XrPenVerticesNeeded(double radius, double tolerance)
|
||||
_XrPenVerticesNeeded(double radius, double tolerance, XrTransform *matrix)
|
||||
{
|
||||
/* XXX: BUG: This calculation needs to be corrected to account for
|
||||
the fact that the radius is specified in user space, while the
|
||||
tolerance is specified in device space. */
|
||||
double e1, e2, emax, theta;
|
||||
|
||||
if (tolerance > radius) {
|
||||
return 4;
|
||||
} else {
|
||||
double theta = acos(1 - tolerance/radius);
|
||||
return ceil(M_PI / theta);
|
||||
}
|
||||
}
|
||||
|
||||
XrTransformEigenValues(matrix, &e1, &e2);
|
||||
|
||||
if (fabs(e1) > fabs(e2))
|
||||
emax = fabs(e1);
|
||||
else
|
||||
emax = fabs(e2);
|
||||
|
||||
theta = acos(1 - tolerance/(emax * radius));
|
||||
return ceil(M_PI / theta);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -151,3 +151,35 @@ XrTransformPoint(XrTransform *transform, XPointDouble *pt)
|
|||
pt->x += transform->m[2][0];
|
||||
pt->y += transform->m[2][1];
|
||||
}
|
||||
|
||||
void
|
||||
XrTransformEigenValues(XrTransform *transform, double *lambda1, double *lambda2)
|
||||
{
|
||||
/* The eigenvalues of an NxN matrix M are found by solving the polynomial:
|
||||
|
||||
det(M - lI) = 0
|
||||
|
||||
which for our 2x2 matrix:
|
||||
|
||||
M = a b
|
||||
c d
|
||||
|
||||
gives:
|
||||
|
||||
l^2 - (a+d)l + (ad - bc) = 0
|
||||
|
||||
l = (a+d +/- sqrt(a^2 + 2ad + d^2 - 4(ad-bc))) / 2;
|
||||
*/
|
||||
|
||||
double a, b, c, d, rad;
|
||||
|
||||
a = transform->m[0][0];
|
||||
b = transform->m[0][1];
|
||||
c = transform->m[1][0];
|
||||
d = transform->m[1][1];
|
||||
|
||||
rad = sqrt(a*a + 2*a*d + d*d - 4*(a*d - b*c));
|
||||
*lambda1 = (a + d + rad) / 2.0;
|
||||
*lambda2 = (a + d - rad) / 2.0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue