OLD | NEW |
| (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 | |
OLD | NEW |