| 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 |