Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(746)

Side by Side Diff: skia/corecg/SkMatrix.cpp

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

Powered by Google App Engine
This is Rietveld 408576698