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