| 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 |