Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1892 serge 1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2002 University of Southern California
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it either under the terms of the GNU Lesser General Public
7
 * License version 2.1 as published by the Free Software Foundation
8
 * (the "LGPL") or, at your option, under the terms of the Mozilla
9
 * Public License Version 1.1 (the "MPL"). If you do not alter this
10
 * notice, a recipient may use your version of this file under either
11
 * the MPL or the LGPL.
12
 *
13
 * You should have received a copy of the LGPL along with this library
14
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16
 * You should have received a copy of the MPL along with this library
17
 * in the file COPYING-MPL-1.1
18
 *
19
 * The contents of this file are subject to the Mozilla Public License
20
 * Version 1.1 (the "License"); you may not use this file except in
21
 * compliance with the License. You may obtain a copy of the License at
22
 * http://www.mozilla.org/MPL/
23
 *
24
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26
 * the specific language governing rights and limitations.
27
 *
28
 * The Original Code is the cairo graphics library.
29
 *
30
 * The Initial Developer of the Original Code is University of Southern
31
 * California.
32
 *
33
 * Contributor(s):
34
 *	Carl D. Worth 
35
 */
36
 
37
#include "cairoint.h"
38
#include "cairo-error-private.h"
3959 Serge 39
#include 
1892 serge 40
 
3959 Serge 41
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
42
 
1892 serge 43
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
44
#define ISFINITE(x) isfinite (x)
45
#else
46
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
47
#endif
48
 
49
/**
50
 * SECTION:cairo-matrix
51
 * @Title: cairo_matrix_t
52
 * @Short_Description: Generic matrix operations
53
 * @See_Also: #cairo_t
54
 *
55
 * #cairo_matrix_t is used throughout cairo to convert between different
56
 * coordinate spaces.  A #cairo_matrix_t holds an affine transformation,
57
 * such as a scale, rotation, shear, or a combination of these.
58
 * The transformation of a point (x,y)
59
 * is given by:
60
 *
61
 * 
62
 * x_new = xx * x + xy * y + x0;
63
 * y_new = yx * x + yy * y + y0;
64
 * 
65
 *
66
 * The current transformation matrix of a #cairo_t, represented as a
67
 * #cairo_matrix_t, defines the transformation from user-space
68
 * coordinates to device-space coordinates. See cairo_get_matrix() and
69
 * cairo_set_matrix().
3959 Serge 70
 **/
1892 serge 71
 
72
static void
73
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
74
 
75
static void
76
_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix);
77
 
78
/**
79
 * cairo_matrix_init_identity:
80
 * @matrix: a #cairo_matrix_t
81
 *
82
 * Modifies @matrix to be an identity transformation.
3959 Serge 83
 *
84
 * Since: 1.0
1892 serge 85
 **/
86
void
87
cairo_matrix_init_identity (cairo_matrix_t *matrix)
88
{
89
    cairo_matrix_init (matrix,
90
		       1, 0,
91
		       0, 1,
92
		       0, 0);
93
}
94
slim_hidden_def(cairo_matrix_init_identity);
95
 
96
/**
97
 * cairo_matrix_init:
98
 * @matrix: a #cairo_matrix_t
99
 * @xx: xx component of the affine transformation
100
 * @yx: yx component of the affine transformation
101
 * @xy: xy component of the affine transformation
102
 * @yy: yy component of the affine transformation
103
 * @x0: X translation component of the affine transformation
104
 * @y0: Y translation component of the affine transformation
105
 *
106
 * Sets @matrix to be the affine transformation given by
107
 * @xx, @yx, @xy, @yy, @x0, @y0. The transformation is given
108
 * by:
109
 * 
110
 *  x_new = xx * x + xy * y + x0;
111
 *  y_new = yx * x + yy * y + y0;
112
 * 
3959 Serge 113
 *
114
 * Since: 1.0
1892 serge 115
 **/
116
void
117
cairo_matrix_init (cairo_matrix_t *matrix,
118
		   double xx, double yx,
119
 
120
		   double xy, double yy,
121
		   double x0, double y0)
122
{
123
    matrix->xx = xx; matrix->yx = yx;
124
    matrix->xy = xy; matrix->yy = yy;
125
    matrix->x0 = x0; matrix->y0 = y0;
126
}
127
slim_hidden_def(cairo_matrix_init);
128
 
129
/**
130
 * _cairo_matrix_get_affine:
131
 * @matrix: a #cairo_matrix_t
132
 * @xx: location to store xx component of matrix
133
 * @yx: location to store yx component of matrix
134
 * @xy: location to store xy component of matrix
135
 * @yy: location to store yy component of matrix
136
 * @x0: location to store x0 (X-translation component) of matrix, or %NULL
137
 * @y0: location to store y0 (Y-translation component) of matrix, or %NULL
138
 *
139
 * Gets the matrix values for the affine transformation that @matrix represents.
140
 * See cairo_matrix_init().
141
 *
142
 *
143
 * This function is a leftover from the old public API, but is still
144
 * mildly useful as an internal means for getting at the matrix
145
 * members in a positional way. For example, when reassigning to some
146
 * external matrix type, or when renaming members to more meaningful
147
 * names (such as a,b,c,d,e,f) for particular manipulations.
148
 **/
149
void
150
_cairo_matrix_get_affine (const cairo_matrix_t *matrix,
151
			  double *xx, double *yx,
152
			  double *xy, double *yy,
153
			  double *x0, double *y0)
154
{
155
    *xx  = matrix->xx;
156
    *yx  = matrix->yx;
157
 
158
    *xy  = matrix->xy;
159
    *yy  = matrix->yy;
160
 
161
    if (x0)
162
	*x0 = matrix->x0;
163
    if (y0)
164
	*y0 = matrix->y0;
165
}
166
 
167
/**
168
 * cairo_matrix_init_translate:
169
 * @matrix: a #cairo_matrix_t
170
 * @tx: amount to translate in the X direction
171
 * @ty: amount to translate in the Y direction
172
 *
173
 * Initializes @matrix to a transformation that translates by @tx and
174
 * @ty in the X and Y dimensions, respectively.
3959 Serge 175
 *
176
 * Since: 1.0
1892 serge 177
 **/
178
void
179
cairo_matrix_init_translate (cairo_matrix_t *matrix,
180
			     double tx, double ty)
181
{
182
    cairo_matrix_init (matrix,
183
		       1, 0,
184
		       0, 1,
185
		       tx, ty);
186
}
187
slim_hidden_def(cairo_matrix_init_translate);
188
 
189
/**
190
 * cairo_matrix_translate:
191
 * @matrix: a #cairo_matrix_t
192
 * @tx: amount to translate in the X direction
193
 * @ty: amount to translate in the Y direction
194
 *
195
 * Applies a translation by @tx, @ty to the transformation in
196
 * @matrix. The effect of the new transformation is to first translate
197
 * the coordinates by @tx and @ty, then apply the original transformation
198
 * to the coordinates.
3959 Serge 199
 *
200
 * Since: 1.0
1892 serge 201
 **/
202
void
203
cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
204
{
205
    cairo_matrix_t tmp;
206
 
207
    cairo_matrix_init_translate (&tmp, tx, ty);
208
 
209
    cairo_matrix_multiply (matrix, &tmp, matrix);
210
}
211
slim_hidden_def (cairo_matrix_translate);
212
 
213
/**
214
 * cairo_matrix_init_scale:
215
 * @matrix: a #cairo_matrix_t
216
 * @sx: scale factor in the X direction
217
 * @sy: scale factor in the Y direction
218
 *
219
 * Initializes @matrix to a transformation that scales by @sx and @sy
220
 * in the X and Y dimensions, respectively.
3959 Serge 221
 *
222
 * Since: 1.0
1892 serge 223
 **/
224
void
225
cairo_matrix_init_scale (cairo_matrix_t *matrix,
226
			 double sx, double sy)
227
{
228
    cairo_matrix_init (matrix,
229
		       sx,  0,
230
		       0, sy,
231
		       0, 0);
232
}
233
slim_hidden_def(cairo_matrix_init_scale);
234
 
235
/**
236
 * cairo_matrix_scale:
237
 * @matrix: a #cairo_matrix_t
238
 * @sx: scale factor in the X direction
239
 * @sy: scale factor in the Y direction
240
 *
241
 * Applies scaling by @sx, @sy to the transformation in @matrix. The
242
 * effect of the new transformation is to first scale the coordinates
243
 * by @sx and @sy, then apply the original transformation to the coordinates.
3959 Serge 244
 *
245
 * Since: 1.0
1892 serge 246
 **/
247
void
248
cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
249
{
250
    cairo_matrix_t tmp;
251
 
252
    cairo_matrix_init_scale (&tmp, sx, sy);
253
 
254
    cairo_matrix_multiply (matrix, &tmp, matrix);
255
}
256
slim_hidden_def(cairo_matrix_scale);
257
 
258
/**
259
 * cairo_matrix_init_rotate:
260
 * @matrix: a #cairo_matrix_t
261
 * @radians: angle of rotation, in radians. The direction of rotation
262
 * is defined such that positive angles rotate in the direction from
263
 * the positive X axis toward the positive Y axis. With the default
264
 * axis orientation of cairo, positive angles rotate in a clockwise
265
 * direction.
266
 *
267
 * Initialized @matrix to a transformation that rotates by @radians.
3959 Serge 268
 *
269
 * Since: 1.0
1892 serge 270
 **/
271
void
272
cairo_matrix_init_rotate (cairo_matrix_t *matrix,
273
			  double radians)
274
{
275
    double  s;
276
    double  c;
277
 
278
    s = sin (radians);
279
    c = cos (radians);
280
 
281
    cairo_matrix_init (matrix,
282
		       c, s,
283
		       -s, c,
284
		       0, 0);
285
}
286
slim_hidden_def(cairo_matrix_init_rotate);
287
 
288
/**
289
 * cairo_matrix_rotate:
290
 * @matrix: a #cairo_matrix_t
291
 * @radians: angle of rotation, in radians. The direction of rotation
292
 * is defined such that positive angles rotate in the direction from
293
 * the positive X axis toward the positive Y axis. With the default
294
 * axis orientation of cairo, positive angles rotate in a clockwise
295
 * direction.
296
 *
297
 * Applies rotation by @radians to the transformation in
298
 * @matrix. The effect of the new transformation is to first rotate the
299
 * coordinates by @radians, then apply the original transformation
300
 * to the coordinates.
3959 Serge 301
 *
302
 * Since: 1.0
1892 serge 303
 **/
304
void
305
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
306
{
307
    cairo_matrix_t tmp;
308
 
309
    cairo_matrix_init_rotate (&tmp, radians);
310
 
311
    cairo_matrix_multiply (matrix, &tmp, matrix);
312
}
313
 
314
/**
315
 * cairo_matrix_multiply:
316
 * @result: a #cairo_matrix_t in which to store the result
317
 * @a: a #cairo_matrix_t
318
 * @b: a #cairo_matrix_t
319
 *
320
 * Multiplies the affine transformations in @a and @b together
321
 * and stores the result in @result. The effect of the resulting
322
 * transformation is to first apply the transformation in @a to the
323
 * coordinates and then apply the transformation in @b to the
324
 * coordinates.
325
 *
326
 * It is allowable for @result to be identical to either @a or @b.
3959 Serge 327
 *
328
 * Since: 1.0
1892 serge 329
 **/
330
/*
331
 * XXX: The ordering of the arguments to this function corresponds
332
 *      to [row_vector]*A*B. If we want to use column vectors instead,
333
 *      then we need to switch the two arguments and fix up all
334
 *      uses.
335
 */
336
void
337
cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b)
338
{
339
    cairo_matrix_t r;
340
 
341
    r.xx = a->xx * b->xx + a->yx * b->xy;
342
    r.yx = a->xx * b->yx + a->yx * b->yy;
343
 
344
    r.xy = a->xy * b->xx + a->yy * b->xy;
345
    r.yy = a->xy * b->yx + a->yy * b->yy;
346
 
347
    r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
348
    r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
349
 
350
    *result = r;
351
}
352
slim_hidden_def(cairo_matrix_multiply);
353
 
3959 Serge 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;
367
}
368
 
1892 serge 369
/**
370
 * cairo_matrix_transform_distance:
371
 * @matrix: a #cairo_matrix_t
372
 * @dx: X component of a distance vector. An in/out parameter
373
 * @dy: Y component of a distance vector. An in/out parameter
374
 *
375
 * Transforms the distance vector (@dx,@dy) by @matrix. This is
376
 * similar to cairo_matrix_transform_point() except that the translation
377
 * components of the transformation are ignored. The calculation of
378
 * the returned vector is as follows:
379
 *
380
 * 
381
 * dx2 = dx1 * a + dy1 * c;
382
 * dy2 = dx1 * b + dy1 * d;
383
 * 
384
 *
385
 * Affine transformations are position invariant, so the same vector
386
 * always transforms to the same vector. If (@x1,@y1) transforms
387
 * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
388
 * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
3959 Serge 389
 *
390
 * Since: 1.0
1892 serge 391
 **/
392
void
393
cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy)
394
{
395
    double new_x, new_y;
396
 
397
    new_x = (matrix->xx * *dx + matrix->xy * *dy);
398
    new_y = (matrix->yx * *dx + matrix->yy * *dy);
399
 
400
    *dx = new_x;
401
    *dy = new_y;
402
}
403
slim_hidden_def(cairo_matrix_transform_distance);
404
 
405
/**
406
 * cairo_matrix_transform_point:
407
 * @matrix: a #cairo_matrix_t
408
 * @x: X position. An in/out parameter
409
 * @y: Y position. An in/out parameter
410
 *
411
 * Transforms the point (@x, @y) by @matrix.
3959 Serge 412
 *
413
 * Since: 1.0
1892 serge 414
 **/
415
void
416
cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y)
417
{
418
    cairo_matrix_transform_distance (matrix, x, y);
419
 
420
    *x += matrix->x0;
421
    *y += matrix->y0;
422
}
423
slim_hidden_def(cairo_matrix_transform_point);
424
 
425
void
426
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
427
				      double *x1, double *y1,
428
				      double *x2, double *y2,
429
				      cairo_bool_t *is_tight)
430
{
431
    int i;
432
    double quad_x[4], quad_y[4];
433
    double min_x, max_x;
434
    double min_y, max_y;
435
 
436
    if (matrix->xy == 0. && matrix->yx == 0.) {
437
	/* non-rotation/skew matrix, just map the two extreme points */
438
 
439
	if (matrix->xx != 1.) {
440
	    quad_x[0] = *x1 * matrix->xx;
441
	    quad_x[1] = *x2 * matrix->xx;
442
	    if (quad_x[0] < quad_x[1]) {
443
		*x1 = quad_x[0];
444
		*x2 = quad_x[1];
445
	    } else {
446
		*x1 = quad_x[1];
447
		*x2 = quad_x[0];
448
	    }
449
	}
450
	if (matrix->x0 != 0.) {
451
	    *x1 += matrix->x0;
452
	    *x2 += matrix->x0;
453
	}
454
 
455
	if (matrix->yy != 1.) {
456
	    quad_y[0] = *y1 * matrix->yy;
457
	    quad_y[1] = *y2 * matrix->yy;
458
	    if (quad_y[0] < quad_y[1]) {
459
		*y1 = quad_y[0];
460
		*y2 = quad_y[1];
461
	    } else {
462
		*y1 = quad_y[1];
463
		*y2 = quad_y[0];
464
	    }
465
	}
466
	if (matrix->y0 != 0.) {
467
	    *y1 += matrix->y0;
468
	    *y2 += matrix->y0;
469
	}
470
 
471
	if (is_tight)
472
	    *is_tight = TRUE;
473
 
474
	return;
475
    }
476
 
477
    /* general matrix */
478
    quad_x[0] = *x1;
479
    quad_y[0] = *y1;
480
    cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
481
 
482
    quad_x[1] = *x2;
483
    quad_y[1] = *y1;
484
    cairo_matrix_transform_point (matrix, &quad_x[1], &quad_y[1]);
485
 
486
    quad_x[2] = *x1;
487
    quad_y[2] = *y2;
488
    cairo_matrix_transform_point (matrix, &quad_x[2], &quad_y[2]);
489
 
490
    quad_x[3] = *x2;
491
    quad_y[3] = *y2;
492
    cairo_matrix_transform_point (matrix, &quad_x[3], &quad_y[3]);
493
 
494
    min_x = max_x = quad_x[0];
495
    min_y = max_y = quad_y[0];
496
 
497
    for (i=1; i < 4; i++) {
498
	if (quad_x[i] < min_x)
499
	    min_x = quad_x[i];
500
	if (quad_x[i] > max_x)
501
	    max_x = quad_x[i];
502
 
503
	if (quad_y[i] < min_y)
504
	    min_y = quad_y[i];
505
	if (quad_y[i] > max_y)
506
	    max_y = quad_y[i];
507
    }
508
 
509
    *x1 = min_x;
510
    *y1 = min_y;
511
    *x2 = max_x;
512
    *y2 = max_y;
513
 
514
    if (is_tight) {
515
        /* it's tight if and only if the four corner points form an axis-aligned
516
           rectangle.
517
           And that's true if and only if we can derive corners 0 and 3 from
518
           corners 1 and 2 in one of two straightforward ways...
519
           We could use a tolerance here but for now we'll fall back to FALSE in the case
520
           of floating point error.
521
        */
522
        *is_tight =
523
            (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
524
             quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
525
            (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
526
             quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
527
    }
528
}
529
 
530
cairo_private void
531
_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
532
					    cairo_box_t          *bbox,
533
					    cairo_bool_t *is_tight)
534
{
535
    double x1, y1, x2, y2;
536
 
537
    _cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
538
    _cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
539
    _cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
540
}
541
 
542
static void
543
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
544
{
545
    matrix->xx *= scalar;
546
    matrix->yx *= scalar;
547
 
548
    matrix->xy *= scalar;
549
    matrix->yy *= scalar;
550
 
551
    matrix->x0 *= scalar;
552
    matrix->y0 *= scalar;
553
}
554
 
555
/* This function isn't a correct adjoint in that the implicit 1 in the
556
   homogeneous result should actually be ad-bc instead. But, since this
557
   adjoint is only used in the computation of the inverse, which
558
   divides by det (A)=ad-bc anyway, everything works out in the end. */
559
static void
560
_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
561
{
562
    /* adj (A) = transpose (C:cofactor (A,i,j)) */
563
    double a, b, c, d, tx, ty;
564
 
565
    _cairo_matrix_get_affine (matrix,
566
			      &a,  &b,
567
			      &c,  &d,
568
			      &tx, &ty);
569
 
570
    cairo_matrix_init (matrix,
571
		       d, -b,
572
		       -c, a,
573
		       c*ty - d*tx, b*tx - a*ty);
574
}
575
 
576
/**
577
 * cairo_matrix_invert:
578
 * @matrix: a #cairo_matrix_t
579
 *
580
 * Changes @matrix to be the inverse of its original value. Not
581
 * all transformation matrices have inverses; if the matrix
582
 * collapses points together (it is degenerate),
583
 * then it has no inverse and this function will fail.
584
 *
585
 * Returns: If @matrix has an inverse, modifies @matrix to
586
 *  be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise,
587
 *  returns %CAIRO_STATUS_INVALID_MATRIX.
3959 Serge 588
 *
589
 * Since: 1.0
1892 serge 590
 **/
591
cairo_status_t
592
cairo_matrix_invert (cairo_matrix_t *matrix)
593
{
594
    double det;
595
 
596
    /* Simple scaling|translation matrices are quite common... */
597
    if (matrix->xy == 0. && matrix->yx == 0.) {
598
	matrix->x0 = -matrix->x0;
599
	matrix->y0 = -matrix->y0;
600
 
601
	if (matrix->xx != 1.) {
602
	    if (matrix->xx == 0.)
603
		return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
604
 
605
	    matrix->xx = 1. / matrix->xx;
606
	    matrix->x0 *= matrix->xx;
607
	}
608
 
609
	if (matrix->yy != 1.) {
610
	    if (matrix->yy == 0.)
611
		return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
612
 
613
	    matrix->yy = 1. / matrix->yy;
614
	    matrix->y0 *= matrix->yy;
615
	}
616
 
617
	return CAIRO_STATUS_SUCCESS;
618
    }
619
 
620
    /* inv (A) = 1/det (A) * adj (A) */
621
    det = _cairo_matrix_compute_determinant (matrix);
622
 
623
    if (! ISFINITE (det))
624
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
625
 
626
    if (det == 0)
627
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
628
 
629
    _cairo_matrix_compute_adjoint (matrix);
630
    _cairo_matrix_scalar_multiply (matrix, 1 / det);
631
 
632
    return CAIRO_STATUS_SUCCESS;
633
}
634
slim_hidden_def(cairo_matrix_invert);
635
 
636
cairo_bool_t
637
_cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
638
{
639
    double det;
640
 
641
    det = _cairo_matrix_compute_determinant (matrix);
642
 
643
    return ISFINITE (det) && det != 0.;
644
}
645
 
646
cairo_bool_t
647
_cairo_matrix_is_scale_0 (const cairo_matrix_t *matrix)
648
{
649
    return matrix->xx == 0. &&
650
           matrix->xy == 0. &&
651
           matrix->yx == 0. &&
652
           matrix->yy == 0.;
653
}
654
 
655
double
656
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix)
657
{
658
    double a, b, c, d;
659
 
660
    a = matrix->xx; b = matrix->yx;
661
    c = matrix->xy; d = matrix->yy;
662
 
663
    return a*d - b*c;
664
}
665
 
666
/**
667
 * _cairo_matrix_compute_basis_scale_factors:
668
 * @matrix: a matrix
669
 * @basis_scale: the scale factor in the direction of basis
670
 * @normal_scale: the scale factor in the direction normal to the basis
671
 * @x_basis: basis to use.  X basis if true, Y basis otherwise.
672
 *
673
 * Computes |Mv| and det(M)/|Mv| for v=[1,0] if x_basis is true, and v=[0,1]
674
 * otherwise, and M is @matrix.
675
 *
676
 * Return value: the scale factor of @matrix on the height of the font,
677
 * or 1.0 if @matrix is %NULL.
678
 **/
679
cairo_status_t
680
_cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix,
681
					   double *basis_scale, double *normal_scale,
682
					   cairo_bool_t x_basis)
683
{
684
    double det;
685
 
686
    det = _cairo_matrix_compute_determinant (matrix);
687
 
688
    if (! ISFINITE (det))
689
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
690
 
691
    if (det == 0)
692
    {
693
	*basis_scale = *normal_scale = 0;
694
    }
695
    else
696
    {
697
	double x = x_basis != 0;
698
	double y = x == 0;
699
	double major, minor;
700
 
701
	cairo_matrix_transform_distance (matrix, &x, &y);
702
	major = hypot (x, y);
703
	/*
704
	 * ignore mirroring
705
	 */
706
	if (det < 0)
707
	    det = -det;
708
	if (major)
709
	    minor = det / major;
710
	else
711
	    minor = 0.0;
712
	if (x_basis)
713
	{
714
	    *basis_scale = major;
715
	    *normal_scale = minor;
716
	}
717
	else
718
	{
719
	    *basis_scale = minor;
720
	    *normal_scale = major;
721
	}
722
    }
723
 
724
    return CAIRO_STATUS_SUCCESS;
725
}
726
 
727
cairo_bool_t
728
_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
729
				      int *itx, int *ity)
730
{
731
    if (_cairo_matrix_is_translation (matrix))
732
    {
733
        cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0);
734
        cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0);
735
 
736
        if (_cairo_fixed_is_integer (x0_fixed) &&
737
            _cairo_fixed_is_integer (y0_fixed))
738
        {
739
            if (itx)
740
                *itx = _cairo_fixed_integer_part (x0_fixed);
741
            if (ity)
742
                *ity = _cairo_fixed_integer_part (y0_fixed);
743
 
744
            return TRUE;
745
        }
746
    }
747
 
748
    return FALSE;
749
}
750
 
751
cairo_bool_t
752
_cairo_matrix_has_unity_scale (const cairo_matrix_t *matrix)
753
{
754
    if (matrix->xy == 0.0 && matrix->yx == 0.0) {
755
	if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
756
	    return FALSE;
757
	if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
758
	    return FALSE;
759
    } else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
760
	if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
761
	    return FALSE;
762
	if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
763
	    return FALSE;
764
    } else
765
	return FALSE;
766
 
767
    return TRUE;
768
}
769
 
770
/* By pixel exact here, we mean a matrix that is composed only of
771
 * 90 degree rotations, flips, and integer translations and produces a 1:1
772
 * mapping between source and destination pixels. If we transform an image
773
 * with a pixel-exact matrix, filtering is not useful.
774
 */
775
cairo_bool_t
776
_cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
777
{
778
    cairo_fixed_t x0_fixed, y0_fixed;
779
 
780
    if (! _cairo_matrix_has_unity_scale (matrix))
781
	return FALSE;
782
 
783
    x0_fixed = _cairo_fixed_from_double (matrix->x0);
784
    y0_fixed = _cairo_fixed_from_double (matrix->y0);
785
 
786
    return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
787
}
788
 
789
/*
790
  A circle in user space is transformed into an ellipse in device space.
791
 
792
  The following is a derivation of a formula to calculate the length of the
793
  major axis for this ellipse; this is useful for error bounds calculations.
794
 
795
  Thanks to Walter Brisken  for this derivation:
796
 
797
  1.  First some notation:
798
 
799
  All capital letters represent vectors in two dimensions.  A prime '
800
  represents a transformed coordinate.  Matrices are written in underlined
801
  form, ie _R_.  Lowercase letters represent scalar real values.
802
 
803
  2.  The question has been posed:  What is the maximum expansion factor
804
  achieved by the linear transformation
805
 
806
  X' = X _R_
807
 
808
  where _R_ is a real-valued 2x2 matrix with entries:
809
 
810
  _R_ = [a b]
811
        [c d]  .
812
 
813
  In other words, what is the maximum radius, MAX[ |X'| ], reached for any
814
  X on the unit circle ( |X| = 1 ) ?
815
 
816
  3.  Some useful formulae
817
 
818
  (A) through (C) below are standard double-angle formulae.  (D) is a lesser
819
  known result and is derived below:
820
 
821
  (A)  sin²(θ) = (1 - cos(2*θ))/2
822
  (B)  cos²(θ) = (1 + cos(2*θ))/2
823
  (C)  sin(θ)*cos(θ) = sin(2*θ)/2
824
  (D)  MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²)
825
 
826
  Proof of (D):
827
 
828
  find the maximum of the function by setting the derivative to zero:
829
 
830
       -a*sin(θ)+b*cos(θ) = 0
831
 
832
  From this it follows that
833
 
834
       tan(θ) = b/a
835
 
836
  and hence
837
 
838
       sin(θ) = b/sqrt(a² + b²)
839
 
840
  and
841
 
842
       cos(θ) = a/sqrt(a² + b²)
843
 
844
  Thus the maximum value is
845
 
846
       MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²)
847
                                   = sqrt(a² + b²)
848
 
849
  4.  Derivation of maximum expansion
850
 
851
  To find MAX[ |X'| ] we search brute force method using calculus.  The unit
852
  circle on which X is constrained is to be parameterized by t:
853
 
854
       X(θ) = (cos(θ), sin(θ))
855
 
856
  Thus
857
 
858
       X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b]
859
                                               [c d]
860
             = (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)).
861
 
862
  Define
863
 
864
       r(θ) = |X'(θ)|
865
 
866
  Thus
867
 
868
       r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))²
869
             = (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ)
870
                 + 2*(a*c + b*d)*cos(θ)*sin(θ)
871
 
872
  Now apply the double angle formulae (A) to (C) from above:
873
 
874
       r²(θ) = (a² + b² + c² + d²)/2
875
	     + (a² + b² - c² - d²)*cos(2*θ)/2
876
  	     + (a*c + b*d)*sin(2*θ)
877
             = f + g*cos(φ) + h*sin(φ)
878
 
879
  Where
880
 
881
       f = (a² + b² + c² + d²)/2
882
       g = (a² + b² - c² - d²)/2
883
       h = (a*c + d*d)
884
       φ = 2*θ
885
 
886
  It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]).  Here we determine MAX[ r² ]
887
  using (D) from above:
888
 
889
       MAX[ r² ] = f + sqrt(g² + h²)
890
 
891
  And finally
892
 
893
       MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) )
894
 
895
  Which is the solution to this problem.
896
 
897
  Walter Brisken
898
  2004/10/08
899
 
900
  (Note that the minor axis length is at the minimum of the above solution,
901
  which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
902
 
903
 
904
  For another derivation of the same result, using Singular Value Decomposition,
905
  see doc/tutorial/src/singular.c.
906
*/
907
 
908
/* determine the length of the major axis of a circle of the given radius
909
   after applying the transformation matrix. */
910
double
911
_cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
912
					     double radius)
913
{
914
    double  a, b, c, d, f, g, h, i, j;
915
 
3959 Serge 916
    if (_cairo_matrix_has_unity_scale (matrix))
917
	return radius;
918
 
1892 serge 919
    _cairo_matrix_get_affine (matrix,
920
                              &a, &b,
921
                              &c, &d,
922
                              NULL, NULL);
923
 
924
    i = a*a + b*b;
925
    j = c*c + d*d;
926
 
927
    f = 0.5 * (i + j);
928
    g = 0.5 * (i - j);
929
    h = a*c + b*d;
930
 
931
    return radius * sqrt (f + hypot (g, h));
932
 
933
    /*
934
     * we don't need the minor axis length, which is
935
     * double min = radius * sqrt (f - sqrt (g*g+h*h));
936
     */
937
}
938
 
3959 Serge 939
static const pixman_transform_t pixman_identity_transform = {{
940
        {1 << 16,        0,       0},
941
        {       0, 1 << 16,       0},
942
        {       0,       0, 1 << 16}
943
    }};
944
 
945
static cairo_status_t
1892 serge 946
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
947
				pixman_transform_t	*pixman_transform,
948
				double xc,
949
				double yc)
950
{
3959 Serge 951
    cairo_matrix_t inv;
952
    unsigned max_iterations;
1892 serge 953
 
3959 Serge 954
    pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
955
    pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
956
    pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
1892 serge 957
 
3959 Serge 958
    pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
959
    pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
960
    pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
1892 serge 961
 
3959 Serge 962
    pixman_transform->matrix[2][0] = 0;
963
    pixman_transform->matrix[2][1] = 0;
964
    pixman_transform->matrix[2][2] = 1 << 16;
1892 serge 965
 
3959 Serge 966
    /* The conversion above breaks cairo's translation invariance:
967
     * a translation of (a, b) in device space translates to
968
     * a translation of (xx * a + xy * b, yx * a + yy * b)
969
     * for cairo, while pixman uses rounded versions of xx ... yy.
970
     * This error increases as a and b get larger.
971
     *
972
     * To compensate for this, we fix the point (xc, yc) in pattern
973
     * space and adjust pixman's transform to agree with cairo's at
974
     * that point.
975
     */
1892 serge 976
 
3959 Serge 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 ||
985
		  fabs (matrix->y0) > PIXMAN_MAX_INT))
986
    {
987
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
988
    }
989
 
990
    /* Note: If we can't invert the transformation, skip the adjustment. */
991
    inv = *matrix;
992
    if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
993
	return CAIRO_STATUS_SUCCESS;
994
 
995
    /* find the pattern space coordinate that maps to (xc, yc) */
996
    max_iterations = 5;
997
    do {
998
	double x,y;
999
	pixman_vector_t vector;
1000
	cairo_fixed_16_16_t dx, dy;
1001
 
1002
	vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
1003
	vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
1004
	vector.vector[2] = 1 << 16;
1005
 
1006
	/* If we can't transform the reference point, skip the adjustment. */
1007
	if (! pixman_transform_point_3d (pixman_transform, &vector))
1008
	    return CAIRO_STATUS_SUCCESS;
1009
 
1010
	x = pixman_fixed_to_double (vector.vector[0]);
1011
	y = pixman_fixed_to_double (vector.vector[1]);
1012
	cairo_matrix_transform_point (&inv, &x, &y);
1013
 
1014
	/* Ideally, the vector should now be (xc, yc).
1015
	 * We can now compensate for the resulting error.
1892 serge 1016
	 */
3959 Serge 1017
	x -= xc;
1018
	y -= yc;
1019
	cairo_matrix_transform_distance (matrix, &x, &y);
1020
	dx = _cairo_fixed_16_16_from_double (x);
1021
	dy = _cairo_fixed_16_16_from_double (y);
1022
	pixman_transform->matrix[0][2] -= dx;
1023
	pixman_transform->matrix[1][2] -= dy;
1892 serge 1024
 
3959 Serge 1025
	if (dx == 0 && dy == 0)
1026
	    return CAIRO_STATUS_SUCCESS;
1027
    } while (--max_iterations);
1892 serge 1028
 
3959 Serge 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
}
1892 serge 1033
 
3959 Serge 1034
static inline double
1035
_pixman_nearest_sample (double d)
1036
{
1037
    return ceil (d - .5);
1038
}
1892 serge 1039
 
3959 Serge 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;
1892 serge 1069
 
3959 Serge 1070
    if (!_cairo_matrix_is_translation (matrix))
1071
	return FALSE;
1892 serge 1072
 
3959 Serge 1073
    if (matrix->x0 == 0. && matrix->y0 == 0.)
1074
	return TRUE;
1892 serge 1075
 
3959 Serge 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.
1892 serge 1162
	     */
3959 Serge 1163
	    tx = m.x0;
1164
	    ty = m.y0;
1165
	    norm = MAX (fabs (tx), fabs (ty));
1892 serge 1166
 
3959 Serge 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
 
1201
	return _cairo_matrix_to_pixman_matrix (&m, out_transform, xc, yc);
1892 serge 1202
    }
1203
}