Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(747)

Side by Side Diff: src/effects/SkBlurMask.cpp

Issue 12387099: first attempt to plumb fast blur code into skia mask filter (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: use actual CreateMode enum instead of bool Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/effects/SkBlurMask.h ('k') | src/effects/SkBlurMaskFilter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « src/effects/SkBlurMask.h ('k') | src/effects/SkBlurMaskFilter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698