| 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 "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); | 142 < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); |
| 143 } | 143 } |
| 144 | 144 |
| 145 // TODO -- we may want to pass the clip into this function so we only scale | 145 // TODO -- we may want to pass the clip into this function so we only scale |
| 146 // the portion of the image that we're going to need. This will complicate | 146 // the portion of the image that we're going to need. This will complicate |
| 147 // the interface to the cache, but might be well worth it. | 147 // the interface to the cache, but might be well worth it. |
| 148 | 148 |
| 149 bool SkBitmapProcState::possiblyScaleImage() { | 149 bool SkBitmapProcState::possiblyScaleImage() { |
| 150 SkASSERT(NULL == fBitmap); | 150 SkASSERT(NULL == fBitmap); |
| 151 | 151 |
| 152 fAdjustedMatrix = false; |
| 153 |
| 152 if (fFilterLevel <= SkPaint::kLow_FilterLevel) { | 154 if (fFilterLevel <= SkPaint::kLow_FilterLevel) { |
| 153 return false; | 155 return false; |
| 154 } | 156 } |
| 155 // Check to see if the transformation matrix is simple, and if we're | 157 // Check to see if the transformation matrix is simple, and if we're |
| 156 // doing high quality scaling. If so, do the bitmap scale here and | 158 // doing high quality scaling. If so, do the bitmap scale here and |
| 157 // remove the scaling component from the matrix. | 159 // remove the (non-fractional) scaling component from the matrix. |
| 160 |
| 161 SkScalar invScaleX = fInvMatrix.getScaleX(); |
| 162 SkScalar invScaleY = fInvMatrix.getScaleY(); |
| 163 |
| 164 float trueDestWidth = fOrigBitmap.width() / invScaleX; |
| 165 float trueDestHeight = fOrigBitmap.height() / invScaleY; |
| 166 |
| 167 #ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING |
| 168 float roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); |
| 169 float roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); |
| 170 #else |
| 171 float roundedDestWidth = trueDestWidth; |
| 172 float roundedDestHeight = trueDestHeight; |
| 173 #endif |
| 158 | 174 |
| 159 if (SkPaint::kHigh_FilterLevel == fFilterLevel && | 175 if (SkPaint::kHigh_FilterLevel == fFilterLevel && |
| 160 fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Ma
sk) && | 176 fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Ma
sk) && |
| 161 kN32_SkColorType == fOrigBitmap.colorType() && | 177 kN32_SkColorType == fOrigBitmap.colorType() && |
| 162 cache_size_okay(fOrigBitmap, fInvMatrix)) { | 178 cache_size_okay(fOrigBitmap, fInvMatrix)) { |
| 163 | 179 |
| 164 SkScalar invScaleX = fInvMatrix.getScaleX(); | |
| 165 SkScalar invScaleY = fInvMatrix.getScaleY(); | |
| 166 | |
| 167 if (SkScalarNearlyEqual(invScaleX,1.0f) && | 180 if (SkScalarNearlyEqual(invScaleX,1.0f) && |
| 168 SkScalarNearlyEqual(invScaleY,1.0f)) { | 181 SkScalarNearlyEqual(invScaleY,1.0f)) { |
| 169 // short-circuit identity scaling; the output is supposed to | 182 // short-circuit identity scaling; the output is supposed to |
| 170 // be the same as the input, so we might as well go fast. | 183 // be the same as the input, so we might as well go fast. |
| 171 | 184 |
| 172 // Note(humper): We could also probably do this if the scales | 185 // Note(humper): We could also probably do this if the scales |
| 173 // are close to -1 as well, since the flip doesn't require | 186 // are close to -1 as well, since the flip doesn't require |
| 174 // any fancy re-sampling... | 187 // any fancy re-sampling... |
| 175 | 188 |
| 176 // Set our filter level to low -- the only post-filtering this | 189 // Set our filter level to low -- the only post-filtering this |
| 177 // image might require is some interpolation if the translation | 190 // image might require is some interpolation if the translation |
| 178 // is fractional. | 191 // is fractional. |
| 179 fFilterLevel = SkPaint::kLow_FilterLevel; | 192 fFilterLevel = SkPaint::kLow_FilterLevel; |
| 180 return false; | 193 return false; |
| 181 } | 194 } |
| 182 | 195 |
| 183 if (!SkBitmapCache::Find(fOrigBitmap, invScaleX, invScaleY, &fScaledBitm
ap)) { | 196 if (!SkBitmapCache::Find(fOrigBitmap, roundedDestWidth, roundedDestHeigh
t, &fScaledBitmap)) { |
| 184 float dest_width = fOrigBitmap.width() / invScaleX; | |
| 185 float dest_height = fOrigBitmap.height() / invScaleY; | |
| 186 | |
| 187 // All the criteria are met; let's make a new bitmap. | 197 // All the criteria are met; let's make a new bitmap. |
| 188 | 198 |
| 189 if (!SkBitmapScaler::Resize(&fScaledBitmap, | 199 if (!SkBitmapScaler::Resize(&fScaledBitmap, |
| 190 fOrigBitmap, | 200 fOrigBitmap, |
| 191 SkBitmapScaler::RESIZE_BEST, | 201 SkBitmapScaler::RESIZE_BEST, |
| 192 dest_width, | 202 roundedDestWidth, |
| 193 dest_height, | 203 roundedDestHeight, |
| 194 SkScaledImageCache::GetAllocator())) { | 204 SkScaledImageCache::GetAllocator())) { |
| 195 // we failed to create fScaledBitmap, so just return and let | 205 // we failed to create fScaledBitmap, so just return and let |
| 196 // the scanline proc handle it. | 206 // the scanline proc handle it. |
| 197 return false; | 207 return false; |
| 198 | 208 |
| 199 } | 209 } |
| 200 | 210 |
| 201 SkASSERT(NULL != fScaledBitmap.getPixels()); | 211 SkASSERT(NULL != fScaledBitmap.getPixels()); |
| 202 SkBitmapCache::Add(fOrigBitmap, invScaleX, invScaleY, fScaledBitmap)
; | 212 SkBitmapCache::Add(fOrigBitmap, roundedDestWidth, roundedDestHeight,
fScaledBitmap); |
| 203 } | 213 } |
| 204 | 214 |
| 205 SkASSERT(NULL != fScaledBitmap.getPixels()); | 215 SkASSERT(NULL != fScaledBitmap.getPixels()); |
| 206 fBitmap = &fScaledBitmap; | 216 fBitmap = &fScaledBitmap; |
| 207 | 217 |
| 208 // set the inv matrix type to translate-only; | 218 // set the inv matrix type to translate-only; |
| 209 fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScale
X(), | 219 fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScale
X(), |
| 210 fInvMatrix.getTranslateY() / fInvMatrix.getScale
Y()); | 220 fInvMatrix.getTranslateY() / fInvMatrix.getScale
Y()); |
| 211 | 221 |
| 222 #ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING |
| 223 // reintroduce any fractional scaling missed by our integral scale done
above. |
| 224 |
| 225 float fractionalScaleX = trueDestWidth/roundedDestWidth; |
| 226 float fractionalScaleY = trueDestHeight/roundedDestHeight; |
| 227 |
| 228 fInvMatrix.postScale(fractionalScaleX, fractionalScaleY); |
| 229 #endif |
| 230 fAdjustedMatrix = true; |
| 231 |
| 212 // Set our filter level to low -- the only post-filtering this | 232 // Set our filter level to low -- the only post-filtering this |
| 213 // image might require is some interpolation if the translation | 233 // image might require is some interpolation if the translation |
| 214 // is fractional. | 234 // is fractional or if there's any remaining scaling to be done. |
| 215 fFilterLevel = SkPaint::kLow_FilterLevel; | 235 fFilterLevel = SkPaint::kLow_FilterLevel; |
| 216 return true; | 236 return true; |
| 217 } | 237 } |
| 218 | 238 |
| 219 /* | 239 /* |
| 220 * If High, then our special-case for scale-only did not take, and so we | 240 * If High, then our special-case for scale-only did not take, and so we |
| 221 * have to make a choice: | 241 * have to make a choice: |
| 222 * 1. fall back on mipmaps + bilerp | 242 * 1. fall back on mipmaps + bilerp |
| 223 * 2. fall back on scanline bicubic filter | 243 * 2. fall back on scanline bicubic filter |
| 224 * For now, we compute the "scale" value from the matrix, and have a | 244 * For now, we compute the "scale" value from the matrix, and have a |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, | 380 // If we are "still" kMedium_FilterLevel, then the request was not fulfilled
by possiblyScale, |
| 361 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) | 381 // so we downgrade to kLow (so the rest of the sniffing code can assume that
) |
| 362 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { | 382 if (SkPaint::kMedium_FilterLevel == fFilterLevel) { |
| 363 fFilterLevel = SkPaint::kLow_FilterLevel; | 383 fFilterLevel = SkPaint::kLow_FilterLevel; |
| 364 } | 384 } |
| 365 | 385 |
| 366 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; | 386 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) ==
0; |
| 367 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 387 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
| 368 SkShader::kClamp_TileMode == fTileModeY; | 388 SkShader::kClamp_TileMode == fTileModeY; |
| 369 | 389 |
| 370 if (!(clampClamp || trivialMatrix)) { | 390 if (!(fAdjustedMatrix || clampClamp || trivialMatrix)) { |
| 371 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | 391 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
| 372 } | 392 } |
| 373 | 393 |
| 374 // Now that all possible changes to the matrix have taken place, check | 394 // Now that all possible changes to the matrix have taken place, check |
| 375 // to see if we're really close to a no-scale matrix. If so, explicitly | 395 // to see if we're really close to a no-scale matrix. If so, explicitly |
| 376 // set it to be so. Subsequent code may inspect this matrix to choose | 396 // set it to be so. Subsequent code may inspect this matrix to choose |
| 377 // a faster path in this case. | 397 // a faster path in this case. |
| 378 | 398 |
| 379 // This code will only execute if the matrix has some scale component; | 399 // This code will only execute if the matrix has some scale component; |
| 380 // if it's already pure translate then we won't do this inversion. | 400 // if it's already pure translate then we won't do this inversion. |
| (...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 } else { | 1027 } else { |
| 1008 size >>= 2; | 1028 size >>= 2; |
| 1009 } | 1029 } |
| 1010 | 1030 |
| 1011 if (fFilterLevel != SkPaint::kNone_FilterLevel) { | 1031 if (fFilterLevel != SkPaint::kNone_FilterLevel) { |
| 1012 size >>= 1; | 1032 size >>= 1; |
| 1013 } | 1033 } |
| 1014 | 1034 |
| 1015 return size; | 1035 return size; |
| 1016 } | 1036 } |
| OLD | NEW |