Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "SkBitmapProcState.h" | 8 #include "SkBitmapProcState.h" |
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
| 10 #include "SkFilterProc.h" | 10 #include "SkFilterProc.h" |
| 11 #include "SkPaint.h" | 11 #include "SkPaint.h" |
| 12 #include "SkShader.h" // for tilemodes | 12 #include "SkShader.h" // for tilemodes |
| 13 #include "SkUtilsArm.h" | 13 #include "SkUtilsArm.h" |
| 14 #include "SkBitmapScaler.h" | 14 #include "SkBitmapScaler.h" |
| 15 #include "SkMipMap.h" | 15 #include "SkMipMap.h" |
| 16 #include "SkPixelRef.h" | |
| 16 #include "SkScaledImageCache.h" | 17 #include "SkScaledImageCache.h" |
| 17 | 18 |
| 18 #if !SK_ARM_NEON_IS_NONE | 19 #if !SK_ARM_NEON_IS_NONE |
| 19 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp | 20 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp |
| 20 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; | 21 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; |
| 21 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; | 22 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; |
| 22 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i nt, uint16_t*); | 23 extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, i nt, uint16_t*); |
| 23 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i nt, int, uint16_t*, int); | 24 extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, i nt, int, uint16_t*, int); |
| 24 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); | 25 extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); |
| 25 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint3 2_t*, int, SkPMColor*); | 26 extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint3 2_t*, int, SkPMColor*); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 v2.fX = mat.getSkewX(); | 103 v2.fX = mat.getSkewX(); |
| 103 v2.fY = mat.getScaleY(); | 104 v2.fY = mat.getScaleY(); |
| 104 | 105 |
| 105 return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); | 106 return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); |
| 106 } | 107 } |
| 107 | 108 |
| 108 // TODO -- we may want to pass the clip into this function so we only scale | 109 // TODO -- we may want to pass the clip into this function so we only scale |
| 109 // the portion of the image that we're going to need. This will complicate | 110 // the portion of the image that we're going to need. This will complicate |
| 110 // the interface to the cache, but might be well worth it. | 111 // the interface to the cache, but might be well worth it. |
| 111 | 112 |
| 112 void SkBitmapProcState::possiblyScaleImage() { | 113 bool SkBitmapProcState::possiblyScaleImage() { |
| 114 SkASSERT(NULL == fBitmap); | |
| 115 SkASSERT(NULL == fScaledCacheID); | |
| 113 | 116 |
| 114 if (fFilterLevel <= SkPaint::kLow_FilterLevel) { | 117 if (fFilterLevel <= SkPaint::kLow_FilterLevel) { |
| 115 // none or low (bilerp) does not need to look any further | 118 return false; |
| 116 return; | |
| 117 } | 119 } |
| 118 | 120 |
| 119 // STEP 1: Highest quality direct scale? | |
| 120 | |
| 121 // Check to see if the transformation matrix is simple, and if we're | 121 // Check to see if the transformation matrix is simple, and if we're |
| 122 // doing high quality scaling. If so, do the bitmap scale here and | 122 // doing high quality scaling. If so, do the bitmap scale here and |
| 123 // remove the scaling component from the matrix. | 123 // remove the scaling component from the matrix. |
| 124 | 124 |
| 125 if (SkPaint::kHigh_FilterLevel == fFilterLevel && | 125 if (SkPaint::kHigh_FilterLevel == fFilterLevel && |
| 126 fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Ma sk) && | 126 fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Ma sk) && |
| 127 fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { | 127 fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { |
| 128 | 128 |
| 129 SkScalar invScaleX = fInvMatrix.getScaleX(); | 129 SkScalar invScaleX = fInvMatrix.getScaleX(); |
| 130 SkScalar invScaleY = fInvMatrix.getScaleY(); | 130 SkScalar invScaleY = fInvMatrix.getScaleY(); |
| 131 | 131 |
| 132 SkASSERT(NULL == fScaledCacheID); | |
| 133 fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, | 132 fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, |
| 134 invScaleX, invScaleY, | 133 invScaleX, invScaleY, |
| 135 &fScaledBitmap); | 134 &fScaledBitmap); |
| 136 if (NULL == fScaledCacheID) { | 135 if (NULL == fScaledCacheID) { |
| 137 int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX) ; | 136 int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX) ; |
| 138 int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY ); | 137 int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY ); |
| 139 | 138 |
| 140 // All the criteria are met; let's make a new bitmap. | 139 // All the criteria are met; let's make a new bitmap. |
| 141 | 140 |
| 142 SkConvolutionProcs simd; | 141 SkConvolutionProcs simd; |
| 143 sk_bzero(&simd, sizeof(simd)); | 142 sk_bzero(&simd, sizeof(simd)); |
| 144 this->platformConvolutionProcs(&simd); | 143 this->platformConvolutionProcs(&simd); |
| 145 | 144 |
| 146 if (!SkBitmapScaler::Resize(&fScaledBitmap, | 145 if (!SkBitmapScaler::Resize(&fScaledBitmap, |
| 147 fOrigBitmap, | 146 fOrigBitmap, |
| 148 SkBitmapScaler::RESIZE_BEST, | 147 SkBitmapScaler::RESIZE_BEST, |
| 149 dest_width, | 148 dest_width, |
| 150 dest_height, | 149 dest_height, |
| 151 simd)) { | 150 simd)) { |
| 152 // we failed to create fScaledBitmap, so just return and let | 151 // we failed to create fScaledBitmap, so just return and let |
| 153 // the scanline proc handle it. | 152 // the scanline proc handle it. |
| 154 return; | 153 return true; |
| 155 | 154 |
| 156 } | 155 } |
| 157 fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, | 156 fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, |
| 158 invScaleX, | 157 invScaleX, |
| 159 invScaleY, | 158 invScaleY, |
| 160 fScaledBitmap); | 159 fScaledBitmap); |
| 161 } | 160 } |
| 162 fScaledBitmap.lockPixels(); | 161 fScaledBitmap.lockPixels(); // wonder if Resize() should have locked thi s |
| 163 | |
| 164 fBitmap = &fScaledBitmap; | 162 fBitmap = &fScaledBitmap; |
| 165 | 163 |
| 166 // set the inv matrix type to translate-only; | 164 // set the inv matrix type to translate-only; |
| 167 | |
| 168 fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScale X(), | 165 fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScale X(), |
| 169 fInvMatrix.getTranslateY() / fInvMatrix.getScale Y()); | 166 fInvMatrix.getTranslateY() / fInvMatrix.getScale Y()); |
| 170 | 167 |
| 171 // no need for any further filtering; we just did it! | 168 // no need for any further filtering; we just did it! |
| 172 | |
| 173 fFilterLevel = SkPaint::kNone_FilterLevel; | 169 fFilterLevel = SkPaint::kNone_FilterLevel; |
| 174 | 170 return true; |
| 175 return; | |
| 176 } | 171 } |
| 177 | 172 |
| 178 /* | 173 /* |
| 179 * If we get here, the caller has requested either Med or High filter-level | |
|
scroggo
2013/09/10 18:08:31
Do these comments no longer apply?
| |
| 180 * | |
| 181 * If High, then our special-case for scale-only did not take, and so we | 174 * If High, then our special-case for scale-only did not take, and so we |
| 182 * have to make a choice: | 175 * have to make a choice: |
| 183 * 1. fall back on mipmaps + bilerp | 176 * 1. fall back on mipmaps + bilerp |
| 184 * 2. fall back on scanline bicubic filter | 177 * 2. fall back on scanline bicubic filter |
| 185 * For now, we compute the "scale" value from the matrix, and have a | 178 * For now, we compute the "scale" value from the matrix, and have a |
| 186 * threshold to decide when bicubic is better, and when mips are better. | 179 * threshold to decide when bicubic is better, and when mips are better. |
| 187 * No doubt a fancier decision tree could be used uere. | 180 * No doubt a fancier decision tree could be used uere. |
| 188 * | 181 * |
| 189 * If Medium, then we just try to build a mipmap and select a level, | 182 * If Medium, then we just try to build a mipmap and select a level, |
| 190 * setting the filter-level to kLow to signal that we just need bilerp | 183 * setting the filter-level to kLow to signal that we just need bilerp |
| 191 * to process the selected level. | 184 * to process the selected level. |
| 192 */ | 185 */ |
| 193 | 186 |
| 194 SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); | 187 SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); |
| 195 | 188 |
| 196 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { | 189 if (SkPaint::kHigh_FilterLevel == fFilterLevel) { |
| 197 // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller | 190 // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller |
| 198 // than this, then the mipmaps quality may be greater (certainly faster) | 191 // than this, then the mipmaps quality may be greater (certainly faster) |
| 199 // so we only keep High quality if the scale is greater than this. | 192 // so we only keep High quality if the scale is greater than this. |
| 200 // | 193 // |
| 201 // Since we're dealing with the inverse, we compare against its inverse. | 194 // Since we're dealing with the inverse, we compare against its inverse. |
| 202 const SkScalar bicubicLimit = SkFloatToScalar(4.0f); | 195 const SkScalar bicubicLimit = SkFloatToScalar(4.0f); |
| 203 const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; | 196 const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; |
| 204 if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline | 197 if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline |
| 205 return; | 198 return false; |
| 206 } | 199 } |
| 207 | 200 |
| 208 // else set the filter-level to Medium, since we're scaling down and | 201 // else set the filter-level to Medium, since we're scaling down and |
| 209 // want to reqeust mipmaps | 202 // want to reqeust mipmaps |
| 210 fFilterLevel = SkPaint::kMedium_FilterLevel; | 203 fFilterLevel = SkPaint::kMedium_FilterLevel; |
| 211 } | 204 } |
| 212 | 205 |
| 213 SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); | 206 SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); |
| 214 | 207 |
| 215 /** | 208 /** |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 240 SkMipMap::Level level; | 233 SkMipMap::Level level; |
| 241 if (mip->extractLevel(levelScale, &level)) { | 234 if (mip->extractLevel(levelScale, &level)) { |
| 242 SkScalar invScaleFixup = level.fScale; | 235 SkScalar invScaleFixup = level.fScale; |
| 243 fInvMatrix.postScale(invScaleFixup, invScaleFixup); | 236 fInvMatrix.postScale(invScaleFixup, invScaleFixup); |
| 244 | 237 |
| 245 fScaledBitmap.setConfig(fOrigBitmap.config(), | 238 fScaledBitmap.setConfig(fOrigBitmap.config(), |
| 246 level.fWidth, level.fHeight, | 239 level.fWidth, level.fHeight, |
| 247 level.fRowBytes); | 240 level.fRowBytes); |
| 248 fScaledBitmap.setPixels(level.fPixels); | 241 fScaledBitmap.setPixels(level.fPixels); |
| 249 fBitmap = &fScaledBitmap; | 242 fBitmap = &fScaledBitmap; |
| 243 fFilterLevel = SkPaint::kLow_FilterLevel; | |
| 244 return true; | |
| 250 } | 245 } |
| 251 } | 246 } |
| 252 } | 247 } |
| 253 | 248 |
| 254 /* | 249 return false; |
| 255 * At this point, we may or may not have built a mipmap. Regardless, we | 250 } |
| 256 * now fall back on Low so will bilerp whatever fBitmap now points at. | 251 |
| 257 */ | 252 static bool decodeInto(const SkBitmap& src, int pow2, SkBitmap* dst) { |
|
scroggo
2013/09/10 18:08:31
Style nit: decode_into
reed1
2013/09/10 20:28:11
Done.
| |
| 258 fFilterLevel = SkPaint::kLow_FilterLevel; | 253 // new way to decodeInto... |
|
scroggo
2013/09/10 18:08:31
This appears to be a change in behavior: if !mip |
|
scroggo
2013/09/10 18:08:31
Should there be some more explicit comments, eg FI
reed1
2013/09/10 20:28:11
Done.
|
| 254 SkPixelRef* pr = src.pixelRef(); | |
| 255 if (pr && pr->decodeInto(pow2, dst)) { | |
| 256 return true; | |
| 257 } | |
| 258 | |
| 259 // olde school impl... ignores pow2 | |
| 260 src.lockPixels(); | |
| 261 if (!src.getPixels()) { | |
| 262 return false; | |
| 263 } | |
| 264 *dst = src; | |
| 265 dst->lockPixels(); | |
| 266 src.unlockPixels(); | |
| 267 return SkToBool(dst->getPixels()); | |
| 268 } | |
| 269 | |
| 270 bool SkBitmapProcState::lockBaseBitmap() { | |
|
scroggo
2013/09/10 18:08:31
Will this function become more general to lock oth
reed1
2013/09/10 20:28:11
I think not. I think that functionality belongs in
| |
| 271 fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, | |
| 272 SK_Scalar1, SK_Scalar1, | |
| 273 &fScaledBitmap); | |
| 274 if (NULL == fScaledCacheID) { | |
| 275 if (!decodeInto(fOrigBitmap, 0, &fScaledBitmap)) { | |
| 276 return false; | |
| 277 } | |
| 278 | |
| 279 fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, | |
| 280 SK_Scalar1, SK_Scalar1, | |
| 281 fScaledBitmap); | |
| 282 if (!fScaledCacheID) { | |
| 283 fScaledBitmap.reset(); | |
| 284 return false; | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 fScaledBitmap.lockPixels(); // just 'cause the cache made a copy :( | |
| 289 fBitmap = &fScaledBitmap; | |
| 290 return true; | |
| 259 } | 291 } |
| 260 | 292 |
| 261 void SkBitmapProcState::endContext() { | 293 void SkBitmapProcState::endContext() { |
| 262 SkDELETE(fBitmapFilter); | 294 SkDELETE(fBitmapFilter); |
| 263 fBitmapFilter = NULL; | 295 fBitmapFilter = NULL; |
| 264 fScaledBitmap.reset(); | 296 fScaledBitmap.reset(); |
| 265 | 297 |
| 266 if (fScaledCacheID) { | 298 if (fScaledCacheID) { |
| 267 SkScaledImageCache::Unlock(fScaledCacheID); | 299 SkScaledImageCache::Unlock(fScaledCacheID); |
| 268 fScaledCacheID = NULL; | 300 fScaledCacheID = NULL; |
| 269 } | 301 } |
| 270 } | 302 } |
| 271 | 303 |
| 272 SkBitmapProcState::~SkBitmapProcState() { | 304 SkBitmapProcState::~SkBitmapProcState() { |
| 273 if (fScaledCacheID) { | 305 if (fScaledCacheID) { |
| 274 SkScaledImageCache::Unlock(fScaledCacheID); | 306 SkScaledImageCache::Unlock(fScaledCacheID); |
| 275 } | 307 } |
| 276 SkDELETE(fBitmapFilter); | 308 SkDELETE(fBitmapFilter); |
| 277 } | 309 } |
| 278 | 310 |
| 279 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { | 311 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { |
| 280 if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { | 312 SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); |
| 281 return false; | |
| 282 } | |
| 283 | 313 |
| 284 fBitmap = &fOrigBitmap; | 314 fBitmap = NULL; |
| 285 fInvMatrix = inv; | 315 fInvMatrix = inv; |
| 286 | |
| 287 // initialize our filter quality to the one requested by the caller. | |
| 288 // We may downgrade it later if we determine that we either don't need | |
| 289 // or can't provide as high a quality filtering as the user requested. | |
| 290 | |
| 291 fFilterLevel = paint.getFilterLevel(); | 316 fFilterLevel = paint.getFilterLevel(); |
| 292 | 317 |
| 293 // possiblyScaleImage will look to see if it can rescale the image as a | 318 // possiblyScaleImage will look to see if it can rescale the image as a |
| 294 // preprocess; either by scaling up to the target size, or by selecting | 319 // preprocess; either by scaling up to the target size, or by selecting |
| 295 // a nearby mipmap level. If it does, it will adjust the working | 320 // a nearby mipmap level. If it does, it will adjust the working |
| 296 // matrix as well as the working bitmap. It may also adjust the filter | 321 // matrix as well as the working bitmap. It may also adjust the filter |
| 297 // quality to avoid re-filtering an already perfectly scaled image. | 322 // quality to avoid re-filtering an already perfectly scaled image. |
| 298 | 323 if (!this->possiblyScaleImage()) { |
| 299 this->possiblyScaleImage(); | 324 if (!this->lockBaseBitmap()) { |
| 325 return false; | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 SkASSERT(fBitmap); | |
| 300 | 330 |
| 301 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; | 331 bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; |
| 302 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && | 332 bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && |
| 303 SkShader::kClamp_TileMode == fTileModeY; | 333 SkShader::kClamp_TileMode == fTileModeY; |
| 304 | 334 |
| 305 if (!(clampClamp || trivialMatrix)) { | 335 if (!(clampClamp || trivialMatrix)) { |
| 306 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); | 336 fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); |
| 307 } | 337 } |
| 308 | 338 |
| 309 // Now that all possible changes to the matrix have taken place, check | 339 // Now that all possible changes to the matrix have taken place, check |
| 310 // to see if we're really close to a no-scale matrix. If so, explicitly | 340 // to see if we're really close to a no-scale matrix. If so, explicitly |
| 311 // set it to be so. Subsequent code may inspect this matrix to choose | 341 // set it to be so. Subsequent code may inspect this matrix to choose |
| 312 // a faster path in this case. | 342 // a faster path in this case. |
| 313 | 343 |
| 314 // This code will only execute if the matrix has some scale component; | 344 // This code will only execute if the matrix has some scale component; |
| 315 // if it's already pure translate then we won't do this inversion. | 345 // if it's already pure translate then we won't do this inversion. |
| 316 | 346 |
| 317 if (matrix_only_scale_translate(fInvMatrix)) { | 347 if (matrix_only_scale_translate(fInvMatrix)) { |
| 318 SkMatrix forward; | 348 SkMatrix forward; |
| 319 if (fInvMatrix.invert(&forward)) { | 349 if (fInvMatrix.invert(&forward)) { |
| 320 if (clampClamp ? just_trans_clamp(forward, *fBitmap) | 350 if (clampClamp ? just_trans_clamp(forward, *fBitmap) |
| 321 : just_trans_general(forward)) { | 351 : just_trans_general(forward)) { |
| 322 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); | 352 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); |
| 323 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); | 353 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); |
| 324 fInvMatrix.setTranslate(tx, ty); | 354 fInvMatrix.setTranslate(tx, ty); |
| 325 | |
| 326 } | 355 } |
| 327 } | 356 } |
| 328 } | 357 } |
| 329 | 358 |
| 330 fInvProc = fInvMatrix.getMapXYProc(); | 359 fInvProc = fInvMatrix.getMapXYProc(); |
| 331 fInvType = fInvMatrix.getType(); | 360 fInvType = fInvMatrix.getType(); |
| 332 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); | 361 fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); |
| 333 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); | 362 fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); |
| 334 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); | 363 fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); |
| 335 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); | 364 fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 } else { | 961 } else { |
| 933 size >>= 2; | 962 size >>= 2; |
| 934 } | 963 } |
| 935 | 964 |
| 936 if (fFilterLevel != SkPaint::kNone_FilterLevel) { | 965 if (fFilterLevel != SkPaint::kNone_FilterLevel) { |
| 937 size >>= 1; | 966 size >>= 1; |
| 938 } | 967 } |
| 939 | 968 |
| 940 return size; | 969 return size; |
| 941 } | 970 } |
| OLD | NEW |