1 :
2 : /*
3 : * Copyright 2006 The Android Open Source Project
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 :
9 :
10 : #ifndef SkMatrix_DEFINED
11 : #define SkMatrix_DEFINED
12 :
13 : #include "SkRect.h"
14 :
15 : class SkString;
16 :
17 : #ifdef SK_SCALAR_IS_FLOAT
18 : typedef SkScalar SkPersp;
19 : #define SkScalarToPersp(x) (x)
20 : #define SkPerspToScalar(x) (x)
21 : #else
22 : typedef SkFract SkPersp;
23 : #define SkScalarToPersp(x) SkFixedToFract(x)
24 : #define SkPerspToScalar(x) SkFractToFixed(x)
25 : #endif
26 :
27 : /** \class SkMatrix
28 :
29 : The SkMatrix class holds a 3x3 matrix for transforming coordinates.
30 : SkMatrix does not have a constructor, so it must be explicitly initialized
31 : using either reset() - to construct an identity matrix, or one of the set
32 : functions (e.g. setTranslate, setRotate, etc.).
33 : */
34 : class SK_API SkMatrix {
35 : public:
36 : /** Enum of bit fields for the mask return by getType().
37 : Use this to identify the complexity of the matrix.
38 : */
39 : enum TypeMask {
40 : kIdentity_Mask = 0,
41 : kTranslate_Mask = 0x01, //!< set if the matrix has translation
42 : kScale_Mask = 0x02, //!< set if the matrix has X or Y scale
43 : kAffine_Mask = 0x04, //!< set if the matrix skews or rotates
44 : kPerspective_Mask = 0x08 //!< set if the matrix is in perspective
45 : };
46 :
47 : /** Returns a mask bitfield describing the types of transformations
48 : that the matrix will perform. This information is used by routines
49 : like mapPoints, to optimize its inner loops to only perform as much
50 : arithmetic as is necessary.
51 : */
52 0 : TypeMask getType() const {
53 0 : if (fTypeMask & kUnknown_Mask) {
54 0 : fTypeMask = this->computeTypeMask();
55 : }
56 : // only return the public masks
57 0 : return (TypeMask)(fTypeMask & 0xF);
58 : }
59 :
60 : /** Returns true if the matrix is identity.
61 : */
62 0 : bool isIdentity() const {
63 0 : return this->getType() == 0;
64 : }
65 :
66 : /** Returns true if will map a rectangle to another rectangle. This can be
67 : true if the matrix is identity, scale-only, or rotates a multiple of
68 : 90 degrees.
69 : */
70 0 : bool rectStaysRect() const {
71 0 : if (fTypeMask & kUnknown_Mask) {
72 0 : fTypeMask = this->computeTypeMask();
73 : }
74 0 : return (fTypeMask & kRectStaysRect_Mask) != 0;
75 : }
76 : // alias for rectStaysRect()
77 : bool preservesAxisAlignment() const { return this->rectStaysRect(); }
78 :
79 : /**
80 : * Returns true if the matrix contains perspective elements.
81 : */
82 0 : bool hasPerspective() const {
83 0 : return SkToBool(this->getPerspectiveTypeMaskOnly() &
84 : kPerspective_Mask);
85 : }
86 :
87 : enum {
88 : kMScaleX,
89 : kMSkewX,
90 : kMTransX,
91 : kMSkewY,
92 : kMScaleY,
93 : kMTransY,
94 : kMPersp0,
95 : kMPersp1,
96 : kMPersp2
97 : };
98 :
99 : /** Affine arrays are in column major order
100 : because that's how PDF and XPS like it.
101 : */
102 : enum {
103 : kAScaleX,
104 : kASkewY,
105 : kASkewX,
106 : kAScaleY,
107 : kATransX,
108 : kATransY
109 : };
110 :
111 0 : SkScalar operator[](int index) const {
112 0 : SkASSERT((unsigned)index < 9);
113 0 : return fMat[index];
114 : }
115 :
116 0 : SkScalar get(int index) const {
117 0 : SkASSERT((unsigned)index < 9);
118 0 : return fMat[index];
119 : }
120 :
121 0 : SkScalar getScaleX() const { return fMat[kMScaleX]; }
122 0 : SkScalar getScaleY() const { return fMat[kMScaleY]; }
123 0 : SkScalar getSkewY() const { return fMat[kMSkewY]; }
124 0 : SkScalar getSkewX() const { return fMat[kMSkewX]; }
125 0 : SkScalar getTranslateX() const { return fMat[kMTransX]; }
126 0 : SkScalar getTranslateY() const { return fMat[kMTransY]; }
127 : SkPersp getPerspX() const { return fMat[kMPersp0]; }
128 : SkPersp getPerspY() const { return fMat[kMPersp1]; }
129 :
130 : SkScalar& operator[](int index) {
131 : SkASSERT((unsigned)index < 9);
132 : this->setTypeMask(kUnknown_Mask);
133 : return fMat[index];
134 : }
135 :
136 0 : void set(int index, SkScalar value) {
137 0 : SkASSERT((unsigned)index < 9);
138 0 : fMat[index] = value;
139 0 : this->setTypeMask(kUnknown_Mask);
140 0 : }
141 :
142 0 : void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
143 0 : void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
144 0 : void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
145 0 : void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
146 : void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
147 : void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
148 : void setPerspX(SkPersp v) { this->set(kMPersp0, v); }
149 : void setPerspY(SkPersp v) { this->set(kMPersp1, v); }
150 :
151 0 : void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
152 : SkScalar skewY, SkScalar scaleY, SkScalar transY,
153 : SkPersp persp0, SkPersp persp1, SkPersp persp2) {
154 0 : fMat[kMScaleX] = scaleX;
155 0 : fMat[kMSkewX] = skewX;
156 0 : fMat[kMTransX] = transX;
157 0 : fMat[kMSkewY] = skewY;
158 0 : fMat[kMScaleY] = scaleY;
159 0 : fMat[kMTransY] = transY;
160 0 : fMat[kMPersp0] = persp0;
161 0 : fMat[kMPersp1] = persp1;
162 0 : fMat[kMPersp2] = persp2;
163 0 : this->setTypeMask(kUnknown_Mask);
164 0 : }
165 :
166 : /** Set the matrix to identity
167 : */
168 : void reset();
169 : // alias for reset()
170 : void setIdentity() { this->reset(); }
171 :
172 : /** Set the matrix to translate by (dx, dy).
173 : */
174 : void setTranslate(SkScalar dx, SkScalar dy);
175 : /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
176 : The pivot point is the coordinate that should remain unchanged by the
177 : specified transformation.
178 : */
179 : void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
180 : /** Set the matrix to scale by sx and sy.
181 : */
182 : void setScale(SkScalar sx, SkScalar sy);
183 : /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't
184 : touch the matrix if either divx or divy is zero.
185 : */
186 : bool setIDiv(int divx, int divy);
187 : /** Set the matrix to rotate by the specified number of degrees, with a
188 : pivot point at (px, py). The pivot point is the coordinate that should
189 : remain unchanged by the specified transformation.
190 : */
191 : void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
192 : /** Set the matrix to rotate about (0,0) by the specified number of degrees.
193 : */
194 : void setRotate(SkScalar degrees);
195 : /** Set the matrix to rotate by the specified sine and cosine values, with
196 : a pivot point at (px, py). The pivot point is the coordinate that
197 : should remain unchanged by the specified transformation.
198 : */
199 : void setSinCos(SkScalar sinValue, SkScalar cosValue,
200 : SkScalar px, SkScalar py);
201 : /** Set the matrix to rotate by the specified sine and cosine values.
202 : */
203 : void setSinCos(SkScalar sinValue, SkScalar cosValue);
204 : /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
205 : The pivot point is the coordinate that should remain unchanged by the
206 : specified transformation.
207 : */
208 : void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
209 : /** Set the matrix to skew by sx and sy.
210 : */
211 : void setSkew(SkScalar kx, SkScalar ky);
212 : /** Set the matrix to the concatenation of the two specified matrices,
213 : returning true if the the result can be represented. Either of the
214 : two matrices may also be the target matrix. *this = a * b;
215 : */
216 : bool setConcat(const SkMatrix& a, const SkMatrix& b);
217 :
218 : /** Preconcats the matrix with the specified translation.
219 : M' = M * T(dx, dy)
220 : */
221 : bool preTranslate(SkScalar dx, SkScalar dy);
222 : /** Preconcats the matrix with the specified scale.
223 : M' = M * S(sx, sy, px, py)
224 : */
225 : bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
226 : /** Preconcats the matrix with the specified scale.
227 : M' = M * S(sx, sy)
228 : */
229 : bool preScale(SkScalar sx, SkScalar sy);
230 : /** Preconcats the matrix with the specified rotation.
231 : M' = M * R(degrees, px, py)
232 : */
233 : bool preRotate(SkScalar degrees, SkScalar px, SkScalar py);
234 : /** Preconcats the matrix with the specified rotation.
235 : M' = M * R(degrees)
236 : */
237 : bool preRotate(SkScalar degrees);
238 : /** Preconcats the matrix with the specified skew.
239 : M' = M * K(kx, ky, px, py)
240 : */
241 : bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
242 : /** Preconcats the matrix with the specified skew.
243 : M' = M * K(kx, ky)
244 : */
245 : bool preSkew(SkScalar kx, SkScalar ky);
246 : /** Preconcats the matrix with the specified matrix.
247 : M' = M * other
248 : */
249 : bool preConcat(const SkMatrix& other);
250 :
251 : /** Postconcats the matrix with the specified translation.
252 : M' = T(dx, dy) * M
253 : */
254 : bool postTranslate(SkScalar dx, SkScalar dy);
255 : /** Postconcats the matrix with the specified scale.
256 : M' = S(sx, sy, px, py) * M
257 : */
258 : bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
259 : /** Postconcats the matrix with the specified scale.
260 : M' = S(sx, sy) * M
261 : */
262 : bool postScale(SkScalar sx, SkScalar sy);
263 : /** Postconcats the matrix by dividing it by the specified integers.
264 : M' = S(1/divx, 1/divy, 0, 0) * M
265 : */
266 : bool postIDiv(int divx, int divy);
267 : /** Postconcats the matrix with the specified rotation.
268 : M' = R(degrees, px, py) * M
269 : */
270 : bool postRotate(SkScalar degrees, SkScalar px, SkScalar py);
271 : /** Postconcats the matrix with the specified rotation.
272 : M' = R(degrees) * M
273 : */
274 : bool postRotate(SkScalar degrees);
275 : /** Postconcats the matrix with the specified skew.
276 : M' = K(kx, ky, px, py) * M
277 : */
278 : bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
279 : /** Postconcats the matrix with the specified skew.
280 : M' = K(kx, ky) * M
281 : */
282 : bool postSkew(SkScalar kx, SkScalar ky);
283 : /** Postconcats the matrix with the specified matrix.
284 : M' = other * M
285 : */
286 : bool postConcat(const SkMatrix& other);
287 :
288 : enum ScaleToFit {
289 : /**
290 : * Scale in X and Y independently, so that src matches dst exactly.
291 : * This may change the aspect ratio of the src.
292 : */
293 : kFill_ScaleToFit,
294 : /**
295 : * Compute a scale that will maintain the original src aspect ratio,
296 : * but will also ensure that src fits entirely inside dst. At least one
297 : * axis (X or Y) will fit exactly. kStart aligns the result to the
298 : * left and top edges of dst.
299 : */
300 : kStart_ScaleToFit,
301 : /**
302 : * Compute a scale that will maintain the original src aspect ratio,
303 : * but will also ensure that src fits entirely inside dst. At least one
304 : * axis (X or Y) will fit exactly. The result is centered inside dst.
305 : */
306 : kCenter_ScaleToFit,
307 : /**
308 : * Compute a scale that will maintain the original src aspect ratio,
309 : * but will also ensure that src fits entirely inside dst. At least one
310 : * axis (X or Y) will fit exactly. kEnd aligns the result to the
311 : * right and bottom edges of dst.
312 : */
313 : kEnd_ScaleToFit
314 : };
315 :
316 : /** Set the matrix to the scale and translate values that map the source
317 : rectangle to the destination rectangle, returning true if the the result
318 : can be represented.
319 : @param src the source rectangle to map from.
320 : @param dst the destination rectangle to map to.
321 : @param stf the ScaleToFit option
322 : @return true if the matrix can be represented by the rectangle mapping.
323 : */
324 : bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
325 :
326 : /** Set the matrix such that the specified src points would map to the
327 : specified dst points. count must be within [0..4].
328 : @param src The array of src points
329 : @param dst The array of dst points
330 : @param count The number of points to use for the transformation
331 : @return true if the matrix was set to the specified transformation
332 : */
333 : bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
334 :
335 : /** If this matrix can be inverted, return true and if inverse is not null,
336 : set inverse to be the inverse of this matrix. If this matrix cannot be
337 : inverted, ignore inverse and return false
338 : */
339 : bool invert(SkMatrix* inverse) const;
340 :
341 : /** Fills the passed array with affine identity values
342 : in column major order.
343 : @param affine The array to fill with affine identity values.
344 : Must not be NULL.
345 : */
346 : static void SetAffineIdentity(SkScalar affine[6]);
347 :
348 : /** Fills the passed array with the affine values in column major order.
349 : If the matrix is a perspective transform, returns false
350 : and does not change the passed array.
351 : @param affine The array to fill with affine values. Ignored if NULL.
352 : */
353 : bool asAffine(SkScalar affine[6]) const;
354 :
355 : /** Apply this matrix to the array of points specified by src, and write
356 : the transformed points into the array of points specified by dst.
357 : dst[] = M * src[]
358 : @param dst Where the transformed coordinates are written. It must
359 : contain at least count entries
360 : @param src The original coordinates that are to be transformed. It
361 : must contain at least count entries
362 : @param count The number of points in src to read, and then transform
363 : into dst.
364 : */
365 : void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
366 :
367 : /** Apply this matrix to the array of points, overwriting it with the
368 : transformed values.
369 : dst[] = M * pts[]
370 : @param pts The points to be transformed. It must contain at least
371 : count entries
372 : @param count The number of points in pts.
373 : */
374 0 : void mapPoints(SkPoint pts[], int count) const {
375 0 : this->mapPoints(pts, pts, count);
376 0 : }
377 :
378 : /** Like mapPoints but with custom byte stride between the points. Stride
379 : * should be a multiple of sizeof(SkScalar).
380 : */
381 : void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
382 : SkASSERT(stride >= sizeof(SkPoint));
383 : SkASSERT(0 == stride % sizeof(SkScalar));
384 : for (int i = 0; i < count; ++i) {
385 : this->mapPoints(pts, pts, 1);
386 : pts = (SkPoint*)((intptr_t)pts + stride);
387 : }
388 : }
389 :
390 : /** Like mapPoints but with custom byte stride between the points.
391 : */
392 : void mapPointsWithStride(SkPoint dst[], SkPoint src[],
393 : size_t stride, int count) const {
394 : SkASSERT(stride >= sizeof(SkPoint));
395 : SkASSERT(0 == stride % sizeof(SkScalar));
396 : for (int i = 0; i < count; ++i) {
397 : this->mapPoints(dst, src, 1);
398 : src = (SkPoint*)((intptr_t)src + stride);
399 : dst = (SkPoint*)((intptr_t)dst + stride);
400 : }
401 : }
402 :
403 0 : void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
404 0 : SkASSERT(result);
405 0 : this->getMapXYProc()(*this, x, y, result);
406 0 : }
407 :
408 : /** Apply this matrix to the array of vectors specified by src, and write
409 : the transformed vectors into the array of vectors specified by dst.
410 : This is similar to mapPoints, but ignores any translation in the matrix.
411 : @param dst Where the transformed coordinates are written. It must
412 : contain at least count entries
413 : @param src The original coordinates that are to be transformed. It
414 : must contain at least count entries
415 : @param count The number of vectors in src to read, and then transform
416 : into dst.
417 : */
418 : void mapVectors(SkVector dst[], const SkVector src[], int count) const;
419 :
420 : /** Apply this matrix to the array of vectors specified by src, and write
421 : the transformed vectors into the array of vectors specified by dst.
422 : This is similar to mapPoints, but ignores any translation in the matrix.
423 : @param vecs The vectors to be transformed. It must contain at least
424 : count entries
425 : @param count The number of vectors in vecs.
426 : */
427 0 : void mapVectors(SkVector vecs[], int count) const {
428 0 : this->mapVectors(vecs, vecs, count);
429 0 : }
430 :
431 : /** Apply this matrix to the src rectangle, and write the transformed
432 : rectangle into dst. This is accomplished by transforming the 4 corners
433 : of src, and then setting dst to the bounds of those points.
434 : @param dst Where the transformed rectangle is written.
435 : @param src The original rectangle to be transformed.
436 : @return the result of calling rectStaysRect()
437 : */
438 : bool mapRect(SkRect* dst, const SkRect& src) const;
439 :
440 : /** Apply this matrix to the rectangle, and write the transformed rectangle
441 : back into it. This is accomplished by transforming the 4 corners of
442 : rect, and then setting it to the bounds of those points
443 : @param rect The rectangle to transform.
444 : @return the result of calling rectStaysRect()
445 : */
446 0 : bool mapRect(SkRect* rect) const {
447 0 : return this->mapRect(rect, *rect);
448 : }
449 :
450 : /** Return the mean radius of a circle after it has been mapped by
451 : this matrix. NOTE: in perspective this value assumes the circle
452 : has its center at the origin.
453 : */
454 : SkScalar mapRadius(SkScalar radius) const;
455 :
456 : typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
457 : SkPoint* result);
458 :
459 0 : static MapXYProc GetMapXYProc(TypeMask mask) {
460 0 : SkASSERT((mask & ~kAllMasks) == 0);
461 0 : return gMapXYProcs[mask & kAllMasks];
462 : }
463 :
464 0 : MapXYProc getMapXYProc() const {
465 0 : return GetMapXYProc(this->getType());
466 : }
467 :
468 : typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
469 : const SkPoint src[], int count);
470 :
471 0 : static MapPtsProc GetMapPtsProc(TypeMask mask) {
472 0 : SkASSERT((mask & ~kAllMasks) == 0);
473 0 : return gMapPtsProcs[mask & kAllMasks];
474 : }
475 :
476 0 : MapPtsProc getMapPtsProc() const {
477 0 : return GetMapPtsProc(this->getType());
478 : }
479 :
480 : /** If the matrix can be stepped in X (not complex perspective)
481 : then return true and if step[XY] is not null, return the step[XY] value.
482 : If it cannot, return false and ignore step.
483 : */
484 : bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const;
485 :
486 : #ifdef SK_SCALAR_IS_FIXED
487 : friend bool operator==(const SkMatrix& a, const SkMatrix& b) {
488 : return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0;
489 : }
490 :
491 : friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
492 : return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0;
493 : }
494 : #else
495 : friend bool operator==(const SkMatrix& a, const SkMatrix& b);
496 : friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
497 : return !(a == b);
498 : }
499 : #endif
500 :
501 : enum {
502 : // flatten/unflatten will never return a value larger than this
503 : kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
504 : };
505 : // return the number of bytes written, whether or not buffer is null
506 : uint32_t flatten(void* buffer) const;
507 : // return the number of bytes read
508 : uint32_t unflatten(const void* buffer);
509 :
510 : void dump() const;
511 : void toDumpString(SkString*) const;
512 :
513 : /**
514 : * Calculates the maximum stretching factor of the matrix. If the matrix has
515 : * perspective -1 is returned.
516 : *
517 : * @return maximum strecthing factor
518 : */
519 : SkScalar getMaxStretch() const;
520 :
521 : /**
522 : * Return a reference to a const identity matrix
523 : */
524 : static const SkMatrix& I();
525 :
526 : /**
527 : * Return a reference to a const matrix that is "invalid", one that could
528 : * never be used.
529 : */
530 : static const SkMatrix& InvalidMatrix();
531 :
532 : /**
533 : * Testing routine; the matrix's type cache should never need to be
534 : * manually invalidated during normal use.
535 : */
536 : void dirtyMatrixTypeCache() {
537 : this->setTypeMask(kUnknown_Mask);
538 : }
539 :
540 : private:
541 : enum {
542 : /** Set if the matrix will map a rectangle to another rectangle. This
543 : can be true if the matrix is scale-only, or rotates a multiple of
544 : 90 degrees. This bit is not set if the matrix is identity.
545 :
546 : This bit will be set on identity matrices
547 : */
548 : kRectStaysRect_Mask = 0x10,
549 :
550 : /** Set if the perspective bit is valid even though the rest of
551 : the matrix is Unknown.
552 : */
553 : kOnlyPerspectiveValid_Mask = 0x40,
554 :
555 : kUnknown_Mask = 0x80,
556 :
557 : kORableMasks = kTranslate_Mask |
558 : kScale_Mask |
559 : kAffine_Mask |
560 : kPerspective_Mask,
561 :
562 : kAllMasks = kTranslate_Mask |
563 : kScale_Mask |
564 : kAffine_Mask |
565 : kPerspective_Mask |
566 : kRectStaysRect_Mask
567 : };
568 :
569 : SkScalar fMat[9];
570 : mutable uint8_t fTypeMask;
571 :
572 : uint8_t computeTypeMask() const;
573 : uint8_t computePerspectiveTypeMask() const;
574 :
575 0 : void setTypeMask(int mask) {
576 : // allow kUnknown or a valid mask
577 0 : SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
578 : ((kUnknown_Mask | kOnlyPerspectiveValid_Mask | kPerspective_Mask) & mask)
579 : == mask);
580 0 : fTypeMask = SkToU8(mask);
581 0 : }
582 :
583 0 : void orTypeMask(int mask) {
584 0 : SkASSERT((mask & kORableMasks) == mask);
585 0 : fTypeMask = SkToU8(fTypeMask | mask);
586 0 : }
587 :
588 0 : void clearTypeMask(int mask) {
589 : // only allow a valid mask
590 0 : SkASSERT((mask & kAllMasks) == mask);
591 0 : fTypeMask &= ~mask;
592 0 : }
593 :
594 0 : TypeMask getPerspectiveTypeMaskOnly() const {
595 0 : if ((fTypeMask & kUnknown_Mask) &&
596 0 : !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
597 0 : fTypeMask = this->computePerspectiveTypeMask();
598 : }
599 0 : return (TypeMask)(fTypeMask & 0xF);
600 : }
601 :
602 : /** Returns true if we already know that the matrix is identity;
603 : false otherwise.
604 : */
605 0 : bool isTriviallyIdentity() const {
606 0 : if (fTypeMask & kUnknown_Mask) {
607 0 : return false;
608 : }
609 0 : return ((fTypeMask & 0xF) == 0);
610 : }
611 :
612 : static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
613 : static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
614 : static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
615 :
616 : static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
617 : static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
618 : static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
619 : static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
620 : static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
621 : static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
622 : static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
623 :
624 : static const MapXYProc gMapXYProcs[];
625 :
626 : static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
627 : static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
628 : static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
629 : static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
630 : int count);
631 : static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
632 : static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
633 : int count);
634 : static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
635 :
636 : static const MapPtsProc gMapPtsProcs[];
637 :
638 : friend class SkPerspIter;
639 : };
640 :
641 : #endif
|