1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkBitmapProcState_MatrixTemplates_DEFINED 9 #define SkBitmapProcState_MatrixTemplates_DEFINED 10 11 #include "SkMath.h" 12 #include "SkMathPriv.h" 13 14 template <typename TileProc, bool tryDecal> 15 void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[], 16 int count, int x, int y) { 17 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 18 SkMatrix::kScale_Mask)) == 0); 19 20 // we store y, x, x, x, x, x 21 22 const unsigned maxX = s.fBitmap->width() - 1; 23 SkFractionalInt fx; 24 { 25 SkPoint pt; 26 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 27 SkIntToScalar(y) + SK_ScalarHalf, &pt); 28 fx = SkScalarToFractionalInt(pt.fY); 29 const unsigned maxY = s.fBitmap->height() - 1; 30 *xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY); 31 fx = SkScalarToFractionalInt(pt.fX); 32 } 33 34 if (0 == maxX) { 35 // all of the following X values must be 0 36 memset(xy, 0, count * sizeof(uint16_t)); 37 return; 38 } 39 40 const SkFractionalInt dx = s.fInvSxFractionalInt; 41 42 if (tryDecal && can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) { 43 decal_nofilter_scale(xy, SkFractionalIntToFixed(fx), 44 SkFractionalIntToFixed(dx), count); 45 } else { 46 int i; 47 for (i = (count >> 2); i > 0; --i) { 48 unsigned a, b; 49 a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx; 50 b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx; 51 #ifdef SK_CPU_BENDIAN 52 *xy++ = (a << 16) | b; 53 #else 54 *xy++ = (b << 16) | a; 55 #endif 56 a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx; 57 b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx; 58 #ifdef SK_CPU_BENDIAN 59 *xy++ = (a << 16) | b; 60 #else 61 *xy++ = (b << 16) | a; 62 #endif 63 } 64 uint16_t* xx = (uint16_t*)xy; 65 for (i = (count & 3); i > 0; --i) { 66 *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx; 67 } 68 } 69 } 70 71 // note: we could special-case on a matrix which is skewed in X but not Y. 72 // this would require a more general setup thatn SCALE does, but could use 73 // SCALE's inner loop that only looks at dx 74 75 template <typename TileProc> 76 void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[], 77 int count, int x, int y) { 78 SkASSERT(s.fInvType & SkMatrix::kAffine_Mask); 79 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 80 SkMatrix::kScale_Mask | 81 SkMatrix::kAffine_Mask)) == 0); 82 83 SkPoint srcPt; 84 s.fInvProc(s.fInvMatrix, 85 SkIntToScalar(x) + SK_ScalarHalf, 86 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 87 88 SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX); 89 SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY); 90 SkFractionalInt dx = s.fInvSxFractionalInt; 91 SkFractionalInt dy = s.fInvKyFractionalInt; 92 int maxX = s.fBitmap->width() - 1; 93 int maxY = s.fBitmap->height() - 1; 94 95 for (int i = count; i > 0; --i) { 96 *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) | 97 TileProc::X(s, SkFractionalIntToFixed(fx), maxX); 98 fx += dx; fy += dy; 99 } 100 } 101 102 template <typename TileProc> 103 void NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy, 104 int count, int x, int y) { 105 SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask); 106 107 int maxX = s.fBitmap->width() - 1; 108 int maxY = s.fBitmap->height() - 1; 109 110 SkPerspIter iter(s.fInvMatrix, 111 SkIntToScalar(x) + SK_ScalarHalf, 112 SkIntToScalar(y) + SK_ScalarHalf, count); 113 114 while ((count = iter.next()) != 0) { 115 const SkFixed* SK_RESTRICT srcXY = iter.getXY(); 116 while (--count >= 0) { 117 *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) | 118 TileProc::X(s, srcXY[0], maxX); 119 srcXY += 2; 120 } 121 } 122 } 123 124 #endif 125