OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
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 | 8 |
9 | 9 |
10 #include "SkBlurMask.h" | 10 #include "SkBlurMask.h" |
(...skipping 1167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 | 1178 |
1179 if ( x > 0.5f ) { | 1179 if ( x > 0.5f ) { |
1180 return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f * x); | 1180 return 0.5625f - (x3 / 6.0f - 3.0f * x2 * 0.25f + 1.125f * x); |
1181 } | 1181 } |
1182 if ( x > -0.5f ) { | 1182 if ( x > -0.5f ) { |
1183 return 0.5f - (0.75f * x - x3 / 3.0f); | 1183 return 0.5f - (0.75f * x - x3 / 3.0f); |
1184 } | 1184 } |
1185 return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); | 1185 return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x); |
1186 } | 1186 } |
1187 | 1187 |
| 1188 /* Compute the size of the array allocated for the |
| 1189 profile. |
| 1190 */ |
| 1191 |
| 1192 static int compute_profile_size(SkScalar radius) { |
| 1193 return SkScalarRoundToInt(radius * 3); |
| 1194 |
| 1195 } |
| 1196 |
1188 /* | 1197 /* |
1189 compute_profile allocates and fills in an array of floating | 1198 compute_profile allocates and fills in an array of floating |
1190 point values between 0 and 255 for the profile signature of | 1199 point values between 0 and 255 for the profile signature of |
1191 a blurred half-plane with the given blur radius. Since we're | 1200 a blurred half-plane with the given blur radius. Since we're |
1192 going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) | 1201 going to be doing screened multiplications (i.e., 1 - (1-x)(1-y)) |
1193 all the time, we actually fill in the profile pre-inverted | 1202 all the time, we actually fill in the profile pre-inverted |
1194 (already done 255-x). | 1203 (already done 255-x). |
1195 | 1204 |
1196 The function returns the size of the array allocated for the | 1205 It's the responsibility of the caller to delete the |
1197 profile. It's the responsibility of the caller to delete the | |
1198 memory returned in profile_out. | 1206 memory returned in profile_out. |
1199 */ | 1207 */ |
1200 | 1208 |
1201 static int compute_profile(SkScalar radius, unsigned int **profile_out) { | 1209 static void compute_profile(SkScalar radius, unsigned int **profile_out) { |
1202 int size = SkScalarRoundToInt(radius * 3); | 1210 int size = compute_profile_size(radius); |
| 1211 |
1203 int center = size >> 1; | 1212 int center = size >> 1; |
1204 | |
1205 unsigned int *profile = SkNEW_ARRAY(unsigned int, size); | 1213 unsigned int *profile = SkNEW_ARRAY(unsigned int, size); |
1206 | 1214 |
1207 float invr = 1.f/radius; | 1215 float invr = 1.f/radius; |
1208 | 1216 |
1209 profile[0] = 255; | 1217 profile[0] = 255; |
1210 for (int x = 1 ; x < size ; ++x) { | 1218 for (int x = 1 ; x < size ; ++x) { |
1211 float scaled_x = (center - x - .5f) * invr; | 1219 float scaled_x = (center - x - .5f) * invr; |
1212 float gi = gaussianIntegral(scaled_x); | 1220 float gi = gaussianIntegral(scaled_x); |
1213 profile[x] = 255 - (uint8_t) (255.f * gi); | 1221 profile[x] = 255 - (uint8_t) (255.f * gi); |
1214 } | 1222 } |
1215 | 1223 |
1216 *profile_out = profile; | 1224 *profile_out = profile; |
1217 return size; | |
1218 } | 1225 } |
1219 | 1226 |
1220 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for | 1227 // TODO MAYBE: Maintain a profile cache to avoid recomputing this for |
1221 // commonly used radii. Consider baking some of the most common blur radii | 1228 // commonly used radii. Consider baking some of the most common blur radii |
1222 // directly in as static data? | 1229 // directly in as static data? |
1223 | 1230 |
1224 // Implementation adapted from Michael Herf's approach: | 1231 // Implementation adapted from Michael Herf's approach: |
1225 // http://stereopsis.com/shadowrect/ | 1232 // http://stereopsis.com/shadowrect/ |
1226 | 1233 |
1227 static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
lurred_width, int sharp_width ) { | 1234 static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
lurred_width, int sharp_width ) { |
1228 int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far
are we from the original edge? | 1235 int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far
are we from the original edge? |
1229 int ox = dx >> 1; | 1236 int ox = dx >> 1; |
1230 if (ox < 0) { | 1237 if (ox < 0) { |
1231 ox = 0; | 1238 ox = 0; |
1232 } | 1239 } |
1233 | 1240 |
1234 return profile[ox]; | 1241 return profile[ox]; |
1235 } | 1242 } |
1236 | 1243 |
1237 bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src, | 1244 bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src, |
1238 SkScalar provided_radius, Style style, | 1245 SkScalar provided_radius, Style style, |
1239 SkIPoint *margin) { | 1246 SkIPoint *margin, SkMask::CreateMode createMode) { |
1240 int profile_size; | 1247 int profile_size; |
1241 unsigned int *profile; | |
1242 | 1248 |
1243 float radius = SkScalarToFloat( SkScalarMul( provided_radius, kBlurRadiusFud
geFactor ) ); | 1249 float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudge
Factor)); |
1244 | 1250 |
1245 // adjust blur radius to match interpretation from boxfilter code | 1251 // adjust blur radius to match interpretation from boxfilter code |
1246 radius = (radius + .5f) *2.f; | 1252 radius = (radius + .5f) * 2.f; |
1247 | 1253 |
1248 profile_size = compute_profile( radius, &profile ); | 1254 profile_size = compute_profile_size(radius); |
1249 | 1255 |
1250 SkAutoTDeleteArray<unsigned int> ada(profile); | |
1251 | |
1252 int pad = profile_size/2; | 1256 int pad = profile_size/2; |
1253 if (margin) { | 1257 if (margin) { |
1254 margin->set( pad, pad ); | 1258 margin->set( pad, pad ); |
1255 } | 1259 } |
1256 | 1260 |
1257 int shadow_left = -pad; | 1261 int shadow_left = -pad; |
1258 int shadow_top = -pad; | 1262 int shadow_top = -pad; |
1259 int shadow_right = (int)(src.width()) + pad; | 1263 int shadow_right = (int)(src.width()) + pad; |
1260 int shadow_bottom = (int)(src.height()) + pad; | 1264 int shadow_bottom = (int)(src.height()) + pad; |
1261 | 1265 |
1262 dst->fBounds.set(shadow_left, shadow_top, shadow_right, shadow_bottom); | 1266 dst->fBounds.set(shadow_left + src.fLeft, |
| 1267 shadow_top + src.fTop, |
| 1268 shadow_right + src.fRight, |
| 1269 shadow_bottom + src.fBottom); |
1263 | 1270 |
1264 dst->fRowBytes = dst->fBounds.width(); | 1271 dst->fRowBytes = dst->fBounds.width(); |
1265 dst->fFormat = SkMask::kA8_Format; | 1272 dst->fFormat = SkMask::kA8_Format; |
1266 dst->fImage = NULL; | 1273 dst->fImage = NULL; |
1267 | 1274 |
| 1275 int sw = SkScalarFloorToInt(src.width()); |
| 1276 int sh = SkScalarFloorToInt(src.height()); |
| 1277 |
| 1278 if (createMode == SkMask::kJustComputeBounds_CreateMode) { |
| 1279 if (style == kInner_Style) { |
| 1280 dst->fBounds.set(0, 0, sw, sh); // restore trimmed bounds |
| 1281 dst->fRowBytes = sw; |
| 1282 } |
| 1283 return true; |
| 1284 } |
| 1285 unsigned int *profile = NULL; |
| 1286 |
| 1287 compute_profile(radius, &profile); |
| 1288 SkAutoTDeleteArray<unsigned int> ada(profile); |
| 1289 |
1268 size_t dstSize = dst->computeImageSize(); | 1290 size_t dstSize = dst->computeImageSize(); |
1269 if (0 == dstSize) { | 1291 if (0 == dstSize) { |
1270 return false; // too big to allocate, abort | 1292 return false; // too big to allocate, abort |
1271 } | 1293 } |
1272 | 1294 |
1273 int sw = SkScalarFloorToInt(src.width()); | |
1274 int sh = SkScalarFloorToInt(src.height()); | |
1275 | |
1276 uint8_t* dp = SkMask::AllocImage(dstSize); | 1295 uint8_t* dp = SkMask::AllocImage(dstSize); |
1277 | 1296 |
1278 dst->fImage = dp; | 1297 dst->fImage = dp; |
1279 | 1298 |
1280 int dstHeight = dst->fBounds.height(); | 1299 int dstHeight = dst->fBounds.height(); |
1281 int dstWidth = dst->fBounds.width(); | 1300 int dstWidth = dst->fBounds.width(); |
1282 | 1301 |
1283 // nearest odd number less than the profile size represents the center | 1302 // nearest odd number less than the profile size represents the center |
1284 // of the (2x scaled) profile | 1303 // of the (2x scaled) profile |
1285 int center = ( profile_size & ~1 ) - 1; | 1304 int center = ( profile_size & ~1 ) - 1; |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1488 (void)autoCall.detach(); | 1507 (void)autoCall.detach(); |
1489 } | 1508 } |
1490 | 1509 |
1491 if (style == kInner_Style) { | 1510 if (style == kInner_Style) { |
1492 dst->fBounds = src.fBounds; // restore trimmed bounds | 1511 dst->fBounds = src.fBounds; // restore trimmed bounds |
1493 dst->fRowBytes = src.fRowBytes; | 1512 dst->fRowBytes = src.fRowBytes; |
1494 } | 1513 } |
1495 | 1514 |
1496 return true; | 1515 return true; |
1497 } | 1516 } |
OLD | NEW |