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 |