OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkBitmapCache.h" | 8 #include "SkBitmapCache.h" |
9 #include "SkBitmapController.h" | 9 #include "SkBitmapController.h" |
10 #include "SkBitmapProcState.h" | 10 #include "SkBitmapProcState.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 | 47 |
48 // true iff the matrix contains, at most, scale and translate elements | 48 // true iff the matrix contains, at most, scale and translate elements |
49 static bool matrix_only_scale_translate(const SkMatrix& m) { | 49 static bool matrix_only_scale_translate(const SkMatrix& m) { |
50 return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); | 50 return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); |
51 } | 51 } |
52 | 52 |
53 /** | 53 /** |
54 * For the purposes of drawing bitmaps, if a matrix is "almost" translate | 54 * For the purposes of drawing bitmaps, if a matrix is "almost" translate |
55 * go ahead and treat it as if it were, so that subsequent code can go fast. | 55 * go ahead and treat it as if it were, so that subsequent code can go fast. |
56 */ | 56 */ |
57 static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { | 57 static bool just_trans_clamp(const SkMatrix& matrix, const SkPixmap& pixmap) { |
58 SkASSERT(matrix_only_scale_translate(matrix)); | 58 SkASSERT(matrix_only_scale_translate(matrix)); |
59 | 59 |
60 if (matrix.getType() & SkMatrix::kScale_Mask) { | 60 if (matrix.getType() & SkMatrix::kScale_Mask) { |
61 SkRect src, dst; | 61 SkRect dst; |
62 bitmap.getBounds(&src); | 62 SkRect src = SkRect::Make(pixmap.bounds()); |
63 | 63 |
64 // Can't call mapRect(), since that will fix up inverted rectangles, | 64 // Can't call mapRect(), since that will fix up inverted rectangles, |
65 // e.g. when scale is negative, and we don't want to return true for | 65 // e.g. when scale is negative, and we don't want to return true for |
66 // those. | 66 // those. |
67 matrix.mapPoints(SkTCast<SkPoint*>(&dst), | 67 matrix.mapPoints(SkTCast<SkPoint*>(&dst), |
68 SkTCast<const SkPoint*>(&src), | 68 SkTCast<const SkPoint*>(&src), |
69 2); | 69 2); |
70 | 70 |
71 // Now round all 4 edges to device space, and then compare the device | 71 // Now round all 4 edges to device space, and then compare the device |
72 // width/height to the original. Note: we must map all 4 and subtract | 72 // width/height to the original. Note: we must map all 4 and subtract |
73 // rather than map the "width" and compare, since we care about the | 73 // rather than map the "width" and compare, since we care about the |
74 // phase (in pixel space) that any translate in the matrix might impart. | 74 // phase (in pixel space) that any translate in the matrix might impart. |
75 SkIRect idst; | 75 SkIRect idst; |
76 dst.round(&idst); | 76 dst.round(&idst); |
77 return idst.width() == bitmap.width() && idst.height() == bitmap.height(
); | 77 return idst.width() == pixmap.width() && idst.height() == pixmap.height(
); |
78 } | 78 } |
79 // if we got here, we're either kTranslate_Mask or identity | 79 // if we got here, we're either kTranslate_Mask or identity |
80 return true; | 80 return true; |
81 } | 81 } |
82 | 82 |
83 static bool just_trans_general(const SkMatrix& matrix) { | 83 static bool just_trans_general(const SkMatrix& matrix) { |
84 SkASSERT(matrix_only_scale_translate(matrix)); | 84 SkASSERT(matrix_only_scale_translate(matrix)); |
85 | 85 |
86 if (matrix.getType() & SkMatrix::kScale_Mask) { | 86 if (matrix.getType() & SkMatrix::kScale_Mask) { |
87 const SkScalar tol = SK_Scalar1 / 32768; | 87 const SkScalar tol = SK_Scalar1 / 32768; |
(...skipping 19 matching lines...) Expand all Loading... |
107 * Analyze filter-quality and matrix, and decide how to implement that. | 107 * Analyze filter-quality and matrix, and decide how to implement that. |
108 * | 108 * |
109 * In general, we cascade down the request level [ High ... None ] | 109 * In general, we cascade down the request level [ High ... None ] |
110 * - for a given level, if we can fulfill it, fine, else | 110 * - for a given level, if we can fulfill it, fine, else |
111 * - else we downgrade to the next lower level and try again. | 111 * - else we downgrade to the next lower level and try again. |
112 * We can always fulfill requests for Low and None | 112 * We can always fulfill requests for Low and None |
113 * - sometimes we will "ignore" Low and give None, but this is likely a legacy
perf hack | 113 * - sometimes we will "ignore" Low and give None, but this is likely a legacy
perf hack |
114 * and may be removed. | 114 * and may be removed. |
115 */ | 115 */ |
116 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 116 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
117 fBitmap = NULL; | 117 fPixmap.reset(); |
118 fInvMatrix = inv; | 118 fInvMatrix = inv; |
119 fFilterLevel = paint.getFilterQuality(); | 119 fFilterLevel = paint.getFilterQuality(); |
120 | 120 |
121 SkDefaultBitmapController controller; | 121 SkDefaultBitmapController controller; |
122 fBMState = controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality
(), | 122 fBMState = controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality
(), |
123 fBMStateStorage.get(), fBMStateStorage.s
ize()); | 123 fBMStateStorage.get(), fBMStateStorage.s
ize()); |
124 if (NULL == fBMState) { | 124 // Note : we allow the controller to return an empty (zero-dimension) result
. Should we? |
| 125 if (NULL == fBMState || fBMState->pixmap().info().isEmpty()) { |
125 return false; | 126 return false; |
126 } | 127 } |
127 fBitmap = &fBMState->lockedBitmap(); | 128 fPixmap = fBMState->pixmap(); |
128 fInvMatrix = fBMState->invMatrix(); | 129 fInvMatrix = fBMState->invMatrix(); |
129 fFilterLevel = fBMState->quality(); | 130 fFilterLevel = fBMState->quality(); |
130 SkASSERT(fBitmap->getPixels()); | 131 SkASSERT(fPixmap.addr()); |
131 | 132 |
132 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; | 133 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; |
133 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 134 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
134 SkShader::kClamp_TileMode == fTileModeY; | 135 SkShader::kClamp_TileMode == fTileModeY; |
135 | 136 |
136 // Most of the scanline procs deal with "unit" texture coordinates, as this | 137 // Most of the scanline procs deal with "unit" texture coordinates, as this |
137 // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generat
e | 138 // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generat
e |
138 // those, we divide the matrix by its dimensions here. | 139 // those, we divide the matrix by its dimensions here. |
139 // | 140 // |
140 // We don't do this if we're either trivial (can ignore the matrix) or clamp
ing | 141 // We don't do this if we're either trivial (can ignore the matrix) or clamp
ing |
141 // in both X and Y since clamping to width,height is just as easy as to 0xFF
FF. | 142 // in both X and Y since clamping to width,height is just as easy as to 0xFF
FF. |
142 | 143 |
143 if (!(clampClamp || trivialMatrix)) { | 144 if (!(clampClamp || trivialMatrix)) { |
144 fInvMatrix.postIDiv(fBitmap->width(), fBitmap->height()); | 145 fInvMatrix.postIDiv(fPixmap.width(), fPixmap.height()); |
145 } | 146 } |
146 | 147 |
147 // Now that all possible changes to the matrix have taken place, check | 148 // Now that all possible changes to the matrix have taken place, check |
148 // to see if we're really close to a no-scale matrix. If so, explicitly | 149 // to see if we're really close to a no-scale matrix. If so, explicitly |
149 // set it to be so. Subsequent code may inspect this matrix to choose | 150 // set it to be so. Subsequent code may inspect this matrix to choose |
150 // a faster path in this case. | 151 // a faster path in this case. |
151 | 152 |
152 // This code will only execute if the matrix has some scale component; | 153 // This code will only execute if the matrix has some scale component; |
153 // if it's already pure translate then we won't do this inversion. | 154 // if it's already pure translate then we won't do this inversion. |
154 | 155 |
155 if (matrix_only_scale_translate(fInvMatrix)) { | 156 if (matrix_only_scale_translate(fInvMatrix)) { |
156 SkMatrix forward; | 157 SkMatrix forward; |
157 if (fInvMatrix.invert(&forward)) { | 158 if (fInvMatrix.invert(&forward)) { |
158 if (clampClamp ? just_trans_clamp(forward, *fBitmap) | 159 if (clampClamp ? just_trans_clamp(forward, fPixmap) |
159 : just_trans_general(forward)) { | 160 : just_trans_general(forward)) { |
160 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 161 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
161 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 162 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
162 fInvMatrix.setTranslate(tx, ty); | 163 fInvMatrix.setTranslate(tx, ty); |
163 } | 164 } |
164 } | 165 } |
165 } | 166 } |
166 | 167 |
167 fInvProc = fInvMatrix.getMapXYProc(); | 168 fInvProc = fInvMatrix.getMapXYProc(); |
168 fInvType = fInvMatrix.getType(); | 169 fInvType = fInvMatrix.getType(); |
(...skipping 12 matching lines...) Expand all Loading... |
181 // recompute the triviality of the matrix here because we may have | 182 // recompute the triviality of the matrix here because we may have |
182 // changed it! | 183 // changed it! |
183 | 184 |
184 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | 185 trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
185 | 186 |
186 if (kLow_SkFilterQuality == fFilterLevel) { | 187 if (kLow_SkFilterQuality == fFilterLevel) { |
187 // Only try bilerp if the matrix is "interesting" and | 188 // Only try bilerp if the matrix is "interesting" and |
188 // the image has a suitable size. | 189 // the image has a suitable size. |
189 | 190 |
190 if (fInvType <= SkMatrix::kTranslate_Mask || | 191 if (fInvType <= SkMatrix::kTranslate_Mask || |
191 !valid_for_filtering(fBitmap->width() | fBitmap->height())) | 192 !valid_for_filtering(fPixmap.width() | fPixmap.height())) |
192 { | 193 { |
193 fFilterLevel = kNone_SkFilterQuality; | 194 fFilterLevel = kNone_SkFilterQuality; |
194 } | 195 } |
195 } | 196 } |
196 | 197 |
197 return this->chooseScanlineProcs(trivialMatrix, clampClamp, paint); | 198 return this->chooseScanlineProcs(trivialMatrix, clampClamp, paint); |
198 } | 199 } |
199 | 200 |
200 bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp, | 201 bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp, |
201 const SkPaint& paint) { | 202 const SkPaint& paint) { |
202 fMatrixProc = this->chooseMatrixProc(trivialMatrix); | 203 fMatrixProc = this->chooseMatrixProc(trivialMatrix); |
203 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. | 204 // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never ret
urns NULL. |
204 if (NULL == fMatrixProc) { | 205 if (NULL == fMatrixProc) { |
205 return false; | 206 return false; |
206 } | 207 } |
207 | 208 |
208 /////////////////////////////////////////////////////////////////////// | 209 /////////////////////////////////////////////////////////////////////// |
209 | 210 |
210 const SkAlphaType at = fBitmap->alphaType(); | 211 const SkAlphaType at = fPixmap.alphaType(); |
211 | 212 |
212 // No need to do this if we're doing HQ sampling; if filter quality is | 213 // No need to do this if we're doing HQ sampling; if filter quality is |
213 // still set to HQ by the time we get here, then we must have installed | 214 // still set to HQ by the time we get here, then we must have installed |
214 // the shader procs above and can skip all this. | 215 // the shader procs above and can skip all this. |
215 | 216 |
216 if (fFilterLevel < kHigh_SkFilterQuality) { | 217 if (fFilterLevel < kHigh_SkFilterQuality) { |
217 | 218 |
218 int index = 0; | 219 int index = 0; |
219 if (fAlphaScale < 256) { // note: this distinction is not used for D16 | 220 if (fAlphaScale < 256) { // note: this distinction is not used for D16 |
220 index |= 1; | 221 index |= 1; |
221 } | 222 } |
222 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 223 if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
223 index |= 2; | 224 index |= 2; |
224 } | 225 } |
225 if (fFilterLevel > kNone_SkFilterQuality) { | 226 if (fFilterLevel > kNone_SkFilterQuality) { |
226 index |= 4; | 227 index |= 4; |
227 } | 228 } |
228 // bits 3,4,5 encoding the source bitmap format | 229 // bits 3,4,5 encoding the source bitmap format |
229 switch (fBitmap->colorType()) { | 230 switch (fPixmap.colorType()) { |
230 case kN32_SkColorType: | 231 case kN32_SkColorType: |
231 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { | 232 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { |
232 return false; | 233 return false; |
233 } | 234 } |
234 index |= 0; | 235 index |= 0; |
235 break; | 236 break; |
236 case kRGB_565_SkColorType: | 237 case kRGB_565_SkColorType: |
237 index |= 8; | 238 index |= 8; |
238 break; | 239 break; |
239 case kIndex_8_SkColorType: | 240 case kIndex_8_SkColorType: |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 | 377 |
377 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 378 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
378 int x, int y, | 379 int x, int y, |
379 SkPMColor* SK_RESTRICT color
s, | 380 SkPMColor* SK_RESTRICT color
s, |
380 int count) { | 381 int count) { |
381 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 382 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
382 SkASSERT(s.fInvKy == 0); | 383 SkASSERT(s.fInvKy == 0); |
383 SkASSERT(count > 0 && colors != NULL); | 384 SkASSERT(count > 0 && colors != NULL); |
384 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); | 385 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); |
385 | 386 |
386 const int maxX = s.fBitmap->width() - 1; | 387 const int maxX = s.fPixmap.width() - 1; |
387 const int maxY = s.fBitmap->height() - 1; | 388 const int maxY = s.fPixmap.height() - 1; |
388 int ix = s.fFilterOneX + x; | 389 int ix = s.fFilterOneX + x; |
389 int iy = SkClampMax(s.fFilterOneY + y, maxY); | 390 int iy = SkClampMax(s.fFilterOneY + y, maxY); |
390 #ifdef SK_DEBUG | 391 #ifdef SK_DEBUG |
391 { | 392 { |
392 SkPoint pt; | 393 SkPoint pt; |
393 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 394 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
394 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 395 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
395 int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); | 396 int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); |
396 int ix2 = SkScalarFloorToInt(pt.fX); | 397 int ix2 = SkScalarFloorToInt(pt.fX); |
397 | 398 |
398 SkASSERT(iy == iy2); | 399 SkASSERT(iy == iy2); |
399 SkASSERT(ix == ix2); | 400 SkASSERT(ix == ix2); |
400 } | 401 } |
401 #endif | 402 #endif |
402 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); | 403 const SkPMColor* row = s.fPixmap.addr32(0, iy); |
403 | 404 |
404 // clamp to the left | 405 // clamp to the left |
405 if (ix < 0) { | 406 if (ix < 0) { |
406 int n = SkMin32(-ix, count); | 407 int n = SkMin32(-ix, count); |
407 sk_memset32(colors, row[0], n); | 408 sk_memset32(colors, row[0], n); |
408 count -= n; | 409 count -= n; |
409 if (0 == count) { | 410 if (0 == count) { |
410 return; | 411 return; |
411 } | 412 } |
412 colors += n; | 413 colors += n; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 | 451 |
451 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, | 452 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, |
452 int x, int y, | 453 int x, int y, |
453 SkPMColor* SK_RESTRICT colo
rs, | 454 SkPMColor* SK_RESTRICT colo
rs, |
454 int count) { | 455 int count) { |
455 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); | 456 SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); |
456 SkASSERT(s.fInvKy == 0); | 457 SkASSERT(s.fInvKy == 0); |
457 SkASSERT(count > 0 && colors != NULL); | 458 SkASSERT(count > 0 && colors != NULL); |
458 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); | 459 SkASSERT(kNone_SkFilterQuality == s.fFilterLevel); |
459 | 460 |
460 const int stopX = s.fBitmap->width(); | 461 const int stopX = s.fPixmap.width(); |
461 const int stopY = s.fBitmap->height(); | 462 const int stopY = s.fPixmap.height(); |
462 int ix = s.fFilterOneX + x; | 463 int ix = s.fFilterOneX + x; |
463 int iy = sk_int_mod(s.fFilterOneY + y, stopY); | 464 int iy = sk_int_mod(s.fFilterOneY + y, stopY); |
464 #ifdef SK_DEBUG | 465 #ifdef SK_DEBUG |
465 { | 466 { |
466 SkPoint pt; | 467 SkPoint pt; |
467 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, | 468 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, |
468 SkIntToScalar(y) + SK_ScalarHalf, &pt); | 469 SkIntToScalar(y) + SK_ScalarHalf, &pt); |
469 int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); | 470 int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); |
470 int ix2 = SkScalarFloorToInt(pt.fX); | 471 int ix2 = SkScalarFloorToInt(pt.fX); |
471 | 472 |
472 SkASSERT(iy == iy2); | 473 SkASSERT(iy == iy2); |
473 SkASSERT(ix == ix2); | 474 SkASSERT(ix == ix2); |
474 } | 475 } |
475 #endif | 476 #endif |
476 const SkPMColor* row = s.fBitmap->getAddr32(0, iy); | 477 const SkPMColor* row = s.fPixmap.addr32(0, iy); |
477 | 478 |
478 ix = sk_int_mod(ix, stopX); | 479 ix = sk_int_mod(ix, stopX); |
479 for (;;) { | 480 for (;;) { |
480 int n = SkMin32(stopX - ix, count); | 481 int n = SkMin32(stopX - ix, count); |
481 memcpy(colors, row + ix, n * sizeof(SkPMColor)); | 482 memcpy(colors, row + ix, n * sizeof(SkPMColor)); |
482 count -= n; | 483 count -= n; |
483 if (0 == count) { | 484 if (0 == count) { |
484 return; | 485 return; |
485 } | 486 } |
486 colors += n; | 487 colors += n; |
487 ix = 0; | 488 ix = 0; |
488 } | 489 } |
489 } | 490 } |
490 | 491 |
491 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, | 492 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, |
492 int x, int y, | 493 int x, int y, |
493 SkPMColor* SK_RESTRICT colors, | 494 SkPMColor* SK_RESTRICT colors, |
494 int count) { | 495 int count) { |
495 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
== 0); | 496 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
== 0); |
496 SkASSERT(s.fInvKy == 0); | 497 SkASSERT(s.fInvKy == 0); |
497 SkASSERT(count > 0 && colors != NULL); | 498 SkASSERT(count > 0 && colors != NULL); |
498 SkASSERT(1 == s.fBitmap->width()); | 499 SkASSERT(1 == s.fPixmap.width()); |
499 | 500 |
500 int iY0; | 501 int iY0; |
501 int iY1 SK_INIT_TO_AVOID_WARNING; | 502 int iY1 SK_INIT_TO_AVOID_WARNING; |
502 int iSubY SK_INIT_TO_AVOID_WARNING; | 503 int iSubY SK_INIT_TO_AVOID_WARNING; |
503 | 504 |
504 if (kNone_SkFilterQuality != s.fFilterLevel) { | 505 if (kNone_SkFilterQuality != s.fFilterLevel) { |
505 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); | 506 SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); |
506 uint32_t xy[2]; | 507 uint32_t xy[2]; |
507 | 508 |
508 mproc(s, xy, 1, x, y); | 509 mproc(s, xy, 1, x, y); |
509 | 510 |
510 iY0 = xy[0] >> 18; | 511 iY0 = xy[0] >> 18; |
511 iY1 = xy[0] & 0x3FFF; | 512 iY1 = xy[0] & 0x3FFF; |
512 iSubY = (xy[0] >> 14) & 0xF; | 513 iSubY = (xy[0] >> 14) & 0xF; |
513 } else { | 514 } else { |
514 int yTemp; | 515 int yTemp; |
515 | 516 |
516 if (s.fInvType > SkMatrix::kTranslate_Mask) { | 517 if (s.fInvType > SkMatrix::kTranslate_Mask) { |
517 SkPoint pt; | 518 SkPoint pt; |
518 s.fInvProc(s.fInvMatrix, | 519 s.fInvProc(s.fInvMatrix, |
519 SkIntToScalar(x) + SK_ScalarHalf, | 520 SkIntToScalar(x) + SK_ScalarHalf, |
520 SkIntToScalar(y) + SK_ScalarHalf, | 521 SkIntToScalar(y) + SK_ScalarHalf, |
521 &pt); | 522 &pt); |
522 // When the matrix has a scale component the setup code in | 523 // When the matrix has a scale component the setup code in |
523 // chooseProcs multiples the inverse matrix by the inverse of the | 524 // chooseProcs multiples the inverse matrix by the inverse of the |
524 // bitmap's width and height. Since this method is going to do | 525 // bitmap's width and height. Since this method is going to do |
525 // its own tiling and sampling we need to undo that here. | 526 // its own tiling and sampling we need to undo that here. |
526 if (SkShader::kClamp_TileMode != s.fTileModeX || | 527 if (SkShader::kClamp_TileMode != s.fTileModeX || |
527 SkShader::kClamp_TileMode != s.fTileModeY) { | 528 SkShader::kClamp_TileMode != s.fTileModeY) { |
528 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); | 529 yTemp = SkScalarFloorToInt(pt.fY * s.fPixmap.height()); |
529 } else { | 530 } else { |
530 yTemp = SkScalarFloorToInt(pt.fY); | 531 yTemp = SkScalarFloorToInt(pt.fY); |
531 } | 532 } |
532 } else { | 533 } else { |
533 yTemp = s.fFilterOneY + y; | 534 yTemp = s.fFilterOneY + y; |
534 } | 535 } |
535 | 536 |
536 const int stopY = s.fBitmap->height(); | 537 const int stopY = s.fPixmap.height(); |
537 switch (s.fTileModeY) { | 538 switch (s.fTileModeY) { |
538 case SkShader::kClamp_TileMode: | 539 case SkShader::kClamp_TileMode: |
539 iY0 = SkClampMax(yTemp, stopY-1); | 540 iY0 = SkClampMax(yTemp, stopY-1); |
540 break; | 541 break; |
541 case SkShader::kRepeat_TileMode: | 542 case SkShader::kRepeat_TileMode: |
542 iY0 = sk_int_mod(yTemp, stopY); | 543 iY0 = sk_int_mod(yTemp, stopY); |
543 break; | 544 break; |
544 case SkShader::kMirror_TileMode: | 545 case SkShader::kMirror_TileMode: |
545 default: | 546 default: |
546 iY0 = sk_int_mirror(yTemp, stopY); | 547 iY0 = sk_int_mirror(yTemp, stopY); |
547 break; | 548 break; |
548 } | 549 } |
549 | 550 |
550 #ifdef SK_DEBUG | 551 #ifdef SK_DEBUG |
551 { | 552 { |
552 SkPoint pt; | 553 SkPoint pt; |
553 s.fInvProc(s.fInvMatrix, | 554 s.fInvProc(s.fInvMatrix, |
554 SkIntToScalar(x) + SK_ScalarHalf, | 555 SkIntToScalar(x) + SK_ScalarHalf, |
555 SkIntToScalar(y) + SK_ScalarHalf, | 556 SkIntToScalar(y) + SK_ScalarHalf, |
556 &pt); | 557 &pt); |
557 if (s.fInvType > SkMatrix::kTranslate_Mask && | 558 if (s.fInvType > SkMatrix::kTranslate_Mask && |
558 (SkShader::kClamp_TileMode != s.fTileModeX || | 559 (SkShader::kClamp_TileMode != s.fTileModeX || |
559 SkShader::kClamp_TileMode != s.fTileModeY)) { | 560 SkShader::kClamp_TileMode != s.fTileModeY)) { |
560 pt.fY *= s.fBitmap->height(); | 561 pt.fY *= s.fPixmap.height(); |
561 } | 562 } |
562 int iY2; | 563 int iY2; |
563 | 564 |
564 switch (s.fTileModeY) { | 565 switch (s.fTileModeY) { |
565 case SkShader::kClamp_TileMode: | 566 case SkShader::kClamp_TileMode: |
566 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); | 567 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); |
567 break; | 568 break; |
568 case SkShader::kRepeat_TileMode: | 569 case SkShader::kRepeat_TileMode: |
569 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); | 570 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); |
570 break; | 571 break; |
571 case SkShader::kMirror_TileMode: | 572 case SkShader::kMirror_TileMode: |
572 default: | 573 default: |
573 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); | 574 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); |
574 break; | 575 break; |
575 } | 576 } |
576 | 577 |
577 SkASSERT(iY0 == iY2); | 578 SkASSERT(iY0 == iY2); |
578 } | 579 } |
579 #endif | 580 #endif |
580 } | 581 } |
581 | 582 |
582 const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); | 583 const SkPMColor* row0 = s.fPixmap.addr32(0, iY0); |
583 SkPMColor color; | 584 SkPMColor color; |
584 | 585 |
585 if (kNone_SkFilterQuality != s.fFilterLevel) { | 586 if (kNone_SkFilterQuality != s.fFilterLevel) { |
586 const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); | 587 const SkPMColor* row1 = s.fPixmap.addr32(0, iY1); |
587 | 588 |
588 if (s.fAlphaScale < 256) { | 589 if (s.fAlphaScale < 256) { |
589 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); | 590 Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); |
590 } else { | 591 } else { |
591 Filter_32_opaque(iSubY, *row0, *row1, &color); | 592 Filter_32_opaque(iSubY, *row0, *row1, &color); |
592 } | 593 } |
593 } else { | 594 } else { |
594 if (s.fAlphaScale < 256) { | 595 if (s.fAlphaScale < 256) { |
595 color = SkAlphaMulQ(*row0, s.fAlphaScale); | 596 color = SkAlphaMulQ(*row0, s.fAlphaScale); |
596 } else { | 597 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
624 // Since we know we're not filtered, we re-purpose these fields allow | 625 // Since we know we're not filtered, we re-purpose these fields allow |
625 // us to go from device -> src coordinates w/ just an integer add, | 626 // us to go from device -> src coordinates w/ just an integer add, |
626 // rather than running through the inverse-matrix | 627 // rather than running through the inverse-matrix |
627 fFilterOneX = SkScalarFloorToInt(pt.fX); | 628 fFilterOneX = SkScalarFloorToInt(pt.fX); |
628 fFilterOneY = SkScalarFloorToInt(pt.fY); | 629 fFilterOneY = SkScalarFloorToInt(pt.fY); |
629 return true; | 630 return true; |
630 } | 631 } |
631 | 632 |
632 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { | 633 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { |
633 | 634 |
634 if (kN32_SkColorType != fBitmap->colorType()) { | 635 if (kN32_SkColorType != fPixmap.colorType()) { |
635 return NULL; | 636 return NULL; |
636 } | 637 } |
637 | 638 |
638 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M
ask; | 639 static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_M
ask; |
639 | 640 |
640 if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { | 641 if (1 == fPixmap.width() && 0 == (fInvType & ~kMask)) { |
641 if (kNone_SkFilterQuality == fFilterLevel && | 642 if (kNone_SkFilterQuality == fFilterLevel && |
642 fInvType <= SkMatrix::kTranslate_Mask && | 643 fInvType <= SkMatrix::kTranslate_Mask && |
643 !this->setupForTranslate()) { | 644 !this->setupForTranslate()) { |
644 return DoNothing_shaderproc; | 645 return DoNothing_shaderproc; |
645 } | 646 } |
646 return S32_D32_constX_shaderproc; | 647 return S32_D32_constX_shaderproc; |
647 } | 648 } |
648 | 649 |
649 if (fAlphaScale < 256) { | 650 if (fAlphaScale < 256) { |
650 return NULL; | 651 return NULL; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); | 746 void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); |
746 | 747 |
747 // There are four formats possible: | 748 // There are four formats possible: |
748 // scale -vs- affine | 749 // scale -vs- affine |
749 // filter -vs- nofilter | 750 // filter -vs- nofilter |
750 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { | 751 if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { |
751 proc = state.fFilterLevel != kNone_SkFilterQuality ? check_scale_filter
: check_scale_nofilter; | 752 proc = state.fFilterLevel != kNone_SkFilterQuality ? check_scale_filter
: check_scale_nofilter; |
752 } else { | 753 } else { |
753 proc = state.fFilterLevel != kNone_SkFilterQuality ? check_affine_filter
: check_affine_nofilter; | 754 proc = state.fFilterLevel != kNone_SkFilterQuality ? check_affine_filter
: check_affine_nofilter; |
754 } | 755 } |
755 proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); | 756 proc(bitmapXY, count, state.fPixmap.width(), state.fPixmap.height()); |
756 } | 757 } |
757 | 758 |
758 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { | 759 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { |
759 return DebugMatrixProc; | 760 return DebugMatrixProc; |
760 } | 761 } |
761 | 762 |
762 #endif | 763 #endif |
763 | 764 |
764 /////////////////////////////////////////////////////////////////////////////// | 765 /////////////////////////////////////////////////////////////////////////////// |
765 /* | 766 /* |
(...skipping 26 matching lines...) Expand all Loading... |
792 return size; | 793 return size; |
793 } | 794 } |
794 | 795 |
795 /////////////////////// | 796 /////////////////////// |
796 | 797 |
797 void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const SkBitmapProcState& s, in
t x, int y, | 798 void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const SkBitmapProcState& s, in
t x, int y, |
798 SkPMColor* SK_RESTRICT dst, in
t count) { | 799 SkPMColor* SK_RESTRICT dst, in
t count) { |
799 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | | 800 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | |
800 SkMatrix::kScale_Mask)) == 0); | 801 SkMatrix::kScale_Mask)) == 0); |
801 | 802 |
802 const unsigned maxX = s.fBitmap->width() - 1; | 803 const unsigned maxX = s.fPixmap.width() - 1; |
803 SkFractionalInt fx; | 804 SkFractionalInt fx; |
804 int dstY; | 805 int dstY; |
805 { | 806 { |
806 SkPoint pt; | 807 SkPoint pt; |
807 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar
(y) + SK_ScalarHalf, | 808 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar
(y) + SK_ScalarHalf, |
808 &pt); | 809 &pt); |
809 fx = SkScalarToFractionalInt(pt.fY); | 810 fx = SkScalarToFractionalInt(pt.fY); |
810 const unsigned maxY = s.fBitmap->height() - 1; | 811 const unsigned maxY = s.fPixmap.height() - 1; |
811 dstY = SkClampMax(SkFractionalIntToInt(fx), maxY); | 812 dstY = SkClampMax(SkFractionalIntToInt(fx), maxY); |
812 fx = SkScalarToFractionalInt(pt.fX); | 813 fx = SkScalarToFractionalInt(pt.fX); |
813 } | 814 } |
814 | 815 |
815 const SkPMColor* SK_RESTRICT src = s.fBitmap->getAddr32(0, dstY); | 816 const SkPMColor* SK_RESTRICT src = s.fPixmap.addr32(0, dstY); |
816 const SkFractionalInt dx = s.fInvSxFractionalInt; | 817 const SkFractionalInt dx = s.fInvSxFractionalInt; |
817 | 818 |
818 // Check if we're safely inside [0...maxX] so no need to clamp each computed
index. | 819 // Check if we're safely inside [0...maxX] so no need to clamp each computed
index. |
819 // | 820 // |
820 if ((uint64_t)SkFractionalIntToInt(fx) <= maxX && | 821 if ((uint64_t)SkFractionalIntToInt(fx) <= maxX && |
821 (uint64_t)SkFractionalIntToInt(fx + dx * (count - 1)) <= maxX) | 822 (uint64_t)SkFractionalIntToInt(fx + dx * (count - 1)) <= maxX) |
822 { | 823 { |
823 int count4 = count >> 2; | 824 int count4 = count >> 2; |
824 for (int i = 0; i < count4; ++i) { | 825 for (int i = 0; i < count4; ++i) { |
825 SkPMColor src0 = src[SkFractionalIntToInt(fx)]; fx += dx; | 826 SkPMColor src0 = src[SkFractionalIntToInt(fx)]; fx += dx; |
(...skipping 13 matching lines...) Expand all Loading... |
839 fx += dx; | 840 fx += dx; |
840 } | 841 } |
841 } else { | 842 } else { |
842 for (int i = 0; i < count; ++i) { | 843 for (int i = 0; i < count; ++i) { |
843 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; | 844 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; |
844 fx += dx; | 845 fx += dx; |
845 } | 846 } |
846 } | 847 } |
847 } | 848 } |
848 | 849 |
OLD | NEW |