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