1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 83dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#include "SkBlurMask.h" 92b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com#include "SkBlurMaskFilter.h" 10daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com#include "SkBlurDrawLooper.h" 11daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com#include "SkLayerDrawLooper.h" 12daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com#include "SkEmbossMaskFilter.h" 135af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com#include "SkCanvas.h" 14889bd8bd7f604acae0a6303365bc82c06da1e6f3tomhudson@google.com#include "SkMath.h" 155af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com#include "SkPaint.h" 164ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h" 174ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org 183dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if SK_SUPPORT_GPU 193dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#include "GrContextFactory.h" 203dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#include "SkGpuDevice.h" 213dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 223dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 233dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#define WRITE_CSV 0 242b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 252b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com/////////////////////////////////////////////////////////////////////////////// 262b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 272b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com#define ILLEGAL_MODE ((SkXfermode::Mode)-1) 282b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 295af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic const int outset = 100; 305af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic const SkColor bgColor = SK_ColorWHITE; 315af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic const int strokeWidth = 4; 325af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 33fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.orgstatic void create(SkBitmap* bm, const SkIRect& bound) { 34fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bm->allocN32Pixels(bound.width(), bound.height()); 355af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com} 365af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 375af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic void drawBG(SkCanvas* canvas) { 385af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com canvas->drawColor(bgColor); 395af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com} 405af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 415af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 425af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstruct BlurTest { 435af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com void (*addPath)(SkPath*); 445af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com int viewLen; 455af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIRect views[9]; 465af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com}; 475af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 485af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com//Path Draw Procs 495af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com//Beware that paths themselves my draw differently depending on the clip. 505af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic void draw50x50Rect(SkPath* path) { 515af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com path->addRect(0, 0, SkIntToScalar(50), SkIntToScalar(50)); 525af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com} 535af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 545af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com//Tests 555af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic BlurTest tests[] = { 565af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com { draw50x50Rect, 3, { 575af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com //inner half of blur 585af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com { 0, 0, 50, 50 }, 595af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com //blur, but no path. 605af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com { 50 + strokeWidth/2, 50 + strokeWidth/2, 100, 100 }, 615af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com //just an edge 625af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com { 40, strokeWidth, 60, 50 - strokeWidth }, 635af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com }}, 645af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com}; 655af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 665af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com/** Assumes that the ref draw was completely inside ref canvas -- 675af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com implies that everything outside is "bgColor". 685af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com Checks that all overlap is the same and that all non-overlap on the 695af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com ref is "bgColor". 705af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com */ 715af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.comstatic bool compare(const SkBitmap& ref, const SkIRect& iref, 725af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com const SkBitmap& test, const SkIRect& itest) 735af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com{ 745af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com const int xOff = itest.fLeft - iref.fLeft; 755af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com const int yOff = itest.fTop - iref.fTop; 765af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 775af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkAutoLockPixels alpRef(ref); 785af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkAutoLockPixels alpTest(test); 795af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 805af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com for (int y = 0; y < test.height(); ++y) { 815af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com for (int x = 0; x < test.width(); ++x) { 825af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkColor testColor = test.getColor(x, y); 835af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com int refX = x + xOff; 845af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com int refY = y + yOff; 855af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkColor refColor; 865af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (refX >= 0 && refX < ref.width() && 875af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refY >= 0 && refY < ref.height()) 885af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com { 895af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refColor = ref.getColor(refX, refY); 905af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } else { 915af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refColor = bgColor; 925af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 935af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (refColor != testColor) { 945af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return false; 955af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 965af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 975af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 985af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return true; 995af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com} 1005af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 1013dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic void test_blur_drawing(skiatest::Reporter* reporter) { 1022b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1035af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkPaint paint; 1045af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com paint.setColor(SK_ColorGRAY); 1055af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com paint.setStyle(SkPaint::kStroke_Style); 1065af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com paint.setStrokeWidth(SkIntToScalar(strokeWidth)); 1075af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 108b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)); 109e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org for (int style = 0; style <= kLastEnum_SkBlurStyle; ++style) { 110e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkBlurStyle blurStyle = static_cast<SkBlurStyle>(style); 1115af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 1125af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com const uint32_t flagPermutations = SkBlurMaskFilter::kAll_BlurFlag; 1135af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com for (uint32_t flags = 0; flags < flagPermutations; ++flags) { 1145af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkMaskFilter* filter; 115b7061176c7f414616fe2e79e832b3e0abe326af6robertphillips@google.com filter = SkBlurMaskFilter::Create(blurStyle, sigma, flags); 1165af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 1175af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com paint.setMaskFilter(filter); 1185af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com filter->unref(); 1195af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com 12083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com for (size_t test = 0; test < SK_ARRAY_COUNT(tests); ++test) { 1215af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkPath path; 1225af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com tests[test].addPath(&path); 123d16872c21fba2898f3b608f9bb33287e9972a312bungeman@google.com SkPath strokedPath; 124d16872c21fba2898f3b608f9bb33287e9972a312bungeman@google.com paint.getFillPath(path, &strokedPath); 125d16872c21fba2898f3b608f9bb33287e9972a312bungeman@google.com SkRect refBound = strokedPath.getBounds(); 1265af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIRect iref; 1275af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refBound.roundOut(&iref); 128d16872c21fba2898f3b608f9bb33287e9972a312bungeman@google.com iref.inset(-outset, -outset); 1295af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkBitmap refBitmap; 130fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org create(&refBitmap, iref); 1312b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1325af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkCanvas refCanvas(refBitmap); 1335af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refCanvas.translate(SkIntToScalar(-iref.fLeft), 1345af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIntToScalar(-iref.fTop)); 1355af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com drawBG(&refCanvas); 1365af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com refCanvas.drawPath(path, paint); 1372b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1385af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com for (int view = 0; view < tests[test].viewLen; ++view) { 1395af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIRect itest = tests[test].views[view]; 1405af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkBitmap testBitmap; 141fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org create(&testBitmap, itest); 1422b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1435af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkCanvas testCanvas(testBitmap); 1445af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com testCanvas.translate(SkIntToScalar(-itest.fLeft), 1455af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIntToScalar(-itest.fTop)); 1465af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com drawBG(&testCanvas); 1475af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com testCanvas.drawPath(path, paint); 1482b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1495af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com REPORTER_ASSERT(reporter, 1505af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com compare(refBitmap, iref, testBitmap, itest)); 1515af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 1525af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 1535af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 1542b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com } 1552b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com} 1562b75f4279a237ceea929ff8ac019f7fbd3ad08b5reed@google.com 1573dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 1583dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1593dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Use SkBlurMask::BlurGroundTruth to blur a 'width' x 'height' solid 1603dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// white rect. Return the right half of the middle row in 'result'. 1616fc1b4998917791a73bf54428513940fe77dc058skia.committer@gmail.comstatic void ground_truth_2d(int width, int height, 1623dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar sigma, 1633dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int* result, int resultCount) { 1643dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkMask src, dst; 1653dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1663dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com src.fBounds.set(0, 0, width, height); 1673dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com src.fFormat = SkMask::kA8_Format; 1683dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com src.fRowBytes = src.fBounds.width(); 1693dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com src.fImage = SkMask::AllocImage(src.computeTotalImageSize()); 1703dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1713dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com memset(src.fImage, 0xff, src.computeTotalImageSize()); 1723dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1733dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com dst.fImage = NULL; 174e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkBlurMask::BlurGroundTruth(sigma, &dst, src, kNormal_SkBlurStyle); 1753dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1763dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int midX = dst.fBounds.centerX(); 1773dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int midY = dst.fBounds.centerY(); 1783dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com uint8_t* bytes = dst.getAddr8(midX, midY); 1793dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int i; 1803dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (i = 0; i < dst.fBounds.width()-(midX-dst.fBounds.fLeft); ++i) { 1813dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com if (i < resultCount) { 1823dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com result[i] = bytes[i]; 1833dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 1843dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 1853dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for ( ; i < resultCount; ++i) { 1863dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com result[i] = 0; 1873dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 1886d837aa1a12c1c03cce7cd37b1cae0ef4805f506robertphillips@google.com 1896d837aa1a12c1c03cce7cd37b1cae0ef4805f506robertphillips@google.com SkMask::FreeImage(src.fImage); 1906d837aa1a12c1c03cce7cd37b1cae0ef4805f506robertphillips@google.com SkMask::FreeImage(dst.fImage); 1913dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 1923dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 1933dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Implement a step function that is 255 between min and max; 0 elsewhere. 1943dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic int step(int x, SkScalar min, SkScalar max) { 1953dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com if (min < x && x < max) { 1963dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com return 255; 1973dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 1983dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com return 0; 1993dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2003dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2013dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Implement a Gaussian function with 0 mean and std.dev. of 'sigma'. 2023dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic float gaussian(int x, SkScalar sigma) { 203b85564afffe630190fca81111a5f28cf9d4143berobertphillips@google.com float k = SK_Scalar1/(sigma * sqrtf(2.0f*SK_ScalarPI)); 2043dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com float exponent = -(x * x) / (2 * sigma * sigma); 205b85564afffe630190fca81111a5f28cf9d4143berobertphillips@google.com return k * expf(exponent); 2063dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2073dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2083dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Perform a brute force convolution of a step function with a Gaussian. 2093dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Return the right half in 'result' 2106fc1b4998917791a73bf54428513940fe77dc058skia.committer@gmail.comstatic void brute_force_1d(SkScalar stepMin, SkScalar stepMax, 2113dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar gaussianSigma, 2123dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int* result, int resultCount) { 2133dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2143dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int gaussianRange = SkScalarCeilToInt(10 * gaussianSigma); 2153dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2163dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int i = 0; i < resultCount; ++i) { 2173dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar sum = 0.0f; 2183dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int j = -gaussianRange; j < gaussianRange; ++j) { 2193dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com sum += gaussian(j, gaussianSigma) * step(i-j, stepMin, stepMax); 2203dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 2213dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2223dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com result[i] = SkClampMax(SkClampPos(int(sum + 0.5f)), 255); 2233dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 2243dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2253dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2266fc1b4998917791a73bf54428513940fe77dc058skia.committer@gmail.comstatic void blur_path(SkCanvas* canvas, const SkPath& path, 2273dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar gaussianSigma) { 2283dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2293dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar midX = path.getBounds().centerX(); 2303dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar midY = path.getBounds().centerY(); 2313dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2323dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com canvas->translate(-midX, -midY); 2333dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2343dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkPaint blurPaint; 2353dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com blurPaint.setColor(SK_ColorWHITE); 236e396455d2d60ddf8e625b5037254f3c09fbcdcf5commit-bot@chromium.org SkMaskFilter* filter = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, 2373dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com gaussianSigma, 2383dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkBlurMaskFilter::kHighQuality_BlurFlag); 2393dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com blurPaint.setMaskFilter(filter)->unref(); 2403dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2413dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com canvas->drawColor(SK_ColorBLACK); 2423dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com canvas->drawPath(path, blurPaint); 2433dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2443dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2453dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Readback the blurred draw results from the canvas 2463dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic void readback(SkCanvas* canvas, int* result, int resultCount) { 2473dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkBitmap readback; 248fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org readback.allocN32Pixels(resultCount, 30); 2493dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2503dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkIRect readBackRect = { 0, 0, resultCount, 30 }; 2513dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2523dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com canvas->readPixels(readBackRect, &readback); 2533dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2543dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com readback.lockPixels(); 2553dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkPMColor* pixels = (SkPMColor*) readback.getAddr32(0, 15); 2563dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2573dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int i = 0; i < resultCount; ++i) { 2583dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com result[i] = SkColorGetR(pixels[i]); 2593dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 2603dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2613dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2626fc1b4998917791a73bf54428513940fe77dc058skia.committer@gmail.com// Draw a blurred version of the provided path. 2633dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Return the right half of the middle row in 'result'. 2643dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic void cpu_blur_path(const SkPath& path, SkScalar gaussianSigma, 2653dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int* result, int resultCount) { 2663dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2673dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkBitmap bitmap; 268fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bitmap.allocN32Pixels(resultCount, 30); 2693dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkCanvas canvas(bitmap); 2703dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2713dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com blur_path(&canvas, path, gaussianSigma); 2723dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com readback(&canvas, result, resultCount); 2733dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 2743dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2753dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if SK_SUPPORT_GPU 2764a24cd8ff41a8b3d292d60e4351a631240a7ed75humper#if 0 2774a24cd8ff41a8b3d292d60e4351a631240a7ed75humper// temporary disable; see below for explanation 278cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.comstatic bool gpu_blur_path(GrContextFactory* factory, const SkPath& path, 2793dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkScalar gaussianSigma, 2803dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int* result, int resultCount) { 2813dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2823dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com GrContext* grContext = factory->get(GrContextFactory::kNative_GLContextType); 2833dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com if (NULL == grContext) { 284cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com return false; 2853dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 2863dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2873dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com GrTextureDesc desc; 2883dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com desc.fConfig = kSkia8888_GrPixelConfig; 2893dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit; 2903dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com desc.fWidth = resultCount; 2913dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com desc.fHeight = 30; 2923dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com desc.fSampleCnt = 0; 2933dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2943dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkAutoTUnref<GrTexture> texture(grContext->createUncachedTexture(desc, NULL, 0)); 2953dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, (grContext, texture.get()))); 2963dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkCanvas canvas(device.get()); 2973dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 2983dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com blur_path(&canvas, path, gaussianSigma); 2993dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com readback(&canvas, result, resultCount); 300cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com return true; 3013dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 3023dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 3034a24cd8ff41a8b3d292d60e4351a631240a7ed75humper#endif 3043dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3053dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if WRITE_CSV 3063dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic void write_as_csv(const char* label, SkScalar scale, int* data, int count) { 3073dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkDebugf("%s_%.2f,", label, scale); 3083dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int i = 0; i < count-1; ++i) { 3093dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkDebugf("%d,", data[i]); 3103dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 3113dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkDebugf("%d\n", data[count-1]); 3123dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 3133dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 3143dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3153dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic bool match(int* first, int* second, int count, int tol) { 3163dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int delta; 3173dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int i = 0; i < count; ++i) { 3183dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com delta = first[i] - second[i]; 3193dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com if (delta > tol || delta < -tol) { 3203dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com return false; 3213dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 3223dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 3233dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3243dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com return true; 3253dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 3263dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3273dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com// Test out the normal blur style with a wide range of sigmas 3283dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.comstatic void test_sigma_range(skiatest::Reporter* reporter, GrContextFactory* factory) { 3293dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3303dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com static const int kSize = 100; 3313dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3323dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com // The geometry is offset a smidge to trigger: 3333dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com // https://code.google.com/p/chromium/issues/detail?id=282418 3343dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkPath rectPath; 3353dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com rectPath.addRect(0.3f, 0.3f, 100.3f, 100.3f); 3363dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3373dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkPoint polyPts[] = { 3383dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com { 0.3f, 0.3f }, 3393dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com { 100.3f, 0.3f }, 3403dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com { 100.3f, 100.3f }, 3413dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com { 0.3f, 100.3f }, 3423dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com { 2.3f, 50.3f } // a little divet to throw off the rect special case 3433dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com }; 3443dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com SkPath polyPath; 3453dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com polyPath.addPoly(polyPts, SK_ARRAY_COUNT(polyPts), true); 3463dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3473dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int rectSpecialCaseResult[kSize]; 3483dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int generalCaseResult[kSize]; 3493dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int groundTruthResult[kSize]; 3503dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com int bruteForce1DResult[kSize]; 3513dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3524b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalar sigma = 10.0f; 3533dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3543dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com for (int i = 0; i < 4; ++i, sigma /= 10) { 3553dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3563dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com cpu_blur_path(rectPath, sigma, rectSpecialCaseResult, kSize); 3573dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com cpu_blur_path(polyPath, sigma, generalCaseResult, kSize); 3584a24cd8ff41a8b3d292d60e4351a631240a7ed75humper 3593dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com ground_truth_2d(100, 100, sigma, groundTruthResult, kSize); 3603dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com brute_force_1d(-50.0f, 50.0f, sigma, bruteForce1DResult, kSize); 3613dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3623dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com REPORTER_ASSERT(reporter, match(rectSpecialCaseResult, bruteForce1DResult, kSize, 5)); 3633dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com REPORTER_ASSERT(reporter, match(generalCaseResult, bruteForce1DResult, kSize, 15)); 3643dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if SK_SUPPORT_GPU 3654a24cd8ff41a8b3d292d60e4351a631240a7ed75humper#if 0 3664a24cd8ff41a8b3d292d60e4351a631240a7ed75humper int gpuResult[kSize]; 3674a24cd8ff41a8b3d292d60e4351a631240a7ed75humper bool haveGPUResult = gpu_blur_path(factory, rectPath, sigma, gpuResult, kSize); 3684a24cd8ff41a8b3d292d60e4351a631240a7ed75humper // Disabling this test for now -- I don't think it's a legit comparison. 3694a24cd8ff41a8b3d292d60e4351a631240a7ed75humper // Will continue to investigate this. 370cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com if (haveGPUResult) { 371cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com // 1 works everywhere but: Ubuntu13 & Nexus4 372cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com REPORTER_ASSERT(reporter, match(gpuResult, bruteForce1DResult, kSize, 10)); 373cb3b615af712fc71b19b86211c1d083430114d7erobertphillips@google.com } 3743dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 3754a24cd8ff41a8b3d292d60e4351a631240a7ed75humper#endif 3763dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com REPORTER_ASSERT(reporter, match(groundTruthResult, bruteForce1DResult, kSize, 1)); 3773dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 3783dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if WRITE_CSV 3793dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com write_as_csv("RectSpecialCase", sigma, rectSpecialCaseResult, kSize); 3803dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com write_as_csv("GeneralCase", sigma, generalCaseResult, kSize); 3813dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#if SK_SUPPORT_GPU 3823dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com write_as_csv("GPU", sigma, gpuResult, kSize); 3833dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 3843dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com write_as_csv("GroundTruth2D", sigma, groundTruthResult, kSize); 3853dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com write_as_csv("BruteForce1D", sigma, bruteForce1DResult, kSize); 3863dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com#endif 3873dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com } 3883dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 3893dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com 390daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com/////////////////////////////////////////////////////////////////////////////////////////// 391daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 392daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic SkBlurQuality blurMaskFilterFlags_as_quality(uint32_t blurMaskFilterFlags) { 393daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return (blurMaskFilterFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? 394daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com kHigh_SkBlurQuality : kLow_SkBlurQuality; 395daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 396daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 397daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic uint32_t blurMaskFilterFlags_to_blurDrawLooperFlags(uint32_t bmf) { 398daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const struct { 399daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com uint32_t fBlurMaskFilterFlag; 400daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com uint32_t fBlurDrawLooperFlag; 401daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } pairs[] = { 402daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com { SkBlurMaskFilter::kIgnoreTransform_BlurFlag, SkBlurDrawLooper::kIgnoreTransform_BlurFlag }, 403daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com { SkBlurMaskFilter::kHighQuality_BlurFlag, SkBlurDrawLooper::kHighQuality_BlurFlag }, 404daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com }; 405daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 406daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com uint32_t bdl = 0; 407daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(pairs); ++i) { 408daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (bmf & pairs[i].fBlurMaskFilterFlag) { 409daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com bdl |= pairs[i].fBlurDrawLooperFlag; 410daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 411daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 412daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return bdl; 413daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 414daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 415daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void test_blurDrawLooper(skiatest::Reporter* reporter, SkScalar sigma, 416daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkBlurStyle style, uint32_t blurMaskFilterFlags) { 417daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (kNormal_SkBlurStyle != style) { 418daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com return; // blurdrawlooper only supports normal 419daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 420daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 421daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkColor color = 0xFF335577; 422daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkScalar dx = 10; 423daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkScalar dy = -5; 424daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkBlurQuality quality = blurMaskFilterFlags_as_quality(blurMaskFilterFlags); 425daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com uint32_t flags = blurMaskFilterFlags_to_blurDrawLooperFlags(blurMaskFilterFlags); 426daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 427daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkAutoTUnref<SkDrawLooper> lp(SkBlurDrawLooper::Create(color, sigma, dx, dy, flags)); 428daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 429daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const bool expectSuccess = sigma > 0 && 430daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 0 == (flags & SkBlurDrawLooper::kIgnoreTransform_BlurFlag); 431daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 432daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (NULL == lp.get()) { 433daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, sigma <= 0); 434daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } else { 435daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkDrawLooper::BlurShadowRec rec; 436daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com bool success = lp->asABlurShadow(&rec); 437daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, success == expectSuccess); 438daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (success) { 439daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fSigma == sigma); 440daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fOffset.x() == dx); 441daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fOffset.y() == dy); 442daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fColor == color); 443daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fStyle == style); 444daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fQuality == quality); 445daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 446daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 447daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 448daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 449daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void test_delete_looper(skiatest::Reporter* reporter, SkDrawLooper* lp, SkScalar sigma, 450daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkBlurStyle style, SkBlurQuality quality, bool expectSuccess) { 451daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkDrawLooper::BlurShadowRec rec; 452daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com bool success = lp->asABlurShadow(&rec); 453daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, success == expectSuccess); 454daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (success != expectSuccess) { 455daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com lp->asABlurShadow(&rec); 456daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 457daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (success) { 458daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fSigma == sigma); 459daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fStyle == style); 460daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fQuality == quality); 461daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 462daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com lp->unref(); 463daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 464daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 465daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void make_noop_layer(SkLayerDrawLooper::Builder* builder) { 466daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkLayerDrawLooper::LayerInfo info; 467daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 468daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com info.fPaintBits = 0; 469daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com info.fColorMode = SkXfermode::kDst_Mode; 470daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com builder->addLayer(info); 471daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 472daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 473daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void make_blur_layer(SkLayerDrawLooper::Builder* builder, SkMaskFilter* mf) { 474daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkLayerDrawLooper::LayerInfo info; 475daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 476daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit; 477daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com info.fColorMode = SkXfermode::kSrc_Mode; 478daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkPaint* paint = builder->addLayer(info); 479daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com paint->setMaskFilter(mf); 480daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 481daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 482daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void test_layerDrawLooper(skiatest::Reporter* reporter, SkMaskFilter* mf, SkScalar sigma, 483daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkBlurStyle style, SkBlurQuality quality, bool expectSuccess) { 484daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 485daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkLayerDrawLooper::LayerInfo info; 486daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkLayerDrawLooper::Builder builder; 487daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 488daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 1 layer is too few 489daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 490daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false); 491daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 492daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 2 layers is good, but need blur 493daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 494daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 495daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false); 496daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 497daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 2 layers is just right 498daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 499daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_blur_layer(&builder, mf); 500daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, expectSuccess); 501daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 502daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 3 layers is too many 503daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 504daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_blur_layer(&builder, mf); 505daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com make_noop_layer(&builder); 506daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false); 507daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 508daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 509daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.comstatic void test_asABlur(skiatest::Reporter* reporter) { 510daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkBlurStyle styles[] = { 511daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com kNormal_SkBlurStyle, kSolid_SkBlurStyle, kOuter_SkBlurStyle, kInner_SkBlurStyle 512daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com }; 513daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkScalar sigmas[] = { 514daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // values <= 0 should not success for a blur 515daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com -1, 0, 0.5f, 2 516daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com }; 517daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 518daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // Test asABlur for SkBlurMaskFilter 519daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 520daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(styles); ++i) { 521daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkBlurStyle style = (SkBlurStyle)styles[i]; 522daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com for (size_t j = 0; j < SK_ARRAY_COUNT(sigmas); ++j) { 523daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkScalar sigma = sigmas[j]; 524daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com for (int flags = 0; flags <= SkBlurMaskFilter::kAll_BlurFlag; ++flags) { 525daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkBlurQuality quality = blurMaskFilterFlags_as_quality(flags); 526daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 527daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkAutoTUnref<SkMaskFilter> mf(SkBlurMaskFilter::Create(style, sigma, flags)); 528daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (NULL == mf.get()) { 529daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, sigma <= 0); 530daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } else { 531daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, sigma > 0); 532daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkMaskFilter::BlurRec rec; 533daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com bool success = mf->asABlur(&rec); 534daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (flags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { 535daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, !success); 536daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } else { 537daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, success); 538daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fSigma == sigma); 539daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fStyle == style); 540daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, rec.fQuality == quality); 541daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 542daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_layerDrawLooper(reporter, mf, sigma, style, quality, success); 543daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 544daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_blurDrawLooper(reporter, sigma, style, flags); 545daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 546daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 547daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 548daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 549daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // Test asABlur for SkEmbossMaskFilter -- should never succeed 550daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com // 551daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com { 552daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkEmbossMaskFilter::Light light = { 553daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com { 1, 1, 1 }, 0, 127, 127 554daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com }; 555daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com for (size_t j = 0; j < SK_ARRAY_COUNT(sigmas); ++j) { 556daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com const SkScalar sigma = sigmas[j]; 557daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkAutoTUnref<SkMaskFilter> mf(SkEmbossMaskFilter::Create(sigma, light)); 558daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com if (mf.get()) { 559daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com SkMaskFilter::BlurRec rec; 560daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com bool success = mf->asABlur(&rec); 561daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com REPORTER_ASSERT(reporter, !success); 562daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 563daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 564daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com } 565daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com} 566daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 567daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com/////////////////////////////////////////////////////////////////////////////////////////// 568daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com 5694ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(Blur, reporter, factory) { 5703dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com test_blur_drawing(reporter); 5713dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com test_sigma_range(reporter, factory); 572daaafa6e81860e3dc52660ba019c336f0a43f1e7reed@google.com test_asABlur(reporter); 5733dfa4cc07cb1b5c8dc90e022b7e5001a77a82066robertphillips@google.com} 574