Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 34... Line 34...
34
 *	Carl D. Worth 
34
 *	Carl D. Worth 
35
 */
35
 */
Line 36... Line 36...
36
 
36
 
37
#include "cairoint.h"
37
#include "cairoint.h"
-
 
38
#include "cairo-error-private.h"
-
 
39
#include 
-
 
40
 
Line 38... Line 41...
38
#include "cairo-error-private.h"
41
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
39
 
42
 
40
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
43
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
41
#define ISFINITE(x) isfinite (x)
44
#define ISFINITE(x) isfinite (x)
Line 62... Line 65...
62
 *
65
 *
63
 * The current transformation matrix of a #cairo_t, represented as a
66
 * The current transformation matrix of a #cairo_t, represented as a
64
 * #cairo_matrix_t, defines the transformation from user-space
67
 * #cairo_matrix_t, defines the transformation from user-space
65
 * coordinates to device-space coordinates. See cairo_get_matrix() and
68
 * coordinates to device-space coordinates. See cairo_get_matrix() and
66
 * cairo_set_matrix().
69
 * cairo_set_matrix().
67
 */
70
 **/
Line 68... Line 71...
68
 
71
 
69
static void
72
static void
Line 70... Line 73...
70
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
73
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
Line 75... Line 78...
75
/**
78
/**
76
 * cairo_matrix_init_identity:
79
 * cairo_matrix_init_identity:
77
 * @matrix: a #cairo_matrix_t
80
 * @matrix: a #cairo_matrix_t
78
 *
81
 *
79
 * Modifies @matrix to be an identity transformation.
82
 * Modifies @matrix to be an identity transformation.
-
 
83
 *
-
 
84
 * Since: 1.0
80
 **/
85
 **/
81
void
86
void
82
cairo_matrix_init_identity (cairo_matrix_t *matrix)
87
cairo_matrix_init_identity (cairo_matrix_t *matrix)
83
{
88
{
84
    cairo_matrix_init (matrix,
89
    cairo_matrix_init (matrix,
Line 103... Line 108...
103
 * by:
108
 * by:
104
 * 
109
 * 
105
 *  x_new = xx * x + xy * y + x0;
110
 *  x_new = xx * x + xy * y + x0;
106
 *  y_new = yx * x + yy * y + y0;
111
 *  y_new = yx * x + yy * y + y0;
107
 * 
112
 * 
-
 
113
 *
-
 
114
 * Since: 1.0
108
 **/
115
 **/
109
void
116
void
110
cairo_matrix_init (cairo_matrix_t *matrix,
117
cairo_matrix_init (cairo_matrix_t *matrix,
111
		   double xx, double yx,
118
		   double xx, double yx,
Line 163... Line 170...
163
 * @tx: amount to translate in the X direction
170
 * @tx: amount to translate in the X direction
164
 * @ty: amount to translate in the Y direction
171
 * @ty: amount to translate in the Y direction
165
 *
172
 *
166
 * Initializes @matrix to a transformation that translates by @tx and
173
 * Initializes @matrix to a transformation that translates by @tx and
167
 * @ty in the X and Y dimensions, respectively.
174
 * @ty in the X and Y dimensions, respectively.
-
 
175
 *
-
 
176
 * Since: 1.0
168
 **/
177
 **/
169
void
178
void
170
cairo_matrix_init_translate (cairo_matrix_t *matrix,
179
cairo_matrix_init_translate (cairo_matrix_t *matrix,
171
			     double tx, double ty)
180
			     double tx, double ty)
172
{
181
{
Line 185... Line 194...
185
 *
194
 *
186
 * Applies a translation by @tx, @ty to the transformation in
195
 * Applies a translation by @tx, @ty to the transformation in
187
 * @matrix. The effect of the new transformation is to first translate
196
 * @matrix. The effect of the new transformation is to first translate
188
 * the coordinates by @tx and @ty, then apply the original transformation
197
 * the coordinates by @tx and @ty, then apply the original transformation
189
 * to the coordinates.
198
 * to the coordinates.
-
 
199
 *
-
 
200
 * Since: 1.0
190
 **/
201
 **/
191
void
202
void
192
cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
203
cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
193
{
204
{
194
    cairo_matrix_t tmp;
205
    cairo_matrix_t tmp;
Line 205... Line 216...
205
 * @sx: scale factor in the X direction
216
 * @sx: scale factor in the X direction
206
 * @sy: scale factor in the Y direction
217
 * @sy: scale factor in the Y direction
207
 *
218
 *
208
 * Initializes @matrix to a transformation that scales by @sx and @sy
219
 * Initializes @matrix to a transformation that scales by @sx and @sy
209
 * in the X and Y dimensions, respectively.
220
 * in the X and Y dimensions, respectively.
-
 
221
 *
-
 
222
 * Since: 1.0
210
 **/
223
 **/
211
void
224
void
212
cairo_matrix_init_scale (cairo_matrix_t *matrix,
225
cairo_matrix_init_scale (cairo_matrix_t *matrix,
213
			 double sx, double sy)
226
			 double sx, double sy)
214
{
227
{
Line 226... Line 239...
226
 * @sy: scale factor in the Y direction
239
 * @sy: scale factor in the Y direction
227
 *
240
 *
228
 * Applies scaling by @sx, @sy to the transformation in @matrix. The
241
 * Applies scaling by @sx, @sy to the transformation in @matrix. The
229
 * effect of the new transformation is to first scale the coordinates
242
 * effect of the new transformation is to first scale the coordinates
230
 * by @sx and @sy, then apply the original transformation to the coordinates.
243
 * by @sx and @sy, then apply the original transformation to the coordinates.
-
 
244
 *
-
 
245
 * Since: 1.0
231
 **/
246
 **/
232
void
247
void
233
cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
248
cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
234
{
249
{
235
    cairo_matrix_t tmp;
250
    cairo_matrix_t tmp;
Line 248... Line 263...
248
 * the positive X axis toward the positive Y axis. With the default
263
 * the positive X axis toward the positive Y axis. With the default
249
 * axis orientation of cairo, positive angles rotate in a clockwise
264
 * axis orientation of cairo, positive angles rotate in a clockwise
250
 * direction.
265
 * direction.
251
 *
266
 *
252
 * Initialized @matrix to a transformation that rotates by @radians.
267
 * Initialized @matrix to a transformation that rotates by @radians.
-
 
268
 *
-
 
269
 * Since: 1.0
253
 **/
270
 **/
254
void
271
void
255
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
272
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
256
			  double radians)
273
			  double radians)
257
{
274
{
Line 279... Line 296...
279
 *
296
 *
280
 * Applies rotation by @radians to the transformation in
297
 * Applies rotation by @radians to the transformation in
281
 * @matrix. The effect of the new transformation is to first rotate the
298
 * @matrix. The effect of the new transformation is to first rotate the
282
 * coordinates by @radians, then apply the original transformation
299
 * coordinates by @radians, then apply the original transformation
283
 * to the coordinates.
300
 * to the coordinates.
-
 
301
 *
-
 
302
 * Since: 1.0
284
 **/
303
 **/
285
void
304
void
286
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
305
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
287
{
306
{
288
    cairo_matrix_t tmp;
307
    cairo_matrix_t tmp;
Line 303... Line 322...
303
 * transformation is to first apply the transformation in @a to the
322
 * transformation is to first apply the transformation in @a to the
304
 * coordinates and then apply the transformation in @b to the
323
 * coordinates and then apply the transformation in @b to the
305
 * coordinates.
324
 * coordinates.
306
 *
325
 *
307
 * It is allowable for @result to be identical to either @a or @b.
326
 * It is allowable for @result to be identical to either @a or @b.
-
 
327
 *
-
 
328
 * Since: 1.0
308
 **/
329
 **/
309
/*
330
/*
310
 * XXX: The ordering of the arguments to this function corresponds
331
 * XXX: The ordering of the arguments to this function corresponds
311
 *      to [row_vector]*A*B. If we want to use column vectors instead,
332
 *      to [row_vector]*A*B. If we want to use column vectors instead,
312
 *      then we need to switch the two arguments and fix up all
333
 *      then we need to switch the two arguments and fix up all
Line 328... Line 349...
328
 
349
 
329
    *result = r;
350
    *result = r;
330
}
351
}
Line -... Line 352...
-
 
352
slim_hidden_def(cairo_matrix_multiply);
-
 
353
 
-
 
354
void
-
 
355
_cairo_matrix_multiply (cairo_matrix_t *r,
-
 
356
			const cairo_matrix_t *a,
-
 
357
			const cairo_matrix_t *b)
-
 
358
{
-
 
359
    r->xx = a->xx * b->xx + a->yx * b->xy;
-
 
360
    r->yx = a->xx * b->yx + a->yx * b->yy;
-
 
361
 
-
 
362
    r->xy = a->xy * b->xx + a->yy * b->xy;
-
 
363
    r->yy = a->xy * b->yx + a->yy * b->yy;
-
 
364
 
-
 
365
    r->x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
-
 
366
    r->y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
331
slim_hidden_def(cairo_matrix_multiply);
367
}
332
 
368
 
333
/**
369
/**
334
 * cairo_matrix_transform_distance:
370
 * cairo_matrix_transform_distance:
335
 * @matrix: a #cairo_matrix_t
371
 * @matrix: a #cairo_matrix_t
Line 348... Line 384...
348
 *
384
 *
349
 * Affine transformations are position invariant, so the same vector
385
 * Affine transformations are position invariant, so the same vector
350
 * always transforms to the same vector. If (@x1,@y1) transforms
386
 * always transforms to the same vector. If (@x1,@y1) transforms
351
 * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
387
 * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
352
 * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
388
 * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
-
 
389
 *
-
 
390
 * Since: 1.0
353
 **/
391
 **/
354
void
392
void
355
cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy)
393
cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy)
356
{
394
{
357
    double new_x, new_y;
395
    double new_x, new_y;
Line 369... Line 407...
369
 * @matrix: a #cairo_matrix_t
407
 * @matrix: a #cairo_matrix_t
370
 * @x: X position. An in/out parameter
408
 * @x: X position. An in/out parameter
371
 * @y: Y position. An in/out parameter
409
 * @y: Y position. An in/out parameter
372
 *
410
 *
373
 * Transforms the point (@x, @y) by @matrix.
411
 * Transforms the point (@x, @y) by @matrix.
-
 
412
 *
-
 
413
 * Since: 1.0
374
 **/
414
 **/
375
void
415
void
376
cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y)
416
cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y)
377
{
417
{
378
    cairo_matrix_transform_distance (matrix, x, y);
418
    cairo_matrix_transform_distance (matrix, x, y);
Line 543... Line 583...
543
 * then it has no inverse and this function will fail.
583
 * then it has no inverse and this function will fail.
544
 *
584
 *
545
 * Returns: If @matrix has an inverse, modifies @matrix to
585
 * Returns: If @matrix has an inverse, modifies @matrix to
546
 *  be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise,
586
 *  be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise,
547
 *  returns %CAIRO_STATUS_INVALID_MATRIX.
587
 *  returns %CAIRO_STATUS_INVALID_MATRIX.
-
 
588
 *
-
 
589
 * Since: 1.0
548
 **/
590
 **/
549
cairo_status_t
591
cairo_status_t
550
cairo_matrix_invert (cairo_matrix_t *matrix)
592
cairo_matrix_invert (cairo_matrix_t *matrix)
551
{
593
{
552
    double det;
594
    double det;
Line 681... Line 723...
681
 
723
 
682
    return CAIRO_STATUS_SUCCESS;
724
    return CAIRO_STATUS_SUCCESS;
Line 683... Line 725...
683
}
725
}
684
 
-
 
685
cairo_bool_t
-
 
686
_cairo_matrix_is_identity (const cairo_matrix_t *matrix)
-
 
687
{
-
 
688
    return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
-
 
689
	    matrix->xy == 0.0 && matrix->yy == 1.0 &&
-
 
690
	    matrix->x0 == 0.0 && matrix->y0 == 0.0);
-
 
691
}
-
 
692
 
-
 
693
cairo_bool_t
-
 
694
_cairo_matrix_is_translation (const cairo_matrix_t *matrix)
-
 
695
{
-
 
696
    return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
-
 
697
	    matrix->xy == 0.0 && matrix->yy == 1.0);
-
 
698
}
-
 
699
 
726
 
700
cairo_bool_t
727
cairo_bool_t
701
_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
728
_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
702
				      int *itx, int *ity)
729
				      int *itx, int *ity)
703
{
730
{
Line 884... Line 911...
884
_cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
911
_cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
885
					     double radius)
912
					     double radius)
886
{
913
{
887
    double  a, b, c, d, f, g, h, i, j;
914
    double  a, b, c, d, f, g, h, i, j;
Line -... Line 915...
-
 
915
 
-
 
916
    if (_cairo_matrix_has_unity_scale (matrix))
-
 
917
	return radius;
888
 
918
 
889
    _cairo_matrix_get_affine (matrix,
919
    _cairo_matrix_get_affine (matrix,
890
                              &a, &b,
920
                              &a, &b,
891
                              &c, &d,
921
                              &c, &d,
Line 904... Line 934...
904
     * we don't need the minor axis length, which is
934
     * we don't need the minor axis length, which is
905
     * double min = radius * sqrt (f - sqrt (g*g+h*h));
935
     * double min = radius * sqrt (f - sqrt (g*g+h*h));
906
     */
936
     */
907
}
937
}
Line 908... Line -...
908
 
-
 
909
void
-
 
910
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
-
 
911
				pixman_transform_t	*pixman_transform,
-
 
912
				double xc,
-
 
913
				double yc)
-
 
914
{
938
 
915
    static const pixman_transform_t pixman_identity_transform = {{
939
static const pixman_transform_t pixman_identity_transform = {{
916
        {1 << 16,        0,       0},
940
        {1 << 16,        0,       0},
917
        {       0, 1 << 16,       0},
941
        {       0, 1 << 16,       0},
918
        {       0,       0, 1 << 16}
942
        {       0,       0, 1 << 16}
Line -... Line 943...
-
 
943
    }};
919
    }};
944
 
920
 
945
static cairo_status_t
-
 
946
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
921
    if (_cairo_matrix_is_identity (matrix)) {
947
				pixman_transform_t	*pixman_transform,
-
 
948
				double xc,
922
        *pixman_transform = pixman_identity_transform;
949
				double yc)
923
    } else {
950
{
Line 924... Line 951...
924
        cairo_matrix_t inv;
951
    cairo_matrix_t inv;
925
	unsigned max_iterations;
952
    unsigned max_iterations;
Line 946... Line 973...
946
         * space and adjust pixman's transform to agree with cairo's at
973
     * space and adjust pixman's transform to agree with cairo's at
947
         * that point.
974
     * that point.
948
	 */
975
     */
Line 949... Line 976...
949
 
976
 
-
 
977
    if (_cairo_matrix_has_unity_scale (matrix))
-
 
978
	return CAIRO_STATUS_SUCCESS;
-
 
979
 
-
 
980
    if (unlikely (fabs (matrix->xx) > PIXMAN_MAX_INT ||
-
 
981
		  fabs (matrix->xy) > PIXMAN_MAX_INT ||
-
 
982
		  fabs (matrix->x0) > PIXMAN_MAX_INT ||
-
 
983
		  fabs (matrix->yx) > PIXMAN_MAX_INT ||
-
 
984
		  fabs (matrix->yy) > PIXMAN_MAX_INT ||
950
	if (_cairo_matrix_has_unity_scale (matrix))
985
		  fabs (matrix->y0) > PIXMAN_MAX_INT))
-
 
986
    {
-
 
987
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
Line 951... Line 988...
951
	    return;
988
    }
952
 
989
 
953
        /* Note: If we can't invert the transformation, skip the adjustment. */
990
    /* Note: If we can't invert the transformation, skip the adjustment. */
954
        inv = *matrix;
991
    inv = *matrix;
Line 955... Line 992...
955
        if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
992
    if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
956
            return;
-
 
957
 
993
	return CAIRO_STATUS_SUCCESS;
958
        /* find the pattern space coordinate that maps to (xc, yc) */
994
 
959
	xc += .5; yc += .5; /* offset for the pixel centre */
995
    /* find the pattern space coordinate that maps to (xc, yc) */
960
	max_iterations = 5;
996
    max_iterations = 5;
961
	do {
997
    do {
Line 962... Line 998...
962
	    double x,y;
998
	double x,y;
963
	    pixman_vector_t vector;
999
	pixman_vector_t vector;
964
	    cairo_fixed_16_16_t dx, dy;
1000
	cairo_fixed_16_16_t dx, dy;
Line -... Line 1001...
-
 
1001
 
965
 
1002
	vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
966
	    vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
1003
	vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
Line 967... Line 1004...
967
	    vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
1004
	vector.vector[2] = 1 << 16;
968
	    vector.vector[2] = 1 << 16;
1005
 
969
 
1006
	/* If we can't transform the reference point, skip the adjustment. */
Line 984... Line 1021...
984
	    dy = _cairo_fixed_16_16_from_double (y);
1021
	dy = _cairo_fixed_16_16_from_double (y);
985
	    pixman_transform->matrix[0][2] -= dx;
1022
	pixman_transform->matrix[0][2] -= dx;
986
	    pixman_transform->matrix[1][2] -= dy;
1023
	pixman_transform->matrix[1][2] -= dy;
Line 987... Line 1024...
987
 
1024
 
988
	    if (dx == 0 && dy == 0)
1025
	if (dx == 0 && dy == 0)
989
		break;
1026
	    return CAIRO_STATUS_SUCCESS;
-
 
1027
    } while (--max_iterations);
-
 
1028
 
-
 
1029
    /* We didn't find an exact match between cairo and pixman, but
-
 
1030
     * the matrix should be mostly correct */
-
 
1031
    return CAIRO_STATUS_SUCCESS;
-
 
1032
}
-
 
1033
 
-
 
1034
static inline double
-
 
1035
_pixman_nearest_sample (double d)
-
 
1036
{
-
 
1037
    return ceil (d - .5);
-
 
1038
}
-
 
1039
 
-
 
1040
/**
-
 
1041
 * _cairo_matrix_is_pixman_translation:
-
 
1042
 * @matrix: a matrix
-
 
1043
 * @filter: the filter to be used on the pattern transformed by @matrix
-
 
1044
 * @x_offset: the translation in the X direction
-
 
1045
 * @y_offset: the translation in the Y direction
-
 
1046
 *
-
 
1047
 * Checks if @matrix translated by (x_offset, y_offset) can be
-
 
1048
 * represented using just an offset (within the range pixman can
-
 
1049
 * accept) and an identity matrix.
-
 
1050
 *
-
 
1051
 * Passing a non-zero value in x_offset/y_offset has the same effect
-
 
1052
 * as applying cairo_matrix_translate(matrix, x_offset, y_offset) and
-
 
1053
 * setting x_offset and y_offset to 0.
-
 
1054
 *
-
 
1055
 * Upon return x_offset and y_offset contain the translation vector if
-
 
1056
 * the return value is %TRUE. If the return value is %FALSE, they will
-
 
1057
 * not be modified.
-
 
1058
 *
-
 
1059
 * Return value: %TRUE if @matrix can be represented as a pixman
-
 
1060
 * translation, %FALSE otherwise.
-
 
1061
 **/
-
 
1062
cairo_bool_t
-
 
1063
_cairo_matrix_is_pixman_translation (const cairo_matrix_t     *matrix,
-
 
1064
				     cairo_filter_t            filter,
-
 
1065
				     int                      *x_offset,
-
 
1066
				     int                      *y_offset)
-
 
1067
{
-
 
1068
    double tx, ty;
-
 
1069
 
-
 
1070
    if (!_cairo_matrix_is_translation (matrix))
-
 
1071
	return FALSE;
-
 
1072
 
-
 
1073
    if (matrix->x0 == 0. && matrix->y0 == 0.)
-
 
1074
	return TRUE;
-
 
1075
 
-
 
1076
    tx = matrix->x0 + *x_offset;
-
 
1077
    ty = matrix->y0 + *y_offset;
-
 
1078
 
-
 
1079
    if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) {
-
 
1080
	tx = _pixman_nearest_sample (tx);
-
 
1081
	ty = _pixman_nearest_sample (ty);
-
 
1082
    } else if (tx != floor (tx) || ty != floor (ty)) {
-
 
1083
	return FALSE;
-
 
1084
    }
-
 
1085
 
-
 
1086
    if (fabs (tx) > PIXMAN_MAX_INT || fabs (ty) > PIXMAN_MAX_INT)
-
 
1087
	return FALSE;
-
 
1088
 
-
 
1089
    *x_offset = _cairo_lround (tx);
-
 
1090
    *y_offset = _cairo_lround (ty);
-
 
1091
    return TRUE;
-
 
1092
}
-
 
1093
 
-
 
1094
/**
-
 
1095
 * _cairo_matrix_to_pixman_matrix_offset:
-
 
1096
 * @matrix: a matrix
-
 
1097
 * @filter: the filter to be used on the pattern transformed by @matrix
-
 
1098
 * @xc: the X coordinate of the point to fix in pattern space
-
 
1099
 * @yc: the Y coordinate of the point to fix in pattern space
-
 
1100
 * @out_transform: the transformation which best approximates @matrix
-
 
1101
 * @x_offset: the translation in the X direction
-
 
1102
 * @y_offset: the translation in the Y direction
-
 
1103
 *
-
 
1104
 * This function tries to represent @matrix translated by (x_offset,
-
 
1105
 * y_offset) as a %pixman_transform_t and an translation.
-
 
1106
 *
-
 
1107
 * Passing a non-zero value in x_offset/y_offset has the same effect
-
 
1108
 * as applying cairo_matrix_translate(matrix, x_offset, y_offset) and
-
 
1109
 * setting x_offset and y_offset to 0.
-
 
1110
 *
-
 
1111
 * If it is possible to represent the matrix with an identity
-
 
1112
 * %pixman_transform_t and a translation within the valid range for
-
 
1113
 * pixman, this function will set @out_transform to be the identity,
-
 
1114
 * @x_offset and @y_offset to be the translation vector and will
-
 
1115
 * return %CAIRO_INT_STATUS_NOTHING_TO_DO. Otherwise it will try to
-
 
1116
 * evenly divide the translational component of @matrix between
-
 
1117
 * @out_transform and (@x_offset, @y_offset).
-
 
1118
 *
-
 
1119
 * Upon return x_offset and y_offset contain the translation vector.
-
 
1120
 *
-
 
1121
 * Return value: %CAIRO_INT_STATUS_NOTHING_TO_DO if the out_transform
-
 
1122
 * is the identity, %CAIRO_STATUS_INVALID_MATRIX if it was not
-
 
1123
 * possible to represent @matrix as a pixman_transform_t without
-
 
1124
 * overflows, %CAIRO_STATUS_SUCCESS otherwise.
-
 
1125
 **/
-
 
1126
cairo_status_t
-
 
1127
_cairo_matrix_to_pixman_matrix_offset (const cairo_matrix_t	*matrix,
-
 
1128
				       cairo_filter_t            filter,
-
 
1129
				       double                    xc,
-
 
1130
				       double                    yc,
-
 
1131
				       pixman_transform_t	*out_transform,
-
 
1132
				       int                      *x_offset,
-
 
1133
				       int                      *y_offset)
-
 
1134
{
-
 
1135
    cairo_bool_t is_pixman_translation;
-
 
1136
 
-
 
1137
    is_pixman_translation = _cairo_matrix_is_pixman_translation (matrix,
-
 
1138
								 filter,
-
 
1139
								 x_offset,
-
 
1140
								 y_offset);
-
 
1141
 
-
 
1142
    if (is_pixman_translation) {
-
 
1143
	*out_transform = pixman_identity_transform;
-
 
1144
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
 
1145
    } else {
-
 
1146
	cairo_matrix_t m;
-
 
1147
 
-
 
1148
	m = *matrix;
-
 
1149
	cairo_matrix_translate (&m, *x_offset, *y_offset);
-
 
1150
	if (m.x0 != 0.0 || m.y0 != 0.0) {
-
 
1151
	    double tx, ty, norm;
-
 
1152
	    int i, j;
-
 
1153
 
-
 
1154
	    /* pixman also limits the [xy]_offset to 16 bits so evenly
-
 
1155
	     * spread the bits between the two.
-
 
1156
	     *
-
 
1157
	     * To do this, find the solutions of:
-
 
1158
	     *   |x| = |x*m.xx + y*m.xy + m.x0|
-
 
1159
	     *   |y| = |x*m.yx + y*m.yy + m.y0|
-
 
1160
	     *
-
 
1161
	     * and select the one whose maximum norm is smallest.
-
 
1162
	     */
-
 
1163
	    tx = m.x0;
-
 
1164
	    ty = m.y0;
-
 
1165
	    norm = MAX (fabs (tx), fabs (ty));
-
 
1166
 
-
 
1167
	    for (i = -1; i < 2; i+=2) {
-
 
1168
		for (j = -1; j < 2; j+=2) {
-
 
1169
		    double x, y, den, new_norm;
-
 
1170
 
-
 
1171
		    den = (m.xx + i) * (m.yy + j) - m.xy * m.yx;
-
 
1172
		    if (fabs (den) < DBL_EPSILON)
-
 
1173
			continue;
-
 
1174
 
-
 
1175
		    x = m.y0 * m.xy - m.x0 * (m.yy + j);
-
 
1176
		    y = m.x0 * m.yx - m.y0 * (m.xx + i);
-
 
1177
 
-
 
1178
		    den = 1 / den;
-
 
1179
		    x *= den;
-
 
1180
		    y *= den;
-
 
1181
 
-
 
1182
		    new_norm = MAX (fabs (x), fabs (y));
-
 
1183
		    if (norm > new_norm) {
-
 
1184
			norm = new_norm;
-
 
1185
			tx = x;
-
 
1186
			ty = y;
-
 
1187
		    }
-
 
1188
		}
-
 
1189
	    }
-
 
1190
 
-
 
1191
	    tx = floor (tx);
-
 
1192
	    ty = floor (ty);
-
 
1193
	    *x_offset = -tx;
-
 
1194
	    *y_offset = -ty;
-
 
1195
	    cairo_matrix_translate (&m, tx, ty);
-
 
1196
	} else {
-
 
1197
	    *x_offset = 0;
-
 
1198
	    *y_offset = 0;
-
 
1199
	}
-
 
1200
 
990
	} while (--max_iterations);
1201
	return _cairo_matrix_to_pixman_matrix (&m, out_transform, xc, yc);
991
    }
1202
    }