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