OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmapProcState.h" | 8 #include "SkBitmapProcState.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
12 #include "SkUnPreMultiply.h" | 12 #include "SkUnPreMultiply.h" |
13 #include "SkRTConf.h" | 13 #include "SkRTConf.h" |
14 #include "SkShader.h" | 14 #include "SkShader.h" |
15 | 15 |
16 #define DS(x) SkDoubleToScalar(x) | 16 #define DS(x) SkDoubleToScalar(x) |
17 | 17 |
18 inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPM
Color c1, SkPMColor c2, SkPMColor c3) { | 18 #define MUL(a, b) ((a) * (b)) |
19 SkScalar t2 = t * t, t3 = t2 * t; | 19 |
20 SkScalar cc[4]; | 20 static inline SkPMColor cubicBlend(const SkFixed cc[4], SkPMColor c0, SkPMColor
c1, SkPMColor c2, SkPMColor c3) { |
21 cc[0] = c[0] + SkScalarMul(c[1], t) + SkScalarMul(c[2], t2) + SkScalarMul(c
[3], t3); | 21 SkFixed fa = MUL(cc[0], SkGetPackedA32(c0)) + MUL(cc[1], SkGetPackedA32(c1))
+ MUL(cc[2], SkGetPackedA32(c2)) + MUL(cc[3], SkGetPackedA32(c3)); |
22 cc[1] = c[4] + SkScalarMul(c[5], t) + SkScalarMul(c[6], t2) + SkScalarMul(c
[7], t3); | 22 SkFixed fr = MUL(cc[0], SkGetPackedR32(c0)) + MUL(cc[1], SkGetPackedR32(c1))
+ MUL(cc[2], SkGetPackedR32(c2)) + MUL(cc[3], SkGetPackedR32(c3)); |
23 cc[2] = c[8] + SkScalarMul(c[9], t) + SkScalarMul(c[10], t2) + SkScalarMul(
c[11], t3); | 23 SkFixed fg = MUL(cc[0], SkGetPackedG32(c0)) + MUL(cc[1], SkGetPackedG32(c1))
+ MUL(cc[2], SkGetPackedG32(c2)) + MUL(cc[3], SkGetPackedG32(c3)); |
24 cc[3] = c[12] + SkScalarMul(c[13], t) + SkScalarMul(c[14], t2) + SkScalarMul
(c[15], t3); | 24 SkFixed fb = MUL(cc[0], SkGetPackedB32(c0)) + MUL(cc[1], SkGetPackedB32(c1))
+ MUL(cc[2], SkGetPackedB32(c2)) + MUL(cc[3], SkGetPackedB32(c3)); |
25 SkScalar a = SkScalarClampMax(SkScalarMul(cc[0], SkGetPackedA32(c0)) + SkSca
larMul(cc[1], SkGetPackedA32(c1)) + SkScalarMul(cc[2], SkGetPackedA32(c2)) + SkS
calarMul(cc[3], SkGetPackedA32(c3)), 255); | 25 |
26 SkScalar r = SkScalarMul(cc[0], SkGetPackedR32(c0)) + SkScalarMul(cc[1], SkG
etPackedR32(c1)) + SkScalarMul(cc[2], SkGetPackedR32(c2)) + SkScalarMul(cc[3], S
kGetPackedR32(c3)); | 26 int a = SkClampMax(SkFixedRoundToInt(fa), 255); |
27 SkScalar g = SkScalarMul(cc[0], SkGetPackedG32(c0)) + SkScalarMul(cc[1], SkG
etPackedG32(c1)) + SkScalarMul(cc[2], SkGetPackedG32(c2)) + SkScalarMul(cc[3], S
kGetPackedG32(c3)); | 27 int r = SkClampMax(SkFixedRoundToInt(fr), a); |
28 SkScalar b = SkScalarMul(cc[0], SkGetPackedB32(c0)) + SkScalarMul(cc[1], SkG
etPackedB32(c1)) + SkScalarMul(cc[2], SkGetPackedB32(c2)) + SkScalarMul(cc[3], S
kGetPackedB32(c3)); | 28 int g = SkClampMax(SkFixedRoundToInt(fg), a); |
29 return SkPackARGB32(SkScalarRoundToInt(a), | 29 int b = SkClampMax(SkFixedRoundToInt(fb), a); |
30 SkScalarRoundToInt(SkScalarClampMax(r, a)), | 30 |
31 SkScalarRoundToInt(SkScalarClampMax(g, a)), | 31 return SkPackARGB32(a, r, g, b); |
32 SkScalarRoundToInt(SkScalarClampMax(b, a))); | 32 } |
| 33 |
| 34 static float poly_eval(const float cc[4], float t) { |
| 35 return cc[0] + t * (cc[1] + t * (cc[2] + t * cc[3])); |
| 36 } |
| 37 |
| 38 static void build_coeff4(SkFixed dst[4], const float src[16], float t) { |
| 39 dst[0] = SkFloatToFixed(poly_eval(&src[ 0], t)); |
| 40 dst[1] = SkFloatToFixed(poly_eval(&src[ 4], t)); |
| 41 dst[2] = SkFloatToFixed(poly_eval(&src[ 8], t)); |
| 42 dst[3] = SkFloatToFixed(poly_eval(&src[12], t)); |
33 } | 43 } |
34 | 44 |
35 static void bicubicFilter(const SkBitmapProcState& s, int x, int y, | 45 static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
36 SkPMColor colors[], int count) { | 46 SkPMColor* SK_RESTRICT colors, int count) { |
37 | 47 |
38 static const SkScalar coefficients[16] = { | 48 static const SkScalar coefficients[16] = { |
39 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), | 49 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), |
40 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), | 50 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), |
41 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), | 51 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), |
42 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), | 52 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), |
43 }; | 53 }; |
44 | 54 |
45 SkPMColor *dptr = &(colors[0]); | 55 const int maxX = s.fBitmap->width() - 1; |
| 56 const int maxY = s.fBitmap->height() - 1; |
| 57 |
46 while (count-- > 0) { | 58 while (count-- > 0) { |
47 SkPoint srcPt; | 59 SkPoint srcPt; |
48 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x), | 60 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x), |
49 SkIntToScalar(y), &srcPt); | 61 SkIntToScalar(y), &srcPt); |
50 srcPt.fX -= SK_ScalarHalf; | 62 srcPt.fX -= SK_ScalarHalf; |
51 srcPt.fY -= SK_ScalarHalf; | 63 srcPt.fY -= SK_ScalarHalf; |
52 SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX); | 64 SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX); |
53 SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); | 65 SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); |
| 66 |
| 67 SkFixed coeffX[4], coeffY[4]; |
| 68 build_coeff4(coeffX, coefficients, fractx); |
| 69 build_coeff4(coeffY, coefficients, fracty); |
| 70 |
54 int sx = SkScalarFloorToInt(srcPt.fX); | 71 int sx = SkScalarFloorToInt(srcPt.fX); |
55 int sy = SkScalarFloorToInt(srcPt.fY); | 72 int sy = SkScalarFloorToInt(srcPt.fY); |
56 int x0 = SkClampMax(sx - 1, s.fBitmap->width() - 1); | 73 |
57 int x1 = SkClampMax(sx , s.fBitmap->width() - 1); | 74 // Here is where we can support other tile modes (e.g. repeat or mirror) |
58 int x2 = SkClampMax(sx + 1, s.fBitmap->width() - 1); | 75 int x0 = SkClampMax(sx - 1, maxX); |
59 int x3 = SkClampMax(sx + 2, s.fBitmap->width() - 1); | 76 int x1 = SkClampMax(sx , maxX); |
60 int y0 = SkClampMax(sy - 1, s.fBitmap->height() - 1); | 77 int x2 = SkClampMax(sx + 1, maxX); |
61 int y1 = SkClampMax(sy , s.fBitmap->height() - 1); | 78 int x3 = SkClampMax(sx + 2, maxX); |
62 int y2 = SkClampMax(sy + 1, s.fBitmap->height() - 1); | 79 int y0 = SkClampMax(sy - 1, maxY); |
63 int y3 = SkClampMax(sy + 2, s.fBitmap->height() - 1); | 80 int y1 = SkClampMax(sy , maxY); |
| 81 int y2 = SkClampMax(sy + 1, maxY); |
| 82 int y3 = SkClampMax(sy + 2, maxY); |
| 83 |
64 SkPMColor s00 = *s.fBitmap->getAddr32(x0, y0); | 84 SkPMColor s00 = *s.fBitmap->getAddr32(x0, y0); |
65 SkPMColor s10 = *s.fBitmap->getAddr32(x1, y0); | 85 SkPMColor s10 = *s.fBitmap->getAddr32(x1, y0); |
66 SkPMColor s20 = *s.fBitmap->getAddr32(x2, y0); | 86 SkPMColor s20 = *s.fBitmap->getAddr32(x2, y0); |
67 SkPMColor s30 = *s.fBitmap->getAddr32(x3, y0); | 87 SkPMColor s30 = *s.fBitmap->getAddr32(x3, y0); |
68 SkPMColor s0 = cubicBlend(coefficients, fractx, s00, s10, s20, s30); | 88 SkPMColor s0 = cubicBlend(coeffX, s00, s10, s20, s30); |
69 SkPMColor s01 = *s.fBitmap->getAddr32(x0, y1); | 89 SkPMColor s01 = *s.fBitmap->getAddr32(x0, y1); |
70 SkPMColor s11 = *s.fBitmap->getAddr32(x1, y1); | 90 SkPMColor s11 = *s.fBitmap->getAddr32(x1, y1); |
71 SkPMColor s21 = *s.fBitmap->getAddr32(x2, y1); | 91 SkPMColor s21 = *s.fBitmap->getAddr32(x2, y1); |
72 SkPMColor s31 = *s.fBitmap->getAddr32(x3, y1); | 92 SkPMColor s31 = *s.fBitmap->getAddr32(x3, y1); |
73 SkPMColor s1 = cubicBlend(coefficients, fractx, s01, s11, s21, s31); | 93 SkPMColor s1 = cubicBlend(coeffX, s01, s11, s21, s31); |
74 SkPMColor s02 = *s.fBitmap->getAddr32(x0, y2); | 94 SkPMColor s02 = *s.fBitmap->getAddr32(x0, y2); |
75 SkPMColor s12 = *s.fBitmap->getAddr32(x1, y2); | 95 SkPMColor s12 = *s.fBitmap->getAddr32(x1, y2); |
76 SkPMColor s22 = *s.fBitmap->getAddr32(x2, y2); | 96 SkPMColor s22 = *s.fBitmap->getAddr32(x2, y2); |
77 SkPMColor s32 = *s.fBitmap->getAddr32(x3, y2); | 97 SkPMColor s32 = *s.fBitmap->getAddr32(x3, y2); |
78 SkPMColor s2 = cubicBlend(coefficients, fractx, s02, s12, s22, s32); | 98 SkPMColor s2 = cubicBlend(coeffX, s02, s12, s22, s32); |
79 SkPMColor s03 = *s.fBitmap->getAddr32(x0, y3); | 99 SkPMColor s03 = *s.fBitmap->getAddr32(x0, y3); |
80 SkPMColor s13 = *s.fBitmap->getAddr32(x1, y3); | 100 SkPMColor s13 = *s.fBitmap->getAddr32(x1, y3); |
81 SkPMColor s23 = *s.fBitmap->getAddr32(x2, y3); | 101 SkPMColor s23 = *s.fBitmap->getAddr32(x2, y3); |
82 SkPMColor s33 = *s.fBitmap->getAddr32(x3, y3); | 102 SkPMColor s33 = *s.fBitmap->getAddr32(x3, y3); |
83 SkPMColor s3 = cubicBlend(coefficients, fractx, s03, s13, s23, s33); | 103 SkPMColor s3 = cubicBlend(coeffX, s03, s13, s23, s33); |
84 *dptr++ = cubicBlend(coefficients, fracty, s0, s1, s2, s3); | 104 *colors++ = cubicBlend(coeffY, s0, s1, s2, s3); |
85 x++; | 105 x++; |
86 } | 106 } |
87 } | 107 } |
88 | 108 |
89 SkBitmapProcState::ShaderProc32 | 109 SkBitmapProcState::ShaderProc32 |
90 SkBitmapProcState::chooseBicubicFilterProc(const SkPaint& paint) { | 110 SkBitmapProcState::chooseBicubicFilterProc(const SkPaint& paint) { |
91 // we need to be requested | 111 // we need to be requested |
92 uint32_t mask = SkPaint::kFilterBitmap_Flag | 112 uint32_t mask = SkPaint::kFilterBitmap_Flag |
93 | SkPaint::kBicubicFilterBitmap_Flag | 113 | SkPaint::kBicubicFilterBitmap_Flag |
94 ; | 114 ; |
(...skipping 11 matching lines...) Expand all Loading... |
106 return NULL; | 126 return NULL; |
107 } | 127 } |
108 | 128 |
109 // TODO: support blending inside our procs | 129 // TODO: support blending inside our procs |
110 if (0xFF != paint.getAlpha()) { | 130 if (0xFF != paint.getAlpha()) { |
111 return NULL; | 131 return NULL; |
112 } | 132 } |
113 | 133 |
114 return bicubicFilter; | 134 return bicubicFilter; |
115 } | 135 } |
OLD | NEW |