1 /* libs/corecg/SkMatrix.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkMatrix.h"
19 #include "Sk64.h"
20 #include "SkFloatBits.h"
21 #include "SkScalarCompare.h"
22 #include "SkString.h"
23
24 #ifdef SK_SCALAR_IS_FLOAT
25 #define kMatrix22Elem SK_Scalar1
26
SkDoubleToFloat(double x)27 static inline float SkDoubleToFloat(double x) {
28 return static_cast<float>(x);
29 }
30 #else
31 #define kMatrix22Elem SK_Fract1
32 #endif
33
34 /* [scale-x skew-x trans-x] [X] [X']
35 [skew-y scale-y trans-y] * [Y] = [Y']
36 [persp-0 persp-1 persp-2] [1] [1 ]
37 */
38
reset()39 void SkMatrix::reset() {
40 fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
41 fMat[kMSkewX] = fMat[kMSkewY] =
42 fMat[kMTransX] = fMat[kMTransY] =
43 fMat[kMPersp0] = fMat[kMPersp1] = 0;
44 fMat[kMPersp2] = kMatrix22Elem;
45
46 this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
47 }
48
49 // this guy aligns with the masks, so we can compute a mask from a varaible 0/1
50 enum {
51 kTranslate_Shift,
52 kScale_Shift,
53 kAffine_Shift,
54 kPerspective_Shift,
55 kRectStaysRect_Shift
56 };
57
58 #ifdef SK_SCALAR_IS_FLOAT
59 static const int32_t kScalar1Int = 0x3f800000;
60 static const int32_t kPersp1Int = 0x3f800000;
61 #else
62 #define scalarAsInt(x) (x)
63 static const int32_t kScalar1Int = (1 << 16);
64 static const int32_t kPersp1Int = (1 << 30);
65 #endif
66
computeTypeMask() const67 uint8_t SkMatrix::computeTypeMask() const {
68 unsigned mask = 0;
69
70 #ifdef SK_SCALAR_SLOW_COMPARES
71 if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
72 SkScalarAs2sCompliment(fMat[kMPersp1]) |
73 (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
74 mask |= kPerspective_Mask;
75 }
76
77 if (SkScalarAs2sCompliment(fMat[kMTransX]) |
78 SkScalarAs2sCompliment(fMat[kMTransY])) {
79 mask |= kTranslate_Mask;
80 }
81 #else
82 // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
83 // is a win, but replacing those below is not. We don't yet understand
84 // that result.
85 if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
86 fMat[kMPersp2] != kMatrix22Elem) {
87 mask |= kPerspective_Mask;
88 }
89
90 if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) {
91 mask |= kTranslate_Mask;
92 }
93 #endif
94
95 int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]);
96 int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]);
97 int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]);
98 int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]);
99
100 if (m01 | m10) {
101 mask |= kAffine_Mask;
102 }
103
104 if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) {
105 mask |= kScale_Mask;
106 }
107
108 if ((mask & kPerspective_Mask) == 0) {
109 // map non-zero to 1
110 m00 = m00 != 0;
111 m01 = m01 != 0;
112 m10 = m10 != 0;
113 m11 = m11 != 0;
114
115 // record if the (p)rimary and (s)econdary diagonals are all 0 or
116 // all non-zero (answer is 0 or 1)
117 int dp0 = (m00 | m11) ^ 1; // true if both are 0
118 int dp1 = m00 & m11; // true if both are 1
119 int ds0 = (m01 | m10) ^ 1; // true if both are 0
120 int ds1 = m01 & m10; // true if both are 1
121
122 // return 1 if primary is 1 and secondary is 0 or
123 // primary is 0 and secondary is 1
124 mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
125 }
126
127 return SkToU8(mask);
128 }
129
130 ///////////////////////////////////////////////////////////////////////////////
131
132 #ifdef SK_SCALAR_IS_FLOAT
133
operator ==(const SkMatrix & a,const SkMatrix & b)134 bool operator==(const SkMatrix& a, const SkMatrix& b) {
135 const SkScalar* SK_RESTRICT ma = a.fMat;
136 const SkScalar* SK_RESTRICT mb = b.fMat;
137
138 return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] &&
139 ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] &&
140 ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
141 }
142
143 #endif
144
145 ///////////////////////////////////////////////////////////////////////////////
146
setTranslate(SkScalar dx,SkScalar dy)147 void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
148 if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
149 fMat[kMTransX] = dx;
150 fMat[kMTransY] = dy;
151
152 fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
153 fMat[kMSkewX] = fMat[kMSkewY] =
154 fMat[kMPersp0] = fMat[kMPersp1] = 0;
155 fMat[kMPersp2] = kMatrix22Elem;
156
157 this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
158 } else {
159 this->reset();
160 }
161 }
162
preTranslate(SkScalar dx,SkScalar dy)163 bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
164 if (this->hasPerspective()) {
165 SkMatrix m;
166 m.setTranslate(dx, dy);
167 return this->preConcat(m);
168 }
169
170 if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
171 fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
172 SkScalarMul(fMat[kMSkewX], dy);
173 fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
174 SkScalarMul(fMat[kMScaleY], dy);
175
176 this->setTypeMask(kUnknown_Mask);
177 }
178 return true;
179 }
180
postTranslate(SkScalar dx,SkScalar dy)181 bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
182 if (this->hasPerspective()) {
183 SkMatrix m;
184 m.setTranslate(dx, dy);
185 return this->postConcat(m);
186 }
187
188 if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
189 fMat[kMTransX] += dx;
190 fMat[kMTransY] += dy;
191 this->setTypeMask(kUnknown_Mask);
192 }
193 return true;
194 }
195
196 ///////////////////////////////////////////////////////////////////////////////
197
setScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)198 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
199 fMat[kMScaleX] = sx;
200 fMat[kMScaleY] = sy;
201 fMat[kMTransX] = px - SkScalarMul(sx, px);
202 fMat[kMTransY] = py - SkScalarMul(sy, py);
203 fMat[kMPersp2] = kMatrix22Elem;
204
205 fMat[kMSkewX] = fMat[kMSkewY] =
206 fMat[kMPersp0] = fMat[kMPersp1] = 0;
207
208 this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
209 }
210
setScale(SkScalar sx,SkScalar sy)211 void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
212 fMat[kMScaleX] = sx;
213 fMat[kMScaleY] = sy;
214 fMat[kMPersp2] = kMatrix22Elem;
215
216 fMat[kMTransX] = fMat[kMTransY] =
217 fMat[kMSkewX] = fMat[kMSkewY] =
218 fMat[kMPersp0] = fMat[kMPersp1] = 0;
219
220 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
221 }
222
preScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)223 bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
224 SkMatrix m;
225 m.setScale(sx, sy, px, py);
226 return this->preConcat(m);
227 }
228
preScale(SkScalar sx,SkScalar sy)229 bool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
230 #ifdef SK_SCALAR_IS_FIXED
231 SkMatrix m;
232 m.setScale(sx, sy);
233 return this->preConcat(m);
234 #else
235 // the assumption is that these multiplies are very cheap, and that
236 // a full concat and/or just computing the matrix type is more expensive.
237 // Also, the fixed-point case checks for overflow, but the float doesn't,
238 // so we can get away with these blind multiplies.
239
240 fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx);
241 fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx);
242 fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx);
243
244 fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy);
245 fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy);
246 fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy);
247
248 this->orTypeMask(kScale_Mask);
249 return true;
250 #endif
251 }
252
postScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)253 bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
254 SkMatrix m;
255 m.setScale(sx, sy, px, py);
256 return this->postConcat(m);
257 }
258
postScale(SkScalar sx,SkScalar sy)259 bool SkMatrix::postScale(SkScalar sx, SkScalar sy) {
260 SkMatrix m;
261 m.setScale(sx, sy);
262 return this->postConcat(m);
263 }
264
265 #ifdef SK_SCALAR_IS_FIXED
roundidiv(SkFixed numer,int denom)266 static inline SkFixed roundidiv(SkFixed numer, int denom) {
267 int ns = numer >> 31;
268 int ds = denom >> 31;
269 numer = (numer ^ ns) - ns;
270 denom = (denom ^ ds) - ds;
271
272 SkFixed answer = (numer + (denom >> 1)) / denom;
273 int as = ns ^ ds;
274 return (answer ^ as) - as;
275 }
276 #endif
277
278 // this guy perhaps can go away, if we have a fract/high-precision way to
279 // scale matrices
postIDiv(int divx,int divy)280 bool SkMatrix::postIDiv(int divx, int divy) {
281 if (divx == 0 || divy == 0) {
282 return false;
283 }
284
285 #ifdef SK_SCALAR_IS_FIXED
286 fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx);
287 fMat[kMSkewX] = roundidiv(fMat[kMSkewX], divx);
288 fMat[kMTransX] = roundidiv(fMat[kMTransX], divx);
289
290 fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy);
291 fMat[kMSkewY] = roundidiv(fMat[kMSkewY], divy);
292 fMat[kMTransY] = roundidiv(fMat[kMTransY], divy);
293 #else
294 const float invX = 1.f / divx;
295 const float invY = 1.f / divy;
296
297 fMat[kMScaleX] *= invX;
298 fMat[kMSkewX] *= invX;
299 fMat[kMTransX] *= invX;
300
301 fMat[kMScaleY] *= invY;
302 fMat[kMSkewY] *= invY;
303 fMat[kMTransY] *= invY;
304 #endif
305
306 this->setTypeMask(kUnknown_Mask);
307 return true;
308 }
309
310 ////////////////////////////////////////////////////////////////////////////////////
311
setSinCos(SkScalar sinV,SkScalar cosV,SkScalar px,SkScalar py)312 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
313 SkScalar px, SkScalar py) {
314 const SkScalar oneMinusCosV = SK_Scalar1 - cosV;
315
316 fMat[kMScaleX] = cosV;
317 fMat[kMSkewX] = -sinV;
318 fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px);
319
320 fMat[kMSkewY] = sinV;
321 fMat[kMScaleY] = cosV;
322 fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py);
323
324 fMat[kMPersp0] = fMat[kMPersp1] = 0;
325 fMat[kMPersp2] = kMatrix22Elem;
326
327 this->setTypeMask(kUnknown_Mask);
328 }
329
setSinCos(SkScalar sinV,SkScalar cosV)330 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
331 fMat[kMScaleX] = cosV;
332 fMat[kMSkewX] = -sinV;
333 fMat[kMTransX] = 0;
334
335 fMat[kMSkewY] = sinV;
336 fMat[kMScaleY] = cosV;
337 fMat[kMTransY] = 0;
338
339 fMat[kMPersp0] = fMat[kMPersp1] = 0;
340 fMat[kMPersp2] = kMatrix22Elem;
341
342 this->setTypeMask(kUnknown_Mask);
343 }
344
setRotate(SkScalar degrees,SkScalar px,SkScalar py)345 void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
346 SkScalar sinV, cosV;
347 sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
348 this->setSinCos(sinV, cosV, px, py);
349 }
350
setRotate(SkScalar degrees)351 void SkMatrix::setRotate(SkScalar degrees) {
352 SkScalar sinV, cosV;
353 sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
354 this->setSinCos(sinV, cosV);
355 }
356
preRotate(SkScalar degrees,SkScalar px,SkScalar py)357 bool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
358 SkMatrix m;
359 m.setRotate(degrees, px, py);
360 return this->preConcat(m);
361 }
362
preRotate(SkScalar degrees)363 bool SkMatrix::preRotate(SkScalar degrees) {
364 SkMatrix m;
365 m.setRotate(degrees);
366 return this->preConcat(m);
367 }
368
postRotate(SkScalar degrees,SkScalar px,SkScalar py)369 bool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
370 SkMatrix m;
371 m.setRotate(degrees, px, py);
372 return this->postConcat(m);
373 }
374
postRotate(SkScalar degrees)375 bool SkMatrix::postRotate(SkScalar degrees) {
376 SkMatrix m;
377 m.setRotate(degrees);
378 return this->postConcat(m);
379 }
380
381 ////////////////////////////////////////////////////////////////////////////////////
382
setSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)383 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
384 fMat[kMScaleX] = SK_Scalar1;
385 fMat[kMSkewX] = sx;
386 fMat[kMTransX] = SkScalarMul(-sx, py);
387
388 fMat[kMSkewY] = sy;
389 fMat[kMScaleY] = SK_Scalar1;
390 fMat[kMTransY] = SkScalarMul(-sy, px);
391
392 fMat[kMPersp0] = fMat[kMPersp1] = 0;
393 fMat[kMPersp2] = kMatrix22Elem;
394
395 this->setTypeMask(kUnknown_Mask);
396 }
397
setSkew(SkScalar sx,SkScalar sy)398 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
399 fMat[kMScaleX] = SK_Scalar1;
400 fMat[kMSkewX] = sx;
401 fMat[kMTransX] = 0;
402
403 fMat[kMSkewY] = sy;
404 fMat[kMScaleY] = SK_Scalar1;
405 fMat[kMTransY] = 0;
406
407 fMat[kMPersp0] = fMat[kMPersp1] = 0;
408 fMat[kMPersp2] = kMatrix22Elem;
409
410 this->setTypeMask(kUnknown_Mask);
411 }
412
preSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)413 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
414 SkMatrix m;
415 m.setSkew(sx, sy, px, py);
416 return this->preConcat(m);
417 }
418
preSkew(SkScalar sx,SkScalar sy)419 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
420 SkMatrix m;
421 m.setSkew(sx, sy);
422 return this->preConcat(m);
423 }
424
postSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)425 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
426 SkMatrix m;
427 m.setSkew(sx, sy, px, py);
428 return this->postConcat(m);
429 }
430
postSkew(SkScalar sx,SkScalar sy)431 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
432 SkMatrix m;
433 m.setSkew(sx, sy);
434 return this->postConcat(m);
435 }
436
437 ///////////////////////////////////////////////////////////////////////////////
438
setRectToRect(const SkRect & src,const SkRect & dst,ScaleToFit align)439 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
440 ScaleToFit align)
441 {
442 if (src.isEmpty()) {
443 this->reset();
444 return false;
445 }
446
447 if (dst.isEmpty()) {
448 sk_bzero(fMat, 8 * sizeof(SkScalar));
449 this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
450 } else {
451 SkScalar tx, sx = SkScalarDiv(dst.width(), src.width());
452 SkScalar ty, sy = SkScalarDiv(dst.height(), src.height());
453 bool xLarger = false;
454
455 if (align != kFill_ScaleToFit) {
456 if (sx > sy) {
457 xLarger = true;
458 sx = sy;
459 } else {
460 sy = sx;
461 }
462 }
463
464 tx = dst.fLeft - SkScalarMul(src.fLeft, sx);
465 ty = dst.fTop - SkScalarMul(src.fTop, sy);
466 if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
467 SkScalar diff;
468
469 if (xLarger) {
470 diff = dst.width() - SkScalarMul(src.width(), sy);
471 } else {
472 diff = dst.height() - SkScalarMul(src.height(), sy);
473 }
474
475 if (align == kCenter_ScaleToFit) {
476 diff = SkScalarHalf(diff);
477 }
478
479 if (xLarger) {
480 tx += diff;
481 } else {
482 ty += diff;
483 }
484 }
485
486 fMat[kMScaleX] = sx;
487 fMat[kMScaleY] = sy;
488 fMat[kMTransX] = tx;
489 fMat[kMTransY] = ty;
490 fMat[kMSkewX] = fMat[kMSkewY] =
491 fMat[kMPersp0] = fMat[kMPersp1] = 0;
492
493 this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
494 }
495 // shared cleanup
496 fMat[kMPersp2] = kMatrix22Elem;
497 return true;
498 }
499
500 ///////////////////////////////////////////////////////////////////////////////
501
502 #ifdef SK_SCALAR_IS_FLOAT
fixmuladdmul(float a,float b,float c,float d,float * result)503 static inline int fixmuladdmul(float a, float b, float c, float d,
504 float* result) {
505 *result = SkDoubleToFloat((double)a * b + (double)c * d);
506 return true;
507 }
508
rowcol3(const float row[],const float col[],float * result)509 static inline bool rowcol3(const float row[], const float col[],
510 float* result) {
511 *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
512 return true;
513 }
514
negifaddoverflows(float & result,float a,float b)515 static inline int negifaddoverflows(float& result, float a, float b) {
516 result = a + b;
517 return 0;
518 }
519 #else
fixmuladdmul(SkFixed a,SkFixed b,SkFixed c,SkFixed d,SkFixed * result)520 static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d,
521 SkFixed* result) {
522 Sk64 tmp1, tmp2;
523 tmp1.setMul(a, b);
524 tmp2.setMul(c, d);
525 tmp1.add(tmp2);
526 if (tmp1.isFixed()) {
527 *result = tmp1.getFixed();
528 return true;
529 }
530 return false;
531 }
532
fracmuladdmul(SkFixed a,SkFract b,SkFixed c,SkFract d)533 static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c,
534 SkFract d) {
535 Sk64 tmp1, tmp2;
536 tmp1.setMul(a, b);
537 tmp2.setMul(c, d);
538 tmp1.add(tmp2);
539 return tmp1.getFract();
540 }
541
rowcol3(const SkFixed row[],const SkFixed col[],SkFixed * result)542 static inline bool rowcol3(const SkFixed row[], const SkFixed col[],
543 SkFixed* result) {
544 Sk64 tmp1, tmp2;
545
546 tmp1.setMul(row[0], col[0]); // N * fixed
547 tmp2.setMul(row[1], col[3]); // N * fixed
548 tmp1.add(tmp2);
549
550 tmp2.setMul(row[2], col[6]); // N * fract
551 tmp2.roundRight(14); // make it fixed
552 tmp1.add(tmp2);
553
554 if (tmp1.isFixed()) {
555 *result = tmp1.getFixed();
556 return true;
557 }
558 return false;
559 }
560
negifaddoverflows(SkFixed & result,SkFixed a,SkFixed b)561 static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) {
562 SkFixed c = a + b;
563 result = c;
564 return (c ^ a) & (c ^ b);
565 }
566 #endif
567
normalize_perspective(SkScalar mat[9])568 static void normalize_perspective(SkScalar mat[9]) {
569 if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) {
570 for (int i = 0; i < 9; i++)
571 mat[i] = SkScalarHalf(mat[i]);
572 }
573 }
574
setConcat(const SkMatrix & a,const SkMatrix & b)575 bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
576 TypeMask aType = a.getType();
577 TypeMask bType = b.getType();
578
579 if (0 == aType) {
580 *this = b;
581 } else if (0 == bType) {
582 *this = a;
583 } else {
584 SkMatrix tmp;
585
586 if ((aType | bType) & kPerspective_Mask) {
587 if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) {
588 return false;
589 }
590 if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) {
591 return false;
592 }
593 if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) {
594 return false;
595 }
596
597 if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) {
598 return false;
599 }
600 if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) {
601 return false;
602 }
603 if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) {
604 return false;
605 }
606
607 if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) {
608 return false;
609 }
610 if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) {
611 return false;
612 }
613 if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) {
614 return false;
615 }
616
617 normalize_perspective(tmp.fMat);
618 } else { // not perspective
619 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX],
620 a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) {
621 return false;
622 }
623 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX],
624 a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) {
625 return false;
626 }
627 if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX],
628 a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) {
629 return false;
630 }
631 if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX],
632 a.fMat[kMTransX]) < 0) {
633 return false;
634 }
635
636 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX],
637 a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) {
638 return false;
639 }
640 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX],
641 a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) {
642 return false;
643 }
644 if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX],
645 a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) {
646 return false;
647 }
648 if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY],
649 a.fMat[kMTransY]) < 0) {
650 return false;
651 }
652
653 tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
654 tmp.fMat[kMPersp2] = kMatrix22Elem;
655 }
656 *this = tmp;
657 }
658 this->setTypeMask(kUnknown_Mask);
659 return true;
660 }
661
preConcat(const SkMatrix & mat)662 bool SkMatrix::preConcat(const SkMatrix& mat) {
663 // check for identity first, so we don't do a needless copy of ourselves
664 // to ourselves inside setConcat()
665 return mat.isIdentity() || this->setConcat(*this, mat);
666 }
667
postConcat(const SkMatrix & mat)668 bool SkMatrix::postConcat(const SkMatrix& mat) {
669 // check for identity first, so we don't do a needless copy of ourselves
670 // to ourselves inside setConcat()
671 return mat.isIdentity() || this->setConcat(mat, *this);
672 }
673
674 ///////////////////////////////////////////////////////////////////////////////
675
676 /* Matrix inversion is very expensive, but also the place where keeping
677 precision may be most important (here and matrix concat). Hence to avoid
678 bitmap blitting artifacts when walking the inverse, we use doubles for
679 the intermediate math, even though we know that is more expensive.
680 The fixed counter part is us using Sk64 for temp calculations.
681 */
682
683 #ifdef SK_SCALAR_IS_FLOAT
684 typedef double SkDetScalar;
685 #define SkPerspMul(a, b) SkScalarMul(a, b)
686 #define SkScalarMulShift(a, b, s) SkDoubleToFloat((a) * (b))
sk_inv_determinant(const float mat[9],int isPerspective,int *)687 static double sk_inv_determinant(const float mat[9], int isPerspective,
688 int* /* (only used in Fixed case) */) {
689 double det;
690
691 if (isPerspective) {
692 det = mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) +
693 mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) +
694 mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]);
695 } else {
696 det = (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY];
697 }
698
699 // Since the determinant is on the order of the cube of the matrix members,
700 // compare to the cube of the default nearly-zero constant (although an
701 // estimate of the condition number would be better if it wasn't so expensive).
702 if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
703 return 0;
704 }
705 return 1.0 / det;
706 }
707 // we declar a,b,c,d to all be doubles, because we want to perform
708 // double-precision muls and subtract, even though the original values are
709 // from the matrix, which are floats.
mul_diff_scale(double a,double b,double c,double d,double scale)710 static float inline mul_diff_scale(double a, double b, double c, double d,
711 double scale) {
712 return SkDoubleToFloat((a * b - c * d) * scale);
713 }
714 #else
715 typedef SkFixed SkDetScalar;
716 #define SkPerspMul(a, b) SkFractMul(a, b)
717 #define SkScalarMulShift(a, b, s) SkMulShift(a, b, s)
set_muladdmul(Sk64 * dst,int32_t a,int32_t b,int32_t c,int32_t d)718 static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c,
719 int32_t d) {
720 Sk64 tmp;
721 dst->setMul(a, b);
722 tmp.setMul(c, d);
723 dst->add(tmp);
724 }
725
sk_inv_determinant(const SkFixed mat[9],int isPerspective,int * shift)726 static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective,
727 int* shift) {
728 Sk64 tmp1, tmp2;
729
730 if (isPerspective) {
731 tmp1.setMul(mat[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]));
732 tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]));
733 tmp1.add(tmp2);
734 tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]));
735 tmp1.add(tmp2);
736 } else {
737 tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]);
738 tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
739 tmp1.sub(tmp2);
740 }
741
742 int s = tmp1.getClzAbs();
743 *shift = s;
744
745 SkFixed denom;
746 if (s <= 32) {
747 denom = tmp1.getShiftRight(33 - s);
748 } else {
749 denom = (int32_t)tmp1.fLo << (s - 33);
750 }
751
752 if (denom == 0) {
753 return 0;
754 }
755 /** This could perhaps be a special fractdiv function, since both of its
756 arguments are known to have bit 31 clear and bit 30 set (when they
757 are made positive), thus eliminating the need for calling clz()
758 */
759 return SkFractDiv(SK_Fract1, denom);
760 }
761 #endif
762
pdfTransform(SkScalar transform[6]) const763 bool SkMatrix::pdfTransform(SkScalar transform[6]) const {
764 SkMatrix identity;
765 const SkMatrix* use = this;
766 bool ret = true;
767 if (this->hasPerspective()) {
768 identity.reset();
769 use = &identity;
770 ret = false;
771 }
772 transform[0] = use->fMat[kMScaleX];
773 transform[1] = use->fMat[kMSkewY];
774 transform[2] = use->fMat[kMSkewX];
775 transform[3] = use->fMat[kMScaleY];
776 transform[4] = use->fMat[kMTransX];
777 transform[5] = use->fMat[kMTransY];
778 return true;
779 }
780
invert(SkMatrix * inv) const781 bool SkMatrix::invert(SkMatrix* inv) const {
782 int isPersp = this->hasPerspective();
783 int shift;
784 SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift);
785
786 if (scale == 0) { // underflow
787 return false;
788 }
789
790 if (inv) {
791 SkMatrix tmp;
792 if (inv == this)
793 inv = &tmp;
794
795 if (isPersp) {
796 shift = 61 - shift;
797 inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift);
798 inv->fMat[kMSkewX] = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX], fMat[kMPersp2]), scale, shift);
799 inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift);
800
801 inv->fMat[kMSkewY] = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY], fMat[kMPersp2]), scale, shift);
802 inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX], fMat[kMPersp0]), scale, shift);
803 inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift);
804
805 inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift);
806 inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift);
807 inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift);
808 #ifdef SK_SCALAR_IS_FIXED
809 if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) {
810 Sk64 tmp;
811
812 tmp.set(SK_Fract1);
813 tmp.shiftLeft(16);
814 tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption);
815
816 SkFract scale = tmp.get32();
817
818 for (int i = 0; i < 9; i++) {
819 inv->fMat[i] = SkFractMul(inv->fMat[i], scale);
820 }
821 }
822 inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]);
823 #endif
824 } else { // not perspective
825 #ifdef SK_SCALAR_IS_FIXED
826 Sk64 tx, ty;
827 int clzNumer;
828
829 // check the 2x2 for overflow
830 {
831 int32_t value = SkAbs32(fMat[kMScaleY]);
832 value |= SkAbs32(fMat[kMSkewX]);
833 value |= SkAbs32(fMat[kMScaleX]);
834 value |= SkAbs32(fMat[kMSkewY]);
835 clzNumer = SkCLZ(value);
836 if (shift - clzNumer > 31)
837 return false; // overflow
838 }
839
840 set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]);
841 set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]);
842 // check tx,ty for overflow
843 clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi));
844 if (shift - clzNumer > 14) {
845 return false; // overflow
846 }
847
848 int fixedShift = 61 - shift;
849 int sk64shift = 44 - shift + clzNumer;
850
851 inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift);
852 inv->fMat[kMSkewX] = SkMulShift(-fMat[kMSkewX], scale, fixedShift);
853 inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift);
854
855 inv->fMat[kMSkewY] = SkMulShift(-fMat[kMSkewY], scale, fixedShift);
856 inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift);
857 inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift);
858 #else
859 inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale);
860 inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale);
861 inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY],
862 fMat[kMScaleY], fMat[kMTransX], scale);
863
864 inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale);
865 inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale);
866 inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX],
867 fMat[kMScaleX], fMat[kMTransY], scale);
868 #endif
869 inv->fMat[kMPersp0] = 0;
870 inv->fMat[kMPersp1] = 0;
871 inv->fMat[kMPersp2] = kMatrix22Elem;
872 }
873
874 if (inv == &tmp) {
875 *(SkMatrix*)this = tmp;
876 }
877 inv->setTypeMask(kUnknown_Mask);
878 }
879 return true;
880 }
881
882 ///////////////////////////////////////////////////////////////////////////////
883
Identity_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)884 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[],
885 const SkPoint src[], int count) {
886 SkASSERT(m.getType() == 0);
887
888 if (dst != src && count > 0)
889 memcpy(dst, src, count * sizeof(SkPoint));
890 }
891
Trans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)892 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[],
893 const SkPoint src[], int count) {
894 SkASSERT(m.getType() == kTranslate_Mask);
895
896 if (count > 0) {
897 SkScalar tx = m.fMat[kMTransX];
898 SkScalar ty = m.fMat[kMTransY];
899 do {
900 dst->fY = src->fY + ty;
901 dst->fX = src->fX + tx;
902 src += 1;
903 dst += 1;
904 } while (--count);
905 }
906 }
907
Scale_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)908 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
909 const SkPoint src[], int count) {
910 SkASSERT(m.getType() == kScale_Mask);
911
912 if (count > 0) {
913 SkScalar mx = m.fMat[kMScaleX];
914 SkScalar my = m.fMat[kMScaleY];
915 do {
916 dst->fY = SkScalarMul(src->fY, my);
917 dst->fX = SkScalarMul(src->fX, mx);
918 src += 1;
919 dst += 1;
920 } while (--count);
921 }
922 }
923
ScaleTrans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)924 void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
925 const SkPoint src[], int count) {
926 SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask));
927
928 if (count > 0) {
929 SkScalar mx = m.fMat[kMScaleX];
930 SkScalar my = m.fMat[kMScaleY];
931 SkScalar tx = m.fMat[kMTransX];
932 SkScalar ty = m.fMat[kMTransY];
933 do {
934 dst->fY = SkScalarMulAdd(src->fY, my, ty);
935 dst->fX = SkScalarMulAdd(src->fX, mx, tx);
936 src += 1;
937 dst += 1;
938 } while (--count);
939 }
940 }
941
Rot_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)942 void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
943 const SkPoint src[], int count) {
944 SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0);
945
946 if (count > 0) {
947 SkScalar mx = m.fMat[kMScaleX];
948 SkScalar my = m.fMat[kMScaleY];
949 SkScalar kx = m.fMat[kMSkewX];
950 SkScalar ky = m.fMat[kMSkewY];
951 do {
952 SkScalar sy = src->fY;
953 SkScalar sx = src->fX;
954 src += 1;
955 dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my);
956 dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx);
957 dst += 1;
958 } while (--count);
959 }
960 }
961
RotTrans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)962 void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
963 const SkPoint src[], int count) {
964 SkASSERT(!m.hasPerspective());
965
966 if (count > 0) {
967 SkScalar mx = m.fMat[kMScaleX];
968 SkScalar my = m.fMat[kMScaleY];
969 SkScalar kx = m.fMat[kMSkewX];
970 SkScalar ky = m.fMat[kMSkewY];
971 SkScalar tx = m.fMat[kMTransX];
972 SkScalar ty = m.fMat[kMTransY];
973 do {
974 SkScalar sy = src->fY;
975 SkScalar sx = src->fX;
976 src += 1;
977 dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty);
978 dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx);
979 dst += 1;
980 } while (--count);
981 }
982 }
983
Persp_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)984 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
985 const SkPoint src[], int count) {
986 SkASSERT(m.hasPerspective());
987
988 #ifdef SK_SCALAR_IS_FIXED
989 SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]);
990 #endif
991
992 if (count > 0) {
993 do {
994 SkScalar sy = src->fY;
995 SkScalar sx = src->fX;
996 src += 1;
997
998 SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
999 SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
1000 SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
1001 SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1002 #ifdef SK_SCALAR_IS_FIXED
1003 SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
1004 SkFractMul(sy, m.fMat[kMPersp1]) + persp2;
1005 #else
1006 float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
1007 SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]);
1008 #endif
1009 if (z) {
1010 z = SkScalarFastInvert(z);
1011 }
1012
1013 dst->fY = SkScalarMul(y, z);
1014 dst->fX = SkScalarMul(x, z);
1015 dst += 1;
1016 } while (--count);
1017 }
1018 }
1019
1020 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
1021 SkMatrix::Identity_pts, SkMatrix::Trans_pts,
1022 SkMatrix::Scale_pts, SkMatrix::ScaleTrans_pts,
1023 SkMatrix::Rot_pts, SkMatrix::RotTrans_pts,
1024 SkMatrix::Rot_pts, SkMatrix::RotTrans_pts,
1025 // repeat the persp proc 8 times
1026 SkMatrix::Persp_pts, SkMatrix::Persp_pts,
1027 SkMatrix::Persp_pts, SkMatrix::Persp_pts,
1028 SkMatrix::Persp_pts, SkMatrix::Persp_pts,
1029 SkMatrix::Persp_pts, SkMatrix::Persp_pts
1030 };
1031
mapPoints(SkPoint dst[],const SkPoint src[],int count) const1032 void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
1033 SkASSERT((dst && src && count > 0) || count == 0);
1034 // no partial overlap
1035 SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count);
1036
1037 this->getMapPtsProc()(*this, dst, src, count);
1038 }
1039
1040 ///////////////////////////////////////////////////////////////////////////////
1041
mapVectors(SkPoint dst[],const SkPoint src[],int count) const1042 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
1043 if (this->hasPerspective()) {
1044 SkPoint origin;
1045
1046 MapXYProc proc = this->getMapXYProc();
1047 proc(*this, 0, 0, &origin);
1048
1049 for (int i = count - 1; i >= 0; --i) {
1050 SkPoint tmp;
1051
1052 proc(*this, src[i].fX, src[i].fY, &tmp);
1053 dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
1054 }
1055 } else {
1056 SkMatrix tmp = *this;
1057
1058 tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
1059 tmp.clearTypeMask(kTranslate_Mask);
1060 tmp.mapPoints(dst, src, count);
1061 }
1062 }
1063
mapRect(SkRect * dst,const SkRect & src) const1064 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
1065 SkASSERT(dst && &src);
1066
1067 if (this->rectStaysRect()) {
1068 this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
1069 dst->sort();
1070 return true;
1071 } else {
1072 SkPoint quad[4];
1073
1074 src.toQuad(quad);
1075 this->mapPoints(quad, quad, 4);
1076 dst->set(quad, 4);
1077 return false;
1078 }
1079 }
1080
mapRadius(SkScalar radius) const1081 SkScalar SkMatrix::mapRadius(SkScalar radius) const {
1082 SkVector vec[2];
1083
1084 vec[0].set(radius, 0);
1085 vec[1].set(0, radius);
1086 this->mapVectors(vec, 2);
1087
1088 SkScalar d0 = vec[0].length();
1089 SkScalar d1 = vec[1].length();
1090
1091 return SkScalarMean(d0, d1);
1092 }
1093
1094 ///////////////////////////////////////////////////////////////////////////////
1095
Persp_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1096 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1097 SkPoint* pt) {
1098 SkASSERT(m.hasPerspective());
1099
1100 SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
1101 SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
1102 SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
1103 SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1104 #ifdef SK_SCALAR_IS_FIXED
1105 SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
1106 SkFractMul(sy, m.fMat[kMPersp1]) +
1107 SkFractToFixed(m.fMat[kMPersp2]);
1108 #else
1109 float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
1110 SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
1111 #endif
1112 if (z) {
1113 z = SkScalarFastInvert(z);
1114 }
1115 pt->fX = SkScalarMul(x, z);
1116 pt->fY = SkScalarMul(y, z);
1117 }
1118
1119 #ifdef SK_SCALAR_IS_FIXED
fixmuladdmul(SkFixed a,SkFixed b,SkFixed c,SkFixed d)1120 static SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) {
1121 Sk64 tmp, tmp1;
1122
1123 tmp.setMul(a, b);
1124 tmp1.setMul(c, d);
1125 return tmp.addGetFixed(tmp1);
1126 // tmp.add(tmp1);
1127 // return tmp.getFixed();
1128 }
1129 #endif
1130
RotTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1131 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1132 SkPoint* pt) {
1133 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
1134
1135 #ifdef SK_SCALAR_IS_FIXED
1136 pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) +
1137 m.fMat[kMTransX];
1138 pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) +
1139 m.fMat[kMTransY];
1140 #else
1141 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
1142 SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
1143 pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
1144 SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1145 #endif
1146 }
1147
Rot_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1148 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1149 SkPoint* pt) {
1150 SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
1151 SkASSERT(0 == m.fMat[kMTransX]);
1152 SkASSERT(0 == m.fMat[kMTransY]);
1153
1154 #ifdef SK_SCALAR_IS_FIXED
1155 pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]);
1156 pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]);
1157 #else
1158 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
1159 SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
1160 pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
1161 SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1162 #endif
1163 }
1164
ScaleTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1165 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1166 SkPoint* pt) {
1167 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1168 == kScale_Mask);
1169
1170 pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]);
1171 pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1172 }
1173
Scale_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1174 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1175 SkPoint* pt) {
1176 SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1177 == kScale_Mask);
1178 SkASSERT(0 == m.fMat[kMTransX]);
1179 SkASSERT(0 == m.fMat[kMTransY]);
1180
1181 pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]);
1182 pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]);
1183 }
1184
Trans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1185 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1186 SkPoint* pt) {
1187 SkASSERT(m.getType() == kTranslate_Mask);
1188
1189 pt->fX = sx + m.fMat[kMTransX];
1190 pt->fY = sy + m.fMat[kMTransY];
1191 }
1192
Identity_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1193 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1194 SkPoint* pt) {
1195 SkASSERT(0 == m.getType());
1196
1197 pt->fX = sx;
1198 pt->fY = sy;
1199 }
1200
1201 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
1202 SkMatrix::Identity_xy, SkMatrix::Trans_xy,
1203 SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy,
1204 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy,
1205 SkMatrix::Rot_xy, SkMatrix::RotTrans_xy,
1206 // repeat the persp proc 8 times
1207 SkMatrix::Persp_xy, SkMatrix::Persp_xy,
1208 SkMatrix::Persp_xy, SkMatrix::Persp_xy,
1209 SkMatrix::Persp_xy, SkMatrix::Persp_xy,
1210 SkMatrix::Persp_xy, SkMatrix::Persp_xy
1211 };
1212
1213 ///////////////////////////////////////////////////////////////////////////////
1214
1215 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
1216 #ifdef SK_SCALAR_IS_FIXED
1217 typedef SkFract SkPerspElemType;
1218 #define PerspNearlyZero(x) (SkAbs32(x) < (SK_Fract1 >> 26))
1219 #else
1220 typedef float SkPerspElemType;
1221 #define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26)))
1222 #endif
1223
fixedStepInX(SkScalar y,SkFixed * stepX,SkFixed * stepY) const1224 bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
1225 if (PerspNearlyZero(fMat[kMPersp0])) {
1226 if (stepX || stepY) {
1227 if (PerspNearlyZero(fMat[kMPersp1]) &&
1228 PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) {
1229 if (stepX) {
1230 *stepX = SkScalarToFixed(fMat[kMScaleX]);
1231 }
1232 if (stepY) {
1233 *stepY = SkScalarToFixed(fMat[kMSkewY]);
1234 }
1235 } else {
1236 #ifdef SK_SCALAR_IS_FIXED
1237 SkFixed z = SkFractMul(y, fMat[kMPersp1]) +
1238 SkFractToFixed(fMat[kMPersp2]);
1239 #else
1240 float z = y * fMat[kMPersp1] + fMat[kMPersp2];
1241 #endif
1242 if (stepX) {
1243 *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z));
1244 }
1245 if (stepY) {
1246 *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z));
1247 }
1248 }
1249 }
1250 return true;
1251 }
1252 return false;
1253 }
1254
1255 ///////////////////////////////////////////////////////////////////////////////
1256
1257 #include "SkPerspIter.h"
1258
SkPerspIter(const SkMatrix & m,SkScalar x0,SkScalar y0,int count)1259 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
1260 : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
1261 SkPoint pt;
1262
1263 SkMatrix::Persp_xy(m, x0, y0, &pt);
1264 fX = SkScalarToFixed(pt.fX);
1265 fY = SkScalarToFixed(pt.fY);
1266 }
1267
next()1268 int SkPerspIter::next() {
1269 int n = fCount;
1270
1271 if (0 == n) {
1272 return 0;
1273 }
1274 SkPoint pt;
1275 SkFixed x = fX;
1276 SkFixed y = fY;
1277 SkFixed dx, dy;
1278
1279 if (n >= kCount) {
1280 n = kCount;
1281 fSX += SkIntToScalar(kCount);
1282 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1283 fX = SkScalarToFixed(pt.fX);
1284 fY = SkScalarToFixed(pt.fY);
1285 dx = (fX - x) >> kShift;
1286 dy = (fY - y) >> kShift;
1287 } else {
1288 fSX += SkIntToScalar(n);
1289 SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1290 fX = SkScalarToFixed(pt.fX);
1291 fY = SkScalarToFixed(pt.fY);
1292 dx = (fX - x) / n;
1293 dy = (fY - y) / n;
1294 }
1295
1296 SkFixed* p = fStorage;
1297 for (int i = 0; i < n; i++) {
1298 *p++ = x; x += dx;
1299 *p++ = y; y += dy;
1300 }
1301
1302 fCount -= n;
1303 return n;
1304 }
1305
1306 ///////////////////////////////////////////////////////////////////////////////
1307
1308 #ifdef SK_SCALAR_IS_FIXED
1309
poly_to_point(SkPoint * pt,const SkPoint poly[],int count)1310 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
1311 SkFixed x = SK_Fixed1, y = SK_Fixed1;
1312 SkPoint pt1, pt2;
1313 Sk64 w1, w2;
1314
1315 if (count > 1) {
1316 pt1.fX = poly[1].fX - poly[0].fX;
1317 pt1.fY = poly[1].fY - poly[0].fY;
1318 y = SkPoint::Length(pt1.fX, pt1.fY);
1319 if (y == 0) {
1320 return false;
1321 }
1322 switch (count) {
1323 case 2:
1324 break;
1325 case 3:
1326 pt2.fX = poly[0].fY - poly[2].fY;
1327 pt2.fY = poly[2].fX - poly[0].fX;
1328 goto CALC_X;
1329 default:
1330 pt2.fX = poly[0].fY - poly[3].fY;
1331 pt2.fY = poly[3].fX - poly[0].fX;
1332 CALC_X:
1333 w1.setMul(pt1.fX, pt2.fX);
1334 w2.setMul(pt1.fY, pt2.fY);
1335 w1.add(w2);
1336 w1.div(y, Sk64::kRound_DivOption);
1337 if (!w1.is32()) {
1338 return false;
1339 }
1340 x = w1.get32();
1341 break;
1342 }
1343 }
1344 pt->set(x, y);
1345 return true;
1346 }
1347
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scalePt)1348 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
1349 const SkPoint& scalePt) {
1350 // need to check if SkFixedDiv overflows...
1351
1352 const SkFixed scale = scalePt.fY;
1353 dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
1354 dst->fMat[kMSkewY] = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale);
1355 dst->fMat[kMPersp0] = 0;
1356 dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale);
1357 dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
1358 dst->fMat[kMPersp1] = 0;
1359 dst->fMat[kMTransX] = srcPt[0].fX;
1360 dst->fMat[kMTransY] = srcPt[0].fY;
1361 dst->fMat[kMPersp2] = SK_Fract1;
1362 dst->setTypeMask(kUnknown_Mask);
1363 return true;
1364 }
1365
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1366 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
1367 const SkPoint& scale) {
1368 // really, need to check if SkFixedDiv overflow'd
1369
1370 dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX);
1371 dst->fMat[kMSkewY] = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX);
1372 dst->fMat[kMPersp0] = 0;
1373 dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY);
1374 dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY);
1375 dst->fMat[kMPersp1] = 0;
1376 dst->fMat[kMTransX] = srcPt[0].fX;
1377 dst->fMat[kMTransY] = srcPt[0].fY;
1378 dst->fMat[kMPersp2] = SK_Fract1;
1379 dst->setTypeMask(kUnknown_Mask);
1380 return true;
1381 }
1382
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1383 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
1384 const SkPoint& scale) {
1385 SkFract a1, a2;
1386 SkFixed x0, y0, x1, y1, x2, y2;
1387
1388 x0 = srcPt[2].fX - srcPt[0].fX;
1389 y0 = srcPt[2].fY - srcPt[0].fY;
1390 x1 = srcPt[2].fX - srcPt[1].fX;
1391 y1 = srcPt[2].fY - srcPt[1].fY;
1392 x2 = srcPt[2].fX - srcPt[3].fX;
1393 y2 = srcPt[2].fY - srcPt[3].fY;
1394
1395 /* check if abs(x2) > abs(y2) */
1396 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1397 SkFixed denom = SkMulDiv(x1, y2, x2) - y1;
1398 if (0 == denom) {
1399 return false;
1400 }
1401 a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
1402 } else {
1403 SkFixed denom = x1 - SkMulDiv(y1, x2, y2);
1404 if (0 == denom) {
1405 return false;
1406 }
1407 a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom);
1408 }
1409
1410 /* check if abs(x1) > abs(y1) */
1411 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1412 SkFixed denom = y2 - SkMulDiv(x2, y1, x1);
1413 if (0 == denom) {
1414 return false;
1415 }
1416 a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom);
1417 } else {
1418 SkFixed denom = SkMulDiv(y2, x1, y1) - x2;
1419 if (0 == denom) {
1420 return false;
1421 }
1422 a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
1423 }
1424
1425 // need to check if SkFixedDiv overflows...
1426 dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) +
1427 srcPt[3].fX - srcPt[0].fX, scale.fX);
1428 dst->fMat[kMSkewY] = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) +
1429 srcPt[3].fY - srcPt[0].fY, scale.fX);
1430 dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX);
1431 dst->fMat[kMSkewX] = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) +
1432 srcPt[1].fX - srcPt[0].fX, scale.fY);
1433 dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) +
1434 srcPt[1].fY - srcPt[0].fY, scale.fY);
1435 dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY);
1436 dst->fMat[kMTransX] = srcPt[0].fX;
1437 dst->fMat[kMTransY] = srcPt[0].fY;
1438 dst->fMat[kMPersp2] = SK_Fract1;
1439 dst->setTypeMask(kUnknown_Mask);
1440 return true;
1441 }
1442
1443 #else /* Scalar is float */
1444
checkForZero(float x)1445 static inline bool checkForZero(float x) {
1446 return x*x == 0;
1447 }
1448
poly_to_point(SkPoint * pt,const SkPoint poly[],int count)1449 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
1450 float x = 1, y = 1;
1451 SkPoint pt1, pt2;
1452
1453 if (count > 1) {
1454 pt1.fX = poly[1].fX - poly[0].fX;
1455 pt1.fY = poly[1].fY - poly[0].fY;
1456 y = SkPoint::Length(pt1.fX, pt1.fY);
1457 if (checkForZero(y)) {
1458 return false;
1459 }
1460 switch (count) {
1461 case 2:
1462 break;
1463 case 3:
1464 pt2.fX = poly[0].fY - poly[2].fY;
1465 pt2.fY = poly[2].fX - poly[0].fX;
1466 goto CALC_X;
1467 default:
1468 pt2.fX = poly[0].fY - poly[3].fY;
1469 pt2.fY = poly[3].fX - poly[0].fX;
1470 CALC_X:
1471 x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) +
1472 SkScalarMul(pt1.fY, pt2.fY), y);
1473 break;
1474 }
1475 }
1476 pt->set(x, y);
1477 return true;
1478 }
1479
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1480 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
1481 const SkPoint& scale) {
1482 float invScale = 1 / scale.fY;
1483
1484 dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1485 dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
1486 dst->fMat[kMPersp0] = 0;
1487 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1488 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1489 dst->fMat[kMPersp1] = 0;
1490 dst->fMat[kMTransX] = srcPt[0].fX;
1491 dst->fMat[kMTransY] = srcPt[0].fY;
1492 dst->fMat[kMPersp2] = 1;
1493 dst->setTypeMask(kUnknown_Mask);
1494 return true;
1495 }
1496
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1497 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
1498 const SkPoint& scale) {
1499 float invScale = 1 / scale.fX;
1500 dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
1501 dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
1502 dst->fMat[kMPersp0] = 0;
1503
1504 invScale = 1 / scale.fY;
1505 dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1506 dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1507 dst->fMat[kMPersp1] = 0;
1508
1509 dst->fMat[kMTransX] = srcPt[0].fX;
1510 dst->fMat[kMTransY] = srcPt[0].fY;
1511 dst->fMat[kMPersp2] = 1;
1512 dst->setTypeMask(kUnknown_Mask);
1513 return true;
1514 }
1515
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1516 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
1517 const SkPoint& scale) {
1518 float a1, a2;
1519 float x0, y0, x1, y1, x2, y2;
1520
1521 x0 = srcPt[2].fX - srcPt[0].fX;
1522 y0 = srcPt[2].fY - srcPt[0].fY;
1523 x1 = srcPt[2].fX - srcPt[1].fX;
1524 y1 = srcPt[2].fY - srcPt[1].fY;
1525 x2 = srcPt[2].fX - srcPt[3].fX;
1526 y2 = srcPt[2].fY - srcPt[3].fY;
1527
1528 /* check if abs(x2) > abs(y2) */
1529 if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1530 float denom = SkScalarMulDiv(x1, y2, x2) - y1;
1531 if (checkForZero(denom)) {
1532 return false;
1533 }
1534 a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
1535 } else {
1536 float denom = x1 - SkScalarMulDiv(y1, x2, y2);
1537 if (checkForZero(denom)) {
1538 return false;
1539 }
1540 a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom);
1541 }
1542
1543 /* check if abs(x1) > abs(y1) */
1544 if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1545 float denom = y2 - SkScalarMulDiv(x2, y1, x1);
1546 if (checkForZero(denom)) {
1547 return false;
1548 }
1549 a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom);
1550 } else {
1551 float denom = SkScalarMulDiv(y2, x1, y1) - x2;
1552 if (checkForZero(denom)) {
1553 return false;
1554 }
1555 a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
1556 }
1557
1558 float invScale = 1 / scale.fX;
1559 dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) +
1560 srcPt[3].fX - srcPt[0].fX, invScale);
1561 dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) +
1562 srcPt[3].fY - srcPt[0].fY, invScale);
1563 dst->fMat[kMPersp0] = SkScalarMul(a2, invScale);
1564 invScale = 1 / scale.fY;
1565 dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) +
1566 srcPt[1].fX - srcPt[0].fX, invScale);
1567 dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) +
1568 srcPt[1].fY - srcPt[0].fY, invScale);
1569 dst->fMat[kMPersp1] = SkScalarMul(a1, invScale);
1570 dst->fMat[kMTransX] = srcPt[0].fX;
1571 dst->fMat[kMTransY] = srcPt[0].fY;
1572 dst->fMat[kMPersp2] = 1;
1573 dst->setTypeMask(kUnknown_Mask);
1574 return true;
1575 }
1576
1577 #endif
1578
1579 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
1580
1581 /* Taken from Rob Johnson's original sample code in QuickDraw GX
1582 */
setPolyToPoly(const SkPoint src[],const SkPoint dst[],int count)1583 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
1584 int count) {
1585 if ((unsigned)count > 4) {
1586 SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
1587 return false;
1588 }
1589
1590 if (0 == count) {
1591 this->reset();
1592 return true;
1593 }
1594 if (1 == count) {
1595 this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
1596 return true;
1597 }
1598
1599 SkPoint scale;
1600 if (!poly_to_point(&scale, src, count) ||
1601 SkScalarNearlyZero(scale.fX) ||
1602 SkScalarNearlyZero(scale.fY)) {
1603 return false;
1604 }
1605
1606 static const PolyMapProc gPolyMapProcs[] = {
1607 SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
1608 };
1609 PolyMapProc proc = gPolyMapProcs[count - 2];
1610
1611 SkMatrix tempMap, result;
1612 tempMap.setTypeMask(kUnknown_Mask);
1613
1614 if (!proc(src, &tempMap, scale)) {
1615 return false;
1616 }
1617 if (!tempMap.invert(&result)) {
1618 return false;
1619 }
1620 if (!proc(dst, &tempMap, scale)) {
1621 return false;
1622 }
1623 if (!result.setConcat(tempMap, result)) {
1624 return false;
1625 }
1626 *this = result;
1627 return true;
1628 }
1629
1630 ///////////////////////////////////////////////////////////////////////////////
1631
getMaxStretch() const1632 SkScalar SkMatrix::getMaxStretch() const {
1633 TypeMask mask = this->getType();
1634
1635 if (mask & kPerspective_Mask) {
1636 return -SK_Scalar1;
1637 }
1638
1639 SkScalar stretch;
1640
1641 if (this->isIdentity()) {
1642 stretch = SK_Scalar1;
1643 } else if (!(mask & kAffine_Mask)) {
1644 stretch = SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), SkScalarAbs(fMat[kMScaleY]));
1645 #if 0 // don't have this bit
1646 } else if (mask & kZeroScale_TypeBit) {
1647 stretch = SkMaxScalar(SkScalarAbs(fM[kSkewX]), SkScalarAbs(fM[kSkewY]));
1648 #endif
1649 } else {
1650 // ignore the translation part of the matrix, just look at 2x2 portion.
1651 // compute singular values, take largest abs value.
1652 // [a b; b c] = A^T*A
1653 SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + SkScalarMul(fMat[kMSkewY], fMat[kMSkewY]);
1654 SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) + SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]);
1655 SkScalar c = SkScalarMul(fMat[kMSkewX], fMat[kMSkewX]) + SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]);
1656 // eigenvalues of A^T*A are the squared singular values of A.
1657 // characteristic equation is det((A^T*A) - l*I) = 0
1658 // l^2 - (a + c)l + (ac-b^2)
1659 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
1660 // and roots are guaraunteed to be pos and real).
1661 SkScalar largerRoot;
1662 SkScalar bSqd = SkScalarMul(b,b);
1663 if (bSqd <= SkFloatToScalar(1e-10)) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
1664 largerRoot = SkMaxScalar(a, c);
1665 } else {
1666 SkScalar aminusc = a - c;
1667 SkScalar apluscdiv2 = (a + c) / 2;
1668 SkScalar x = SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd) / 2;
1669 largerRoot = apluscdiv2 + x;
1670 }
1671
1672 stretch = SkScalarSqrt(largerRoot);
1673 }
1674 #if defined(SK_DEBUG) && 0
1675 // test a bunch of vectors. None should be scaled by more than stretch
1676 // (modulo some error) and we should find a vector that is scaled by almost
1677 // stretch.
1678 SkPoint pt;
1679 SkScalar max = 0;
1680 for (int i = 0; i < 1000; ++i) {
1681 SkScalar x = (float)rand() / RAND_MAX;
1682 SkScalar y = sqrtf(1 - (x*x));
1683 pt.fX = fMat[kMScaleX]*x + fMat[kMSkewX]*y;
1684 pt.fY = fMat[kMSkewY]*x + fMat[kMScaleY]*y;
1685 SkScalar d = pt.distanceToOrigin();
1686 SkASSERT(d <= (1.0001 * stretch));
1687 if (max < pt.distanceToOrigin()) {
1688 max = pt.distanceToOrigin();
1689 }
1690 }
1691 SkASSERT((stretch - max) < .05*stretch);
1692 #endif
1693 return stretch;
1694 }
1695
I()1696 const SkMatrix& SkMatrix::I() {
1697 static SkMatrix gIdentity;
1698 static bool gOnce;
1699 if (!gOnce) {
1700 gIdentity.reset();
1701 gOnce = true;
1702 }
1703 return gIdentity;
1704 };
1705
InvalidMatrix()1706 const SkMatrix& SkMatrix::InvalidMatrix() {
1707 static SkMatrix gInvalid;
1708 static bool gOnce;
1709 if (!gOnce) {
1710 gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1711 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1712 SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
1713 gInvalid.getType(); // force the type to be computed
1714 gOnce = true;
1715 }
1716 return gInvalid;
1717 }
1718
1719 ///////////////////////////////////////////////////////////////////////////////
1720
flatten(void * buffer) const1721 uint32_t SkMatrix::flatten(void* buffer) const {
1722 // TODO write less for simple matrices
1723 if (buffer) {
1724 memcpy(buffer, fMat, 9 * sizeof(SkScalar));
1725 }
1726 return 9 * sizeof(SkScalar);
1727 }
1728
unflatten(const void * buffer)1729 uint32_t SkMatrix::unflatten(const void* buffer) {
1730 if (buffer) {
1731 memcpy(fMat, buffer, 9 * sizeof(SkScalar));
1732 this->setTypeMask(kUnknown_Mask);
1733 }
1734 return 9 * sizeof(SkScalar);
1735 }
1736
dump() const1737 void SkMatrix::dump() const {
1738 SkString str;
1739 this->toDumpString(&str);
1740 SkDebugf("%s\n", str.c_str());
1741 }
1742
toDumpString(SkString * str) const1743 void SkMatrix::toDumpString(SkString* str) const {
1744 #ifdef SK_CAN_USE_FLOAT
1745 str->printf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
1746 #ifdef SK_SCALAR_IS_FLOAT
1747 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1748 fMat[6], fMat[7], fMat[8]);
1749 #else
1750 SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]),
1751 SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]),
1752 SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8]));
1753 #endif
1754 #else // can't use float
1755 str->printf("[%x %x %x][%x %x %x][%x %x %x]",
1756 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1757 fMat[6], fMat[7], fMat[8]);
1758 #endif
1759 }
1760