Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: src/core/SkBitmapProcState.cpp

Issue 470233002: always scale to an integer; compensate for fractional image sizes by leaving the fractional scale i… (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: more git rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | tests/ScaledImageCache.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkBitmapProcState.h ('k') | tests/ScaledImageCache.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698