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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 91 } |
92 | 92 |
93 /////////////////////////////////////////////////////////////////////////////// | 93 /////////////////////////////////////////////////////////////////////////////// |
94 | 94 |
95 static bool valid_for_filtering(unsigned dimension) { | 95 static bool valid_for_filtering(unsigned dimension) { |
96 // for filtering, width and height must fit in 14bits, since we use steal | 96 // for filtering, width and height must fit in 14bits, since we use steal |
97 // 2 bits from each to store our 4bit subpixel data | 97 // 2 bits from each to store our 4bit subpixel data |
98 return (dimension & ~0x3FFF) == 0; | 98 return (dimension & ~0x3FFF) == 0; |
99 } | 99 } |
100 | 100 |
| 101 static SkScalar effective_matrix_scale(const SkMatrix& mat) { |
| 102 SkScalar dx = SkVector::Length(mat.getScaleX(), mat.getSkewY()); |
| 103 SkScalar dy = SkVector::Length(mat.getSkewX(), mat.getScaleY()); |
| 104 return SkScalarSqrt(dx * dy); |
| 105 } |
| 106 |
101 // Check to see that the size of the bitmap that would be produced by | 107 // Check to see that the size of the bitmap that would be produced by |
102 // scaling by the given inverted matrix is less than the maximum allowed. | 108 // scaling by the given inverted matrix is less than the maximum allowed. |
103 static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { | 109 static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { |
104 size_t maximumAllocation = SkResourceCache::GetEffectiveSingleAllocationByte
Limit(); | 110 size_t maximumAllocation = SkResourceCache::GetEffectiveSingleAllocationByte
Limit(); |
105 if (0 == maximumAllocation) { | 111 if (0 == maximumAllocation) { |
106 return true; | 112 return true; |
107 } | 113 } |
108 // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); | 114 // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY); |
109 // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); | 115 // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize); |
110 // Skip the division step: | 116 // Skip the division step: |
111 return bm.info().getSafeSize(bm.info().minRowBytes()) | 117 return bm.info().getSafeSize(bm.info().minRowBytes()) |
112 < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); | 118 < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY()); |
113 } | 119 } |
114 | 120 |
115 /* | 121 /* |
| 122 * Extract the "best" scale factors from a matrix. |
| 123 */ |
| 124 static bool extract_scale(const SkMatrix& matrix, SkVector* scale) { |
| 125 SkASSERT(!matrix.hasPerspective()); |
| 126 SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::k
MSkewY]); |
| 127 SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::k
MScaleY]); |
| 128 if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) || |
| 129 SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) |
| 130 { |
| 131 return false; |
| 132 } |
| 133 scale->set(sx, sy); |
| 134 return true; |
| 135 } |
| 136 |
| 137 /* |
116 * High quality is implemented by performing up-right scale-only filtering and
then | 138 * High quality is implemented by performing up-right scale-only filtering and
then |
117 * using bilerp for any remaining transformations. | 139 * using bilerp for any remaining transformations. |
118 */ | 140 */ |
119 void SkBitmapProcState::processHQRequest() { | 141 void SkBitmapProcState::processHQRequest() { |
120 SkASSERT(kHigh_SkFilterQuality == fFilterLevel); | 142 SkASSERT(kHigh_SkFilterQuality == fFilterLevel); |
121 | 143 |
122 // Our default return state is to downgrade the request to Medium, w/ or w/o
setting fBitmap | 144 // Our default return state is to downgrade the request to Medium, w/ or w/o
setting fBitmap |
123 // to a valid bitmap. If we succeed, we will set this to Low instead. | 145 // to a valid bitmap. If we succeed, we will set this to Low instead. |
124 fFilterLevel = kMedium_SkFilterQuality; | 146 fFilterLevel = kMedium_SkFilterQuality; |
125 | 147 |
126 if (kN32_SkColorType != fOrigBitmap.colorType() || !cache_size_okay(fOrigBit
map, fInvMatrix) || | 148 if (kN32_SkColorType != fOrigBitmap.colorType() || !cache_size_okay(fOrigBit
map, fInvMatrix) || |
127 fInvMatrix.hasPerspective()) | 149 fInvMatrix.hasPerspective()) |
128 { | 150 { |
129 return; // can't handle the reqeust | 151 return; // can't handle the reqeust |
130 } | 152 } |
131 | 153 |
132 SkScalar invScaleX = fInvMatrix.getScaleX(); | 154 SkScalar invScaleX = fInvMatrix.getScaleX(); |
133 SkScalar invScaleY = fInvMatrix.getScaleY(); | 155 SkScalar invScaleY = fInvMatrix.getScaleY(); |
134 if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) { | 156 if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) { |
135 SkSize scale; | 157 SkVector scale; |
136 if (!fInvMatrix.decomposeScale(&scale)) { | 158 if (!extract_scale(fInvMatrix, &scale)) { |
137 return; | 159 return; // can't find suitable scale factors |
138 } | 160 } |
139 invScaleX = scale.width(); | 161 invScaleX = scale.x(); |
140 invScaleY = scale.height(); | 162 invScaleY = scale.y(); |
141 } | 163 } |
142 if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1))
{ | 164 if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1))
{ |
143 return; // no need for HQ | 165 return; // no need for HQ |
144 } | 166 } |
145 | 167 |
146 SkScalar trueDestWidth = fOrigBitmap.width() / invScaleX; | 168 SkScalar trueDestWidth = fOrigBitmap.width() / invScaleX; |
147 SkScalar trueDestHeight = fOrigBitmap.height() / invScaleY; | 169 SkScalar trueDestHeight = fOrigBitmap.height() / invScaleY; |
148 SkScalar roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); | 170 SkScalar roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); |
149 SkScalar roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); | 171 SkScalar roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); |
150 | 172 |
(...skipping 24 matching lines...) Expand all Loading... |
175 * Modulo internal errors, this should always succeed *if* the matrix is downsc
aling | 197 * Modulo internal errors, this should always succeed *if* the matrix is downsc
aling |
176 * (in this case, we have the inverse, so it succeeds if fInvMatrix is upscalin
g) | 198 * (in this case, we have the inverse, so it succeeds if fInvMatrix is upscalin
g) |
177 */ | 199 */ |
178 void SkBitmapProcState::processMediumRequest() { | 200 void SkBitmapProcState::processMediumRequest() { |
179 SkASSERT(kMedium_SkFilterQuality == fFilterLevel); | 201 SkASSERT(kMedium_SkFilterQuality == fFilterLevel); |
180 | 202 |
181 // Our default return state is to downgrade the request to Low, w/ or w/o se
tting fBitmap | 203 // Our default return state is to downgrade the request to Low, w/ or w/o se
tting fBitmap |
182 // to a valid bitmap. | 204 // to a valid bitmap. |
183 fFilterLevel = kLow_SkFilterQuality; | 205 fFilterLevel = kLow_SkFilterQuality; |
184 | 206 |
185 SkSize invScaleSize; | 207 SkScalar invScale = effective_matrix_scale(fInvMatrix); |
186 if (!fInvMatrix.decomposeScale(&invScaleSize, NULL)) { | |
187 return; | |
188 } | |
189 SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height(
)); | |
190 | 208 |
191 if (invScale > SK_Scalar1) { | 209 if (invScale > SK_Scalar1) { |
192 fCurrMip.reset(SkMipMapCache::FindAndRef(fOrigBitmap)); | 210 fCurrMip.reset(SkMipMapCache::FindAndRef(fOrigBitmap)); |
193 if (NULL == fCurrMip.get()) { | 211 if (NULL == fCurrMip.get()) { |
194 fCurrMip.reset(SkMipMapCache::AddAndRef(fOrigBitmap)); | 212 fCurrMip.reset(SkMipMapCache::AddAndRef(fOrigBitmap)); |
195 if (NULL == fCurrMip.get()) { | 213 if (NULL == fCurrMip.get()) { |
196 return; | 214 return; |
197 } | 215 } |
198 } | 216 } |
199 // diagnostic for a crasher... | 217 // diagnostic for a crasher... |
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 fx += dx; | 1014 fx += dx; |
997 } | 1015 } |
998 } else { | 1016 } else { |
999 for (int i = 0; i < count; ++i) { | 1017 for (int i = 0; i < count; ++i) { |
1000 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; | 1018 dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)]; |
1001 fx += dx; | 1019 fx += dx; |
1002 } | 1020 } |
1003 } | 1021 } |
1004 } | 1022 } |
1005 | 1023 |
OLD | NEW |