Flutter Engine
The Flutter Engine
Functions | Variables
ImageFilterTest.cpp File Reference
#include "include/core/SkAlphaType.h"
#include "include/core/SkBBHFactory.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkFlattenable.h"
#include "include/core/SkFont.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
#include "include/effects/SkPerlinNoiseShader.h"
#include "include/encode/SkPngEncoder.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrTypes.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkDevice.h"
#include "src/core/SkImageFilterTypes.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkSpecialImage.h"
#include "src/effects/colorfilters/SkColorFilterBase.h"
#include "src/image/SkImage_Base.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/EncodeUtils.h"
#include "tools/GpuToolUtils.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <utility>
#include <limits>

Go to the source code of this file.

Functions

static skif::Context make_context (const SkIRect &out, const SkSpecialImage *src)
 
static skif::Context make_context (int outWidth, int outHeight, const SkSpecialImage *src)
 
static sk_sp< SkImagemake_small_image ()
 
static sk_sp< SkImageFiltermake_scale (float amount, sk_sp< SkImageFilter > input)
 
static sk_sp< SkImageFiltermake_grayscale (sk_sp< SkImageFilter > input, const SkIRect *cropRect)
 
static sk_sp< SkImageFiltermake_blue (sk_sp< SkImageFilter > input, const SkIRect *cropRect)
 
static sk_sp< SkDevicecreate_empty_device (GrRecordingContext *rContext, int widthHeight)
 
static sk_sp< SkSpecialImagecreate_empty_special_image (GrRecordingContext *rContext, int widthHeight, SkColor4f color=SkColors::kTransparent)
 
 DEF_TEST (ImageFilter, reporter)
 
static void test_cropRects (skiatest::Reporter *reporter, GrRecordingContext *rContext)
 
static bool special_image_to_bitmap (GrDirectContext *dContext, const SkSpecialImage *src, SkBitmap *dst)
 
static void test_negative_blur_sigma (skiatest::Reporter *reporter, GrDirectContext *dContext)
 
 DEF_TEST (ImageFilterNegativeBlurSigma, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterNegativeBlurSigma_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
static void test_morphology_radius_with_mirror_ctm (skiatest::Reporter *reporter, GrDirectContext *dContext)
 
 DEF_TEST (MorphologyFilterRadiusWithMirrorCTM, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (MorphologyFilterRadiusWithMirrorCTM_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
static void test_zero_blur_sigma (skiatest::Reporter *reporter, GrDirectContext *dContext)
 
 DEF_TEST (ImageFilterZeroBlurSigma, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterZeroBlurSigma_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
static void test_fail_affects_transparent_black (skiatest::Reporter *reporter, GrDirectContext *dContext)
 
 DEF_TEST (ImageFilterFailAffectsTransparentBlack, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterFailAffectsTransparentBlack_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterDrawTiled, reporter)
 
static void draw_saveLayer_picture (int width, int height, int tileSize, SkBBHFactory *factory, SkBitmap *result)
 
 DEF_TEST (ImageFilterDrawMatrixBBH, reporter)
 
static sk_sp< SkImageFiltermake_blur (sk_sp< SkImageFilter > input)
 
static sk_sp< SkImageFiltermake_drop_shadow (sk_sp< SkImageFilter > input)
 
 DEF_TEST (ImageFilterBlurThenShadowBounds, reporter)
 
 DEF_TEST (ImageFilterShadowThenBlurBounds, reporter)
 
 DEF_TEST (ImageFilterDilateThenBlurBounds, reporter)
 
 DEF_TEST (ImageFilterScaledBlurRadius, reporter)
 
 DEF_TEST (ImageFilterComposedBlurFastBounds, reporter)
 
 DEF_TEST (ImageFilterUnionBounds, reporter)
 
static void test_imagefilter_merge_result_size (skiatest::Reporter *reporter, GrRecordingContext *rContext)
 
 DEF_TEST (ImageFilterMergeResultSize, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterMergeResultSize_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
static void draw_blurred_rect (SkCanvas *canvas)
 
static void draw_picture_clipped (SkCanvas *canvas, const SkRect &clipRect, const SkPicture *picture)
 
 DEF_TEST (ImageFilterDrawTiledBlurRTree, reporter)
 
 DEF_TEST (ImageFilterMatrixConvolution, reporter)
 
 DEF_TEST (ImageFilterMatrixConvolutionBorder, reporter)
 
static void test_big_kernel (skiatest::Reporter *reporter, GrRecordingContext *rContext)
 
 DEF_TEST (ImageFilterMatrixConvolutionBigKernel, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterMatrixConvolutionBigKernel_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterCropRect, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterCropRect_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterMatrix, reporter)
 
static void test_clipped_picture_imagefilter (skiatest::Reporter *reporter, GrRecordingContext *rContext)
 
 DEF_TEST (ImageFilterClippedPictureImageFilter, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterClippedPictureImageFilter_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterEmptySaveLayer, reporter)
 
static void test_huge_blur (SkCanvas *canvas, skiatest::Reporter *reporter)
 
 DEF_TEST (HugeBlurImageFilter, reporter)
 
 DEF_TEST (ImageFilterMatrixConvolutionTest, reporter)
 
static void test_xfermode_cropped_input (SkSurface *surf, skiatest::Reporter *reporter)
 
 DEF_TEST (ImageFilterNestedSaveLayer, reporter)
 
 DEF_TEST (XfermodeImageFilterCroppedInput, reporter)
 
static void test_composed_imagefilter_offset (skiatest::Reporter *reporter, GrRecordingContext *rContext)
 
 DEF_TEST (ComposedImageFilterOffset, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ComposedImageFilterOffset_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
static void test_composed_imagefilter_bounds (skiatest::Reporter *reporter, GrDirectContext *dContext)
 
 DEF_TEST (ComposedImageFilterBounds, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ComposedImageFilterBounds_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterCanComputeFastBounds, reporter)
 
 DEF_TEST (ImageFilterImageSourceSerialization, reporter)
 
 DEF_TEST (ImageFilterImageSourceUninitialized, r)
 
static void test_large_blur_input (skiatest::Reporter *reporter, SkCanvas *canvas)
 
 DEF_TEST (ImageFilterBlurLargeImage, reporter)
 
static void test_make_with_filter (skiatest::Reporter *reporter, const std::function< sk_sp< SkSurface >(int width, int height)> &createSurface, const std::function< sk_sp< SkImage >(sk_sp< SkImage > src, const SkImageFilter *filter, const SkIRect &subset, const SkIRect &clipBounds, SkIRect *outSubset, SkIPoint *offset)> &makeWithFilter)
 
 DEF_TEST (ImageFilterMakeWithFilter, reporter)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterMakeWithFilter_Ganesh, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (ImageFilterHugeBlur_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (XfermodeImageFilterCroppedInput_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_GANESH_TEST_FOR_ALL_CONTEXTS (ImageFilterBlurLargeImage_Gpu, reporter, ctxInfo, CtsEnforcement::kNever)
 
 DEF_TEST (ImageFilterComplexCTM, reporter)
 
 DEF_TEST (XfermodeImageFilterBounds, reporter)
 
 DEF_TEST (OffsetImageFilterBounds, reporter)
 
 DEF_TEST (OffsetImageFilterBoundsNoOverflow, reporter)
 
static void test_arithmetic_bounds (skiatest::Reporter *reporter, float k1, float k2, float k3, float k4, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground, const SkIRect *crop, const SkIRect &expected)
 
static void test_arithmetic_combinations (skiatest::Reporter *reporter, float v)
 
 DEF_TEST (ArithmeticImageFilterBounds, reporter)
 
 DEF_TEST (DisplacementMapBounds, reporter)
 
 DEF_TEST (ImageSourceBounds, reporter)
 
 DEF_TEST (PictureImageSourceBounds, reporter)
 
 DEF_TEST (DropShadowImageFilter_Huge, reporter)
 

Variables

static const int kBitmapSize = 4
 

Function Documentation

◆ create_empty_device()

static sk_sp< SkDevice > create_empty_device ( GrRecordingContext rContext,
int  widthHeight 
)
static

Definition at line 376 of file ImageFilterTest.cpp.

376 {
377
378 const SkImageInfo ii = SkImageInfo::Make({ widthHeight, widthHeight },
381
382 if (rContext) {
385 kTestSurfaceOrigin, {},
387 } else {
388 SkBitmap bm;
390 return sk_make_sp<SkBitmapDevice>(bm, SkSurfaceProps());
391 }
392}
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
sk_sp< skgpu::ganesh::Device > createDevice(GrColorType, sk_sp< GrSurfaceProxy >, sk_sp< SkColorSpace >, GrSurfaceOrigin, const SkSurfaceProps &, skgpu::ganesh::Device::InitContents)
GrRecordingContextPriv priv()
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:271
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)

◆ create_empty_special_image()

static sk_sp< SkSpecialImage > create_empty_special_image ( GrRecordingContext rContext,
int  widthHeight,
SkColor4f  color = SkColors::kTransparent 
)
static

Definition at line 394 of file ImageFilterTest.cpp.

396 {
397 sk_sp<SkDevice> device = create_empty_device(rContext, widthHeight);
398
400
401 SkPaint p;
402 p.setColor4f(color, /*colorSpace=*/nullptr);
403 p.setBlendMode(SkBlendMode::kSrc);
404 device->drawPaint(p);
405 return device->snapSpecial(SkIRect::MakeWH(widthHeight, widthHeight));
406}
static sk_sp< SkDevice > create_empty_device(GrRecordingContext *rContext, int widthHeight)
#define SkASSERT(cond)
Definition: SkAssert.h:116
DlColor color
VkDevice device
Definition: main.cc:53
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56

◆ DEF_GANESH_TEST_FOR_ALL_CONTEXTS()

DEF_GANESH_TEST_FOR_ALL_CONTEXTS ( ImageFilterBlurLargeImage_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1957 of file ImageFilterTest.cpp.

1960 {
1962 ctxInfo.directContext(),
1965 test_large_blur_input(reporter, surface->getCanvas());
1966}
reporter
Definition: FontMgrTest.cpp:39
static void test_large_blur_input(skiatest::Reporter *reporter, SkCanvas *canvas)
VkSurfaceKHR surface
Definition: main.cc:49
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [1/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ComposedImageFilterBounds_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1620 of file ImageFilterTest.cpp.

1623 {
1624 test_composed_imagefilter_bounds(reporter, ctxInfo.directContext());
1625}
static void test_composed_imagefilter_bounds(skiatest::Reporter *reporter, GrDirectContext *dContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [2/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ComposedImageFilterOffset_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1575 of file ImageFilterTest.cpp.

1578 {
1579 test_composed_imagefilter_offset(reporter, ctxInfo.directContext());
1580}
static void test_composed_imagefilter_offset(skiatest::Reporter *reporter, GrRecordingContext *rContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [3/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterClippedPictureImageFilter_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1336 of file ImageFilterTest.cpp.

1339 {
1340 test_clipped_picture_imagefilter(reporter, ctxInfo.directContext());
1341}
static void test_clipped_picture_imagefilter(skiatest::Reporter *reporter, GrRecordingContext *rContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [4/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterCropRect_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1271 of file ImageFilterTest.cpp.

1274 {
1275 test_cropRects(reporter, ctxInfo.directContext());
1276}
static void test_cropRects(skiatest::Reporter *reporter, GrRecordingContext *rContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [5/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterFailAffectsTransparentBlack_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 776 of file ImageFilterTest.cpp.

779 {
780 test_fail_affects_transparent_black(reporter, ctxInfo.directContext());
781}
static void test_fail_affects_transparent_black(skiatest::Reporter *reporter, GrDirectContext *dContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [6/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterHugeBlur_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1933 of file ImageFilterTest.cpp.

1936 {
1938 ctxInfo.directContext(), skgpu::Budgeted::kNo, SkImageInfo::MakeN32Premul(100, 100)));
1939
1940 SkCanvas* canvas = surf->getCanvas();
1941
1942 test_huge_blur(canvas, reporter);
1943}
static void test_huge_blur(SkCanvas *canvas, skiatest::Reporter *reporter)
static SkImageInfo MakeN32Premul(int width, int height)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [7/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterMakeWithFilter_Ganesh  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1869 of file ImageFilterTest.cpp.

1872 {
1873 GrRecordingContext* rContext = ctxInfo.directContext();
1874
1875 auto createGaneshSurface = [rContext](int width, int height) -> sk_sp<SkSurface> {
1878 rContext, skgpu::Budgeted::kNo, info, 0, kTestSurfaceOrigin, nullptr);
1879 };
1880
1881 auto ganesh = [rContext](sk_sp<SkImage> src,
1882 const SkImageFilter* filter,
1883 const SkIRect& subset,
1884 const SkIRect& clipBounds,
1885 SkIRect* outSubset,
1887 return SkImages::MakeWithFilter(rContext,
1888 std::move(src),
1889 filter,
1890 subset,
1891 clipBounds,
1892 outSubset,
1893 offset);
1894 };
1895
1896 test_make_with_filter(reporter, createGaneshSurface, ganesh);
1897}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static void test_make_with_filter(skiatest::Reporter *reporter, const std::function< sk_sp< SkSurface >(int width, int height)> &createSurface, const std::function< sk_sp< SkImage >(sk_sp< SkImage > src, const SkImageFilter *filter, const SkIRect &subset, const SkIRect &clipBounds, SkIRect *outSubset, SkIPoint *offset)> &makeWithFilter)
@ kOpaque_SkAlphaType
pixel is opaque
Definition: SkAlphaType.h:28
SK_API sk_sp< SkImage > MakeWithFilter(sk_sp< SkImage > src, const SkImageFilter *filter, const SkIRect &subset, const SkIRect &clipBounds, SkIRect *outSubset, SkIPoint *offset)
int32_t height
int32_t width
SeparatedVector2 offset
Definition: SkRect.h:32
static SkImageInfo MakeN32(int width, int height, SkAlphaType at)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [8/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterMatrixConvolutionBigKernel_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1260 of file ImageFilterTest.cpp.

1263 {
1264 test_big_kernel(reporter, ctxInfo.directContext());
1265}
static void test_big_kernel(skiatest::Reporter *reporter, GrRecordingContext *rContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [9/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterMergeResultSize_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1100 of file ImageFilterTest.cpp.

1103 {
1104 test_imagefilter_merge_result_size(reporter, ctxInfo.directContext());
1105}
static void test_imagefilter_merge_result_size(skiatest::Reporter *reporter, GrRecordingContext *rContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [10/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterNegativeBlurSigma_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 610 of file ImageFilterTest.cpp.

613 {
614 test_negative_blur_sigma(reporter, ctxInfo.directContext());
615}
static void test_negative_blur_sigma(skiatest::Reporter *reporter, GrDirectContext *dContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [11/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( ImageFilterZeroBlurSigma_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 742 of file ImageFilterTest.cpp.

745 {
746 test_zero_blur_sigma(reporter, ctxInfo.directContext());
747}
static void test_zero_blur_sigma(skiatest::Reporter *reporter, GrDirectContext *dContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [12/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( MorphologyFilterRadiusWithMirrorCTM_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 699 of file ImageFilterTest.cpp.

702 {
703 test_morphology_radius_with_mirror_ctm(reporter, ctxInfo.directContext());
704}
static void test_morphology_radius_with_mirror_ctm(skiatest::Reporter *reporter, GrDirectContext *dContext)

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [13/13]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( XfermodeImageFilterCroppedInput_Gpu  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kNever   
)

Definition at line 1945 of file ImageFilterTest.cpp.

1948 {
1950 ctxInfo.directContext(),
1953
1955}
static void test_xfermode_cropped_input(SkSurface *surf, skiatest::Reporter *reporter)

◆ DEF_TEST() [1/42]

DEF_TEST ( ArithmeticImageFilterBounds  ,
reporter   
)

Definition at line 2174 of file ImageFilterTest.cpp.

2174 {
2177}
static void test_arithmetic_combinations(skiatest::Reporter *reporter, float v)

◆ DEF_TEST() [2/42]

DEF_TEST ( ComposedImageFilterBounds  ,
reporter   
)

Definition at line 1616 of file ImageFilterTest.cpp.

1616 {
1618}

◆ DEF_TEST() [3/42]

DEF_TEST ( ComposedImageFilterOffset  ,
reporter   
)

Definition at line 1571 of file ImageFilterTest.cpp.

1571 {
1573}

◆ DEF_TEST() [4/42]

DEF_TEST ( DisplacementMapBounds  ,
reporter   
)

Definition at line 2180 of file ImageFilterTest.cpp.

2180 {
2181 SkIRect floodBounds(SkIRect::MakeXYWH(20, 30, 10, 10));
2183 &floodBounds));
2184 SkIRect tilingBounds(SkIRect::MakeXYWH(0, 0, 200, 100));
2186 SkRect::Make(tilingBounds),
2187 flood));
2190 20.0f, nullptr, tiling));
2191
2192 // The filter graph rooted at 'displace' uses the dynamic source image for the displacement
2193 // component of ::DisplacementMap, modifying the color component produced by the ::Tile. The
2194 // output of the tiling filter will be 'tilingBounds', regardless of its input, so 'floodBounds'
2195 // has no effect on the output. Since 'tiling' doesn't reference any dynamic source image, it
2196 // also will not affect the required input bounds. The displacement map is sampled 1-to-1
2197 // with the output pixels, and covers the output unless the color's output makes that impossible
2198 // and the output is a subset of the desired output. Thus, the displacement can impact the
2199 // reported output bounds.
2200 SkIRect input(SkIRect::MakeXYWH(20, 30, 40, 50));
2201
2202 // 'input' is the desired output, which directly constrains the displacement component in this
2203 // specific filter graph.
2204 SkIRect actualInput = displace->filterBounds(input, SkMatrix::I(),
2206 REPORTER_ASSERT(reporter, input == actualInput);
2207
2208 // 'input' is the content bounds, which don't affect output bounds because it's only referenced
2209 // by the displacement component and not the color component.
2210 SkIRect actualOutput = displace->filterBounds(input, SkMatrix::I(),
2212 REPORTER_ASSERT(reporter, tilingBounds.makeOutset(10, 10) == actualOutput);
2213}
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static sk_sp< SkImageFilter > DisplacementMap(SkColorChannel xChannelSelector, SkColorChannel yChannelSelector, SkScalar scale, sk_sp< SkImageFilter > displacement, sk_sp< SkImageFilter > color, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Shader(sk_sp< SkShader > shader, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Tile(const SkRect &src, const SkRect &dst, sk_sp< SkImageFilter > input)
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
SK_API sk_sp< SkShader > Color(SkColor)
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669

◆ DEF_TEST() [5/42]

DEF_TEST ( DropShadowImageFilter_Huge  ,
reporter   
)

Definition at line 2319 of file ImageFilterTest.cpp.

2319 {
2320 // Successful if it doesn't crash or trigger ASAN. (crbug.com/1264705)
2321 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(300, 150));
2322
2323 SkPaint paint;
2325 0.0f, 0.437009f, 14129.6f, 14129.6f, SK_ColorGRAY, nullptr));
2326
2327 surf->getCanvas()->saveLayer(nullptr, &paint);
2328 surf->getCanvas()->restore();
2329}
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
static sk_sp< SkImageFilter > DropShadowOnly(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
const Paint & paint
Definition: color_source.cc:38
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)

◆ DEF_TEST() [6/42]

DEF_TEST ( HugeBlurImageFilter  ,
reporter   
)

Definition at line 1405 of file ImageFilterTest.cpp.

1405 {
1406 SkBitmap temp;
1407 temp.allocN32Pixels(100, 100);
1408 SkCanvas canvas(temp);
1409 test_huge_blur(&canvas, reporter);
1410}
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232

◆ DEF_TEST() [7/42]

DEF_TEST ( ImageFilter  ,
reporter   
)

Definition at line 409 of file ImageFilterTest.cpp.

409 {
410 {
411 // Check that a color matrix filter followed by a color matrix filter
412 // concatenates into a single filter.
413 sk_sp<SkImageFilter> doubleBrightness(make_scale(2.0f, nullptr));
414 sk_sp<SkImageFilter> halfBrightness(make_scale(0.5f, std::move(doubleBrightness)));
415 REPORTER_ASSERT(reporter, nullptr == halfBrightness->getInput(0));
416 SkColorFilter* cf;
417 REPORTER_ASSERT(reporter, halfBrightness->asColorFilter(&cf));
418 cf->unref();
419 }
420
421 {
422 // Check that a color filter image filter without a crop rect can be
423 // expressed as a color filter.
424 sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
425 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
426 }
427
428 {
429 // Check that a colorfilterimage filter without a crop rect but with an input
430 // that is another colorfilterimage can be expressed as a colorfilter (composed).
431 sk_sp<SkImageFilter> mode(make_blue(nullptr, nullptr));
432 sk_sp<SkImageFilter> gray(make_grayscale(std::move(mode), nullptr));
433 REPORTER_ASSERT(reporter, true == gray->asColorFilter(nullptr));
434 }
435
436 {
437 // Test that if we exceed the limit of what ComposeColorFilter can combine, we still
438 // can build the DAG and won't assert if we call asColorFilter.
439 sk_sp<SkImageFilter> filter(make_blue(nullptr, nullptr));
440 const int kWayTooManyForComposeColorFilter = 100;
441 for (int i = 0; i < kWayTooManyForComposeColorFilter; ++i) {
442 filter = make_blue(filter, nullptr);
443 // the first few of these will succeed, but after we hit the internal limit,
444 // it will then return false.
445 (void)filter->asColorFilter(nullptr);
446 }
447 }
448
449 {
450 // Check that a color filter image filter with a crop rect cannot
451 // be expressed as a color filter.
452 SkIRect cropRect = SkIRect::MakeWH(100, 100);
453 sk_sp<SkImageFilter> grayWithCrop(make_grayscale(nullptr, &cropRect));
454 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(nullptr));
455 }
456
457 {
458 // Check that two non-commutative matrices are concatenated in
459 // the correct order.
460 float blueToRedMatrix[20] = { 0 };
461 blueToRedMatrix[2] = blueToRedMatrix[18] = 1;
462 float redToGreenMatrix[20] = { 0 };
463 redToGreenMatrix[5] = redToGreenMatrix[18] = 1;
464 sk_sp<SkColorFilter> blueToRed(SkColorFilters::Matrix(blueToRedMatrix));
465 sk_sp<SkImageFilter> filter1(SkImageFilters::ColorFilter(std::move(blueToRed), nullptr));
466 sk_sp<SkColorFilter> redToGreen(SkColorFilters::Matrix(redToGreenMatrix));
467 sk_sp<SkImageFilter> filter2(SkImageFilters::ColorFilter(std::move(redToGreen),
468 std::move(filter1)));
469
471 result.allocN32Pixels(kBitmapSize, kBitmapSize);
472
474 paint.setColor(SK_ColorBLUE);
475 paint.setImageFilter(std::move(filter2));
476 SkCanvas canvas(result);
477 canvas.clear(0x0);
479 canvas.drawRect(rect, paint);
480 uint32_t pixel = *result.getAddr32(0, 0);
481 // The result here should be green, since we have effectively shifted blue to green.
483 }
484
485 {
486 // Tests pass by not asserting
489 result.allocN32Pixels(kBitmapSize, kBitmapSize);
490
491 {
492 // This tests for :
493 // 1 ) location at (0,0,1)
494 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
495 // 2 ) location and target at same value
496 SkPoint3 target = SkPoint3::Make(location.fX, location.fY, location.fZ);
497 // 3 ) large negative specular exponent value
498 SkScalar specularExponent = -1000;
499
500 sk_sp<SkImageFilter> bmSrc(SkImageFilters::Image(std::move(image), {}));
503 location, target, specularExponent, 180,
504 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1,
505 std::move(bmSrc)));
506 SkCanvas canvas(result);
508 canvas.drawRect(r, paint);
509 }
510 }
511}
static sk_sp< SkImageFilter > make_grayscale(sk_sp< SkImageFilter > input, const SkIRect *cropRect)
static sk_sp< SkImageFilter > make_blue(sk_sp< SkImageFilter > input, const SkIRect *cropRect)
static const int kBitmapSize
static sk_sp< SkImageFilter > make_scale(float amount, sk_sp< SkImageFilter > input)
static sk_sp< SkImage > make_small_image()
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
#define SK_Scalar1
Definition: SkScalar.h:18
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkImageFilter > ColorFilter(sk_sp< SkColorFilter > cf, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
static sk_sp< SkImageFilter > SpotLitSpecular(const SkPoint3 &location, const SkPoint3 &target, SkScalar falloffExponent, SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
void unref() const
Definition: SkRefCnt.h:72
float SkScalar
Definition: extension.cpp:12
GAsyncResult * result
uint32_t * target
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
SkScalar fX
Definition: SkPoint3.h:16
static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z)
Definition: SkPoint3.h:18
SkScalar fZ
Definition: SkPoint3.h:16
SkScalar fY
Definition: SkPoint3.h:16
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623

◆ DEF_TEST() [8/42]

DEF_TEST ( ImageFilterBlurLargeImage  ,
reporter   
)

Definition at line 1767 of file ImageFilterTest.cpp.

1767 {
1769 test_large_blur_input(reporter, surface->getCanvas());
1770}

◆ DEF_TEST() [9/42]

DEF_TEST ( ImageFilterBlurThenShadowBounds  ,
reporter   
)

Definition at line 921 of file ImageFilterTest.cpp.

921 {
922 sk_sp<SkImageFilter> filter1(make_blur(nullptr));
923 sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
924
925 static const SkIRect kContentBounds = SkIRect::MakeXYWH(0, 0, 100, 100);
926
927 // For output, the [0,0,100,100] source is expanded to [-3,-3,103,103] by the initial blur.
928 // The drop shadow is translated by [100,100] and further outset by 30px -> [67,67,233,233],
929 // The blend unions the inner blur result with the drop shadow to get [-3,-3,233,233].
930 static const SkIRect kExpectedOutputBounds = SkIRect::MakeLTRB(-3, -3, 233, 233);
931 SkIRect outputBounds = filter2->filterBounds(kContentBounds,
932 SkMatrix::I(),
934 REPORTER_ASSERT(reporter, outputBounds == kExpectedOutputBounds);
935
936 // For input, it should be able to restrict itself to the source content.
937 SkIRect inputBounds = filter2->filterBounds(kExpectedOutputBounds,
938 SkMatrix::I(),
940 &kContentBounds);
941
942 REPORTER_ASSERT(reporter, inputBounds == kContentBounds);
943}
static sk_sp< SkImageFilter > make_drop_shadow(sk_sp< SkImageFilter > input)
static sk_sp< SkImageFilter > make_blur(sk_sp< SkImageFilter > input)
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91

◆ DEF_TEST() [10/42]

DEF_TEST ( ImageFilterCanComputeFastBounds  ,
reporter   
)

Definition at line 1627 of file ImageFilterTest.cpp.

1627 {
1628
1629 {
1630 SkPoint3 location = SkPoint3::Make(0, 0, SK_Scalar1);
1632 location, SK_ColorGREEN, 0, 0, nullptr));
1633 REPORTER_ASSERT(reporter, !lighting->canComputeFastBounds());
1634 }
1635
1636 {
1637 sk_sp<SkImageFilter> gray(make_grayscale(nullptr, nullptr));
1638 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1639 {
1640 SkColorFilter* grayCF;
1641 REPORTER_ASSERT(reporter, gray->asAColorFilter(&grayCF));
1642 REPORTER_ASSERT(reporter, !as_CFB(grayCF)->affectsTransparentBlack());
1643 grayCF->unref();
1644 }
1645 REPORTER_ASSERT(reporter, gray->canComputeFastBounds());
1646
1648 SK_Scalar1, SK_Scalar1, std::move(gray)));
1649 REPORTER_ASSERT(reporter, grayBlur->canComputeFastBounds());
1650 }
1651
1652 {
1653 float greenMatrix[20] = { 0, 0, 0, 0, 0,
1654 0, 0, 0, 0, 1.0f/255,
1655 0, 0, 0, 0, 0,
1656 0, 0, 0, 0, 1.0f/255
1657 };
1658 sk_sp<SkColorFilter> greenCF(SkColorFilters::Matrix(greenMatrix));
1659 sk_sp<SkImageFilter> green(SkImageFilters::ColorFilter(greenCF, nullptr));
1660
1661 REPORTER_ASSERT(reporter, as_CFB(greenCF)->affectsTransparentBlack());
1662 REPORTER_ASSERT(reporter, !green->canComputeFastBounds());
1663
1665 std::move(green)));
1666 REPORTER_ASSERT(reporter, !greenBlur->canComputeFastBounds());
1667 }
1668
1669 uint8_t allOne[256], identity[256];
1670 for (int i = 0; i < 256; ++i) {
1671 identity[i] = i;
1672 allOne[i] = 255;
1673 }
1674
1676 identity, allOne));
1677 sk_sp<SkImageFilter> identityFilter(SkImageFilters::ColorFilter(identityCF, nullptr));
1678 REPORTER_ASSERT(reporter, !as_CFB(identityCF)->affectsTransparentBlack());
1679 REPORTER_ASSERT(reporter, identityFilter->canComputeFastBounds());
1680
1682 identity, identity));
1683 sk_sp<SkImageFilter> forceOpaque(SkImageFilters::ColorFilter(forceOpaqueCF, nullptr));
1684 REPORTER_ASSERT(reporter, as_CFB(forceOpaqueCF)->affectsTransparentBlack());
1685 REPORTER_ASSERT(reporter, !forceOpaque->canComputeFastBounds());
1686}
static SkColorFilterBase * as_CFB(SkColorFilter *filter)
static sk_sp< SkColorFilter > TableARGB(const uint8_t tableA[256], const uint8_t tableR[256], const uint8_t tableG[256], const uint8_t tableB[256])
static sk_sp< SkImageFilter > PointLitDiffuse(const SkPoint3 &location, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, sk_sp< SkImageFilter > input, const CropRect &cropRect={})

◆ DEF_TEST() [11/42]

DEF_TEST ( ImageFilterClippedPictureImageFilter  ,
reporter   
)

Definition at line 1332 of file ImageFilterTest.cpp.

1332 {
1334}

◆ DEF_TEST() [12/42]

DEF_TEST ( ImageFilterComplexCTM  ,
reporter   
)

Definition at line 1972 of file ImageFilterTest.cpp.

1972 {
1973 // just need a colorfilter to exercise the corresponding imagefilter
1975 sk_sp<SkImageFilter> cfif = SkImageFilters::ColorFilter(cf, nullptr); // can handle
1976 sk_sp<SkImageFilter> blif = SkImageFilters::Blur(3, 3, nullptr); // cannot handle
1978
1979 struct {
1980 sk_sp<SkImageFilter> fFilter;
1981 MatrixCapability fExpectCapability;
1982 } recs[] = {
1983 { cfif, MatrixCapability::kComplex },
1984 { SkImageFilters::ColorFilter(cf, cfif), MatrixCapability::kComplex },
1985 { SkImageFilters::Merge(cfif, cfif), MatrixCapability::kComplex },
1986 { SkImageFilters::Compose(cfif, cfif), MatrixCapability::kComplex },
1987
1988 { blif, MatrixCapability::kScaleTranslate },
1989 { SkImageFilters::Blur(3, 3, cfif), MatrixCapability::kScaleTranslate },
1990 { SkImageFilters::ColorFilter(cf, blif), MatrixCapability::kScaleTranslate },
1991 { SkImageFilters::Merge(cfif, blif), MatrixCapability::kScaleTranslate },
1992 { SkImageFilters::Compose(blif, cfif), MatrixCapability::kScaleTranslate },
1993 };
1994
1995 for (const auto& rec : recs) {
1996 const MatrixCapability capability = as_IFB(rec.fFilter)->getCTMCapability();
1997 REPORTER_ASSERT(reporter, capability == rec.fExpectCapability);
1998 }
1999}
@ kSrcATop
r = s*da + d*(1-sa)
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static SkImageFilter_Base * as_IFB(SkImageFilter *filter)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
skif::MatrixCapability MatrixCapability
MatrixCapability getCTMCapability() const
static sk_sp< SkImageFilter > Merge(sk_sp< SkImageFilter > *const filters, int count, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Compose(sk_sp< SkImageFilter > outer, sk_sp< SkImageFilter > inner)

◆ DEF_TEST() [13/42]

DEF_TEST ( ImageFilterComposedBlurFastBounds  ,
reporter   
)

Definition at line 1042 of file ImageFilterTest.cpp.

1042 {
1043 sk_sp<SkImageFilter> filter1(make_blur(nullptr));
1044 sk_sp<SkImageFilter> filter2(make_blur(nullptr));
1045 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(filter1),
1046 std::move(filter2)));
1047
1048 static const SkRect kBoundsSrc = SkRect::MakeIWH(100, 100);
1049 static const SkRect kExpectedBounds = SkRect::MakeXYWH(-6, -6, 112, 112);
1050 SkRect boundsDst = composedFilter->computeFastBounds(kBoundsSrc);
1051
1052 REPORTER_ASSERT(reporter, boundsDst == kExpectedBounds);
1053}
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659

◆ DEF_TEST() [14/42]

DEF_TEST ( ImageFilterCropRect  ,
reporter   
)

Definition at line 1267 of file ImageFilterTest.cpp.

1267 {
1268 test_cropRects(reporter, nullptr);
1269}

◆ DEF_TEST() [15/42]

DEF_TEST ( ImageFilterDilateThenBlurBounds  ,
reporter   
)

Definition at line 967 of file ImageFilterTest.cpp.

967 {
968 sk_sp<SkImageFilter> filter1(SkImageFilters::Dilate(2, 2, nullptr));
969 sk_sp<SkImageFilter> filter2(make_drop_shadow(std::move(filter1)));
970
971 static const SkIRect kContentBounds = SkIRect::MakeXYWH(0, 0, 100, 100);
972 // For output, the [0,0,100,100] source is outset by dilate radius (2px) to [-2,-2,102,102].
973 // This is then translated by 100px and outset by 30px for the drop shadow = [68,68,232,232].
974 // Finally this is joined with the original dilate result to get [-2,-2,232,232].
975 static const SkIRect kExpectedOutputBounds = SkIRect::MakeLTRB(-2, -2, 232, 232);
976 SkIRect outputBounds = filter2->filterBounds(kContentBounds,
977 SkMatrix::I(),
979 REPORTER_ASSERT(reporter, outputBounds == kExpectedOutputBounds);
980
981 // For input, it should be able to restrict itself to the source content.
982 SkIRect inputBounds = filter2->filterBounds(kExpectedOutputBounds,
983 SkMatrix::I(),
985 &kContentBounds);
986 REPORTER_ASSERT(reporter, inputBounds == kContentBounds);
987}
static sk_sp< SkImageFilter > Dilate(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})

◆ DEF_TEST() [16/42]

DEF_TEST ( ImageFilterDrawMatrixBBH  ,
reporter   
)

Definition at line 891 of file ImageFilterTest.cpp.

891 {
892 // Check that matrix filter when drawn tiled with BBH exactly
893 // matches the same thing drawn without BBH.
894 // Tests pass by not asserting.
895
896 const int width = 200, height = 200;
897 const int tileSize = 100;
898 SkBitmap result1, result2;
899 SkRTreeFactory factory;
900
901 draw_saveLayer_picture(width, height, tileSize, &factory, &result1);
902 draw_saveLayer_picture(width, height, tileSize, nullptr, &result2);
903
904 for (int y = 0; y < height; y++) {
905 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
906 REPORTER_ASSERT(reporter, !diffs);
907 if (diffs) {
908 break;
909 }
910 }
911}
static void draw_saveLayer_picture(int width, int height, int tileSize, SkBBHFactory *factory, SkBitmap *result)
size_t rowBytes() const
Definition: SkBitmap.h:238
uint32_t * getAddr32(int x, int y) const
Definition: SkBitmap.h:1260
double y

◆ DEF_TEST() [17/42]

DEF_TEST ( ImageFilterDrawTiled  ,
reporter   
)

Definition at line 783 of file ImageFilterTest.cpp.

783 {
784 // Check that all filters when drawn tiled (with subsequent clip rects) exactly
785 // match the same filters drawn with a single full-canvas bitmap draw.
786 // Tests pass by not asserting.
787
788 FilterList filters(nullptr);
789
790 SkBitmap untiledResult, tiledResult;
791 const int width = 64, height = 64;
792 untiledResult.allocN32Pixels(width, height);
793 tiledResult.allocN32Pixels(width, height);
794 SkCanvas tiledCanvas(tiledResult);
795 SkCanvas untiledCanvas(untiledResult);
796 const int tileSize = 8;
797
798 SkPaint textPaint;
799 textPaint.setColor(SK_ColorWHITE);
801
802 const char* text = "ABC";
803 const SkScalar yPos = SkIntToScalar(height);
804
805 for (int scale = 1; scale <= 2; ++scale) {
806 for (int i = 0; i < filters.count(); ++i) {
807 SkPaint combinedPaint;
808 combinedPaint.setColor(SK_ColorWHITE);
809 combinedPaint.setImageFilter(sk_ref_sp(filters.getFilter(i)));
810
811 untiledCanvas.clear(SK_ColorTRANSPARENT);
812 untiledCanvas.save();
813 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
814 untiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
815 untiledCanvas.restore();
816
817 tiledCanvas.clear(SK_ColorTRANSPARENT);
818 for (int y = 0; y < height; y += tileSize) {
819 for (int x = 0; x < width; x += tileSize) {
820 tiledCanvas.save();
821 const SkRect clipRect = SkRect::MakeXYWH(x, y, tileSize, tileSize);
822 tiledCanvas.clipRect(clipRect);
823 if (filters.needsSaveLayer(i)) {
824 tiledCanvas.saveLayer(nullptr, &combinedPaint);
825 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
826 tiledCanvas.drawString(text, 0, yPos, font, textPaint);
827 tiledCanvas.restore();
828 } else {
829 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
830 tiledCanvas.drawString(text, 0, yPos, font, combinedPaint);
831 }
832
833 tiledCanvas.restore();
834 }
835 }
836
837 if (!ToolUtils::equal_pixels(untiledResult, tiledResult)) {
838 SkString encoded;
839 SkString errString("Tiled image filter doesn't match untiled reference");
840 errString.append("\nExpected: ");
841 if (ToolUtils::BitmapToBase64DataURI(untiledResult, &encoded)) {
842 errString.append(encoded);
843 } else {
844 errString.append("failed to encode");
845 }
846
847 errString.append("\nActual: ");
848 if (ToolUtils::BitmapToBase64DataURI(tiledResult, &encoded)) {
849 errString.append(encoded);
850 } else {
851 errString.append("failed to encode");
852 }
853
854 ERRORF(reporter, "%s\n%s", filters.getName(i), errString.c_str());
855 }
856 }
857 }
858}
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SkIntToScalar(x)
Definition: SkScalar.h:57
#define ERRORF(r,...)
Definition: Test.h:293
Definition: SkFont.h:35
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
std::u16string text
double x
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
sk_sp< SkTypeface > DefaultPortableTypeface()
bool BitmapToBase64DataURI(const SkBitmap &bitmap, SkString *dst)
Definition: EncodeUtils.cpp:25
bool equal_pixels(const SkPixmap &a, const SkPixmap &b)
Definition: ToolUtils.cpp:456
font
Font Metadata and Metrics.
const Scalar scale

◆ DEF_TEST() [18/42]

DEF_TEST ( ImageFilterDrawTiledBlurRTree  ,
reporter   
)

Definition at line 1125 of file ImageFilterTest.cpp.

1125 {
1126 // Check that the blur filter when recorded with RTree acceleration,
1127 // and drawn tiled (with subsequent clip rects) exactly
1128 // matches the same filter drawn with without RTree acceleration.
1129 // This tests that the "bleed" from the blur into the otherwise-blank
1130 // tiles is correctly rendered.
1131 // Tests pass by not asserting.
1132
1133 int width = 16, height = 8;
1134 SkBitmap result1, result2;
1135 result1.allocN32Pixels(width, height);
1136 result2.allocN32Pixels(width, height);
1137 SkCanvas canvas1(result1);
1138 SkCanvas canvas2(result2);
1139 int tileSize = 8;
1140
1141 canvas1.clear(0);
1142 canvas2.clear(0);
1143
1144 SkRTreeFactory factory;
1145
1146 SkPictureRecorder recorder1, recorder2;
1147 // The only difference between these two pictures is that one has RTree aceleration.
1148 SkCanvas* recordingCanvas1 = recorder1.beginRecording(width, height);
1149 SkCanvas* recordingCanvas2 = recorder2.beginRecording(width, height, &factory);
1150
1151 draw_blurred_rect(recordingCanvas1);
1152 draw_blurred_rect(recordingCanvas2);
1153 sk_sp<SkPicture> picture1(recorder1.finishRecordingAsPicture());
1154 sk_sp<SkPicture> picture2(recorder2.finishRecordingAsPicture());
1155 for (int y = 0; y < height; y += tileSize) {
1156 for (int x = 0; x < width; x += tileSize) {
1157 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize));
1158 draw_picture_clipped(&canvas1, tileRect, picture1.get());
1159 draw_picture_clipped(&canvas2, tileRect, picture2.get());
1160 }
1161 }
1162 for (int y = 0; y < height; y++) {
1163 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes());
1164 REPORTER_ASSERT(reporter, !diffs);
1165 if (diffs) {
1166 break;
1167 }
1168 }
1169}
static void draw_blurred_rect(SkCanvas *canvas)
static void draw_picture_clipped(SkCanvas *canvas, const SkRect &clipRect, const SkPicture *picture)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()

◆ DEF_TEST() [19/42]

DEF_TEST ( ImageFilterEmptySaveLayer  ,
reporter   
)

Definition at line 1343 of file ImageFilterTest.cpp.

1343 {
1344 // Even when there's an empty saveLayer()/restore(), ensure that an image
1345 // filter or color filter which affects transparent black still draws.
1346
1348 bitmap.allocN32Pixels(10, 10);
1349 SkCanvas canvas(bitmap);
1350
1351 SkRTreeFactory factory;
1352 SkPictureRecorder recorder;
1353
1355 sk_sp<SkImageFilter> imageFilter(SkImageFilters::ColorFilter(green, nullptr));
1356 SkPaint imageFilterPaint;
1357 imageFilterPaint.setImageFilter(std::move(imageFilter));
1358 SkPaint colorFilterPaint;
1359 colorFilterPaint.setColorFilter(green);
1360
1361 SkRect bounds = SkRect::MakeIWH(10, 10);
1362
1363 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory);
1364 recordingCanvas->saveLayer(&bounds, &imageFilterPaint);
1365 recordingCanvas->restore();
1367
1368 canvas.clear(0);
1369 canvas.drawPicture(picture);
1370 uint32_t pixel = *bitmap.getAddr32(0, 0);
1372
1373 recordingCanvas = recorder.beginRecording(10, 10, &factory);
1374 recordingCanvas->saveLayer(nullptr, &imageFilterPaint);
1375 recordingCanvas->restore();
1376 sk_sp<SkPicture> picture2(recorder.finishRecordingAsPicture());
1377
1378 canvas.clear(0);
1379 canvas.drawPicture(picture2);
1380 pixel = *bitmap.getAddr32(0, 0);
1382
1383 recordingCanvas = recorder.beginRecording(10, 10, &factory);
1384 recordingCanvas->saveLayer(&bounds, &colorFilterPaint);
1385 recordingCanvas->restore();
1386 sk_sp<SkPicture> picture3(recorder.finishRecordingAsPicture());
1387
1388 canvas.clear(0);
1389 canvas.drawPicture(picture3);
1390 pixel = *bitmap.getAddr32(0, 0);
1392}
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void restore()
Definition: SkCanvas.cpp:461
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkPicture > picture
Definition: SkRecords.h:299
Definition: bitmap.py:1

◆ DEF_TEST() [20/42]

DEF_TEST ( ImageFilterFailAffectsTransparentBlack  ,
reporter   
)

Definition at line 772 of file ImageFilterTest.cpp.

772 {
774}

◆ DEF_TEST() [21/42]

DEF_TEST ( ImageFilterImageSourceSerialization  ,
reporter   
)

Definition at line 1689 of file ImageFilterTest.cpp.

1689 {
1691 surface->getCanvas()->clear(SK_ColorGREEN);
1692 sk_sp<SkImage> image(surface->makeImageSnapshot());
1694
1695 SkSerialProcs sProcs;
1696 sProcs.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
1697 return SkPngEncoder::Encode(as_IB(img)->directContext(), img, SkPngEncoder::Options{});
1698 };
1699 sk_sp<SkData> data(filter->serialize(&sProcs));
1700 sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
1701 REPORTER_ASSERT(reporter, unflattenedFilter);
1702
1703 SkBitmap bm;
1704 bm.allocN32Pixels(10, 10);
1706 SkPaint paint;
1707 paint.setColor(SK_ColorRED);
1708 paint.setImageFilter(unflattenedFilter);
1709
1710 SkCanvas canvas(bm);
1711 canvas.drawRect(SkRect::MakeIWH(10, 10), paint);
1713}
SK_API SkPMColor SkPreMultiplyColor(SkColor c)
Definition: SkColor.cpp:21
static SkImage_Base * as_IB(SkImage *image)
Definition: SkImage_Base.h:201
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
static sk_sp< SkImageFilter > Deserialize(const void *data, size_t size, const SkDeserialProcs *procs=nullptr)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
SkSerialImageProc fImageProc
Definition: SkSerialProcs.h:90
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ DEF_TEST() [22/42]

DEF_TEST ( ImageFilterImageSourceUninitialized  ,
 
)

Definition at line 1715 of file ImageFilterTest.cpp.

1715 {
1716 sk_sp<SkData> data(GetResourceAsData("crbug769134.fil"));
1717 if (!data) {
1718 return;
1719 }
1720 sk_sp<SkImageFilter> unflattenedFilter = SkImageFilter::Deserialize(data->data(), data->size());
1721 // This will fail. More importantly, msan will verify that we did not
1722 // compare against uninitialized memory.
1723 REPORTER_ASSERT(r, !unflattenedFilter);
1724}
sk_sp< SkData > GetResourceAsData(const char *resource)
Definition: Resources.cpp:42

◆ DEF_TEST() [23/42]

DEF_TEST ( ImageFilterMakeWithFilter  ,
reporter   
)

Definition at line 1846 of file ImageFilterTest.cpp.

1846 {
1847 auto createRasterSurface = [](int width, int height) -> sk_sp<SkSurface> {
1849 return SkSurfaces::Raster(info);
1850 };
1851
1852 auto raster = [](sk_sp<SkImage> src,
1853 const SkImageFilter* filter,
1854 const SkIRect& subset,
1855 const SkIRect& clipBounds,
1856 SkIRect* outSubset,
1858 return SkImages::MakeWithFilter(std::move(src),
1859 filter,
1860 subset,
1861 clipBounds,
1862 outSubset,
1863 offset);
1864 };
1865
1866 test_make_with_filter(reporter, createRasterSurface, raster);
1867}

◆ DEF_TEST() [24/42]

DEF_TEST ( ImageFilterMatrix  ,
reporter   
)

Definition at line 1278 of file ImageFilterTest.cpp.

1278 {
1279 SkBitmap temp;
1280 temp.allocN32Pixels(100, 100);
1281 SkCanvas canvas(temp);
1282 canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
1283
1284 SkMatrix expectedMatrix = canvas.getTotalMatrix();
1285
1286 SkRTreeFactory factory;
1287 SkPictureRecorder recorder;
1288 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory);
1289
1290 SkPaint paint;
1291 paint.setImageFilter(sk_sp<SkImageFilter>(new MatrixTestImageFilter(reporter, expectedMatrix)));
1292 recordingCanvas->saveLayer(nullptr, &paint);
1293 SkPaint solidPaint;
1294 solidPaint.setColor(0xFFFFFFFF);
1295 recordingCanvas->save();
1296 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10));
1297 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
1298 recordingCanvas->restore(); // scale
1299 recordingCanvas->restore(); // saveLayer
1300
1301 canvas.drawPicture(recorder.finishRecordingAsPicture());
1302}
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
int save()
Definition: SkCanvas.cpp:447
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289

◆ DEF_TEST() [25/42]

DEF_TEST ( ImageFilterMatrixConvolution  ,
reporter   
)

Definition at line 1171 of file ImageFilterTest.cpp.

1171 {
1172 // Check that a 1x3 filter does not cause a spurious assert.
1173 SkScalar kernel[3] = {
1175 };
1176 SkISize kernelSize = SkISize::Make(1, 3);
1177 SkScalar gain = SK_Scalar1, bias = 0;
1178 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1179
1181 kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kRepeat, false, nullptr));
1182
1184 int width = 16, height = 16;
1185 result.allocN32Pixels(width, height);
1186 SkCanvas canvas(result);
1187 canvas.clear(0);
1188
1189 SkPaint paint;
1190 paint.setImageFilter(std::move(filter));
1192 canvas.drawRect(rect, paint);
1193}
static sk_sp< SkImageFilter > MatrixConvolution(const SkISize &kernelSize, const SkScalar kernel[], SkScalar gain, SkScalar bias, const SkIPoint &kernelOffset, SkTileMode tileMode, bool convolveAlpha, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static constexpr SkIPoint Make(int32_t x, int32_t y)
Definition: SkPoint_impl.h:38
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20

◆ DEF_TEST() [26/42]

DEF_TEST ( ImageFilterMatrixConvolutionBigKernel  ,
reporter   
)

Definition at line 1256 of file ImageFilterTest.cpp.

1256 {
1257 test_big_kernel(reporter, nullptr);
1258}

◆ DEF_TEST() [27/42]

DEF_TEST ( ImageFilterMatrixConvolutionBorder  ,
reporter   
)

Definition at line 1195 of file ImageFilterTest.cpp.

1195 {
1196 // Check that a filter with borders outside the target bounds
1197 // does not crash.
1198 SkScalar kernel[3] = {
1199 0, 0, 0,
1200 };
1201 SkISize kernelSize = SkISize::Make(3, 1);
1202 SkScalar gain = SK_Scalar1, bias = 0;
1203 SkIPoint kernelOffset = SkIPoint::Make(2, 0);
1204
1206 kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kClamp, true, nullptr));
1207
1209
1210 int width = 10, height = 10;
1211 result.allocN32Pixels(width, height);
1212 SkCanvas canvas(result);
1213 canvas.clear(0);
1214
1215 SkPaint filterPaint;
1216 filterPaint.setImageFilter(std::move(filter));
1217 SkRect bounds = SkRect::MakeIWH(1, 10);
1219 SkPaint rectPaint;
1220 canvas.saveLayer(&bounds, &filterPaint);
1221 canvas.drawRect(rect, rectPaint);
1222 canvas.restore();
1223}

◆ DEF_TEST() [28/42]

DEF_TEST ( ImageFilterMatrixConvolutionTest  ,
reporter   
)

Definition at line 1412 of file ImageFilterTest.cpp.

1412 {
1413 SkScalar kernel[1] = { 0 };
1414 SkScalar gain = SK_Scalar1, bias = 0;
1415 SkIPoint kernelOffset = SkIPoint::Make(1, 1);
1416
1417 // Check that an enormous (non-allocatable) kernel gives a nullptr filter.
1419 SkISize::Make(1<<30, 1<<30), kernel, gain, bias, kernelOffset,
1420 SkTileMode::kRepeat, false, nullptr));
1421
1422 REPORTER_ASSERT(reporter, nullptr == conv.get());
1423
1424 // Check that a nullptr kernel gives a nullptr filter.
1426 SkISize::Make(1, 1), nullptr, gain, bias, kernelOffset,
1427 SkTileMode::kRepeat, false, nullptr);
1428
1429 REPORTER_ASSERT(reporter, nullptr == conv.get());
1430
1431 // Check that a kernel width < 1 gives a nullptr filter.
1433 SkISize::Make(0, 1), kernel, gain, bias, kernelOffset,
1434 SkTileMode::kRepeat, false, nullptr);
1435
1436 REPORTER_ASSERT(reporter, nullptr == conv.get());
1437
1438 // Check that kernel height < 1 gives a nullptr filter.
1440 SkISize::Make(1, -1), kernel, gain, bias, kernelOffset,
1441 SkTileMode::kRepeat, false, nullptr);
1442
1443 REPORTER_ASSERT(reporter, nullptr == conv.get());
1444}

◆ DEF_TEST() [29/42]

DEF_TEST ( ImageFilterMergeResultSize  ,
reporter   
)

Definition at line 1096 of file ImageFilterTest.cpp.

1096 {
1098}

◆ DEF_TEST() [30/42]

DEF_TEST ( ImageFilterNegativeBlurSigma  ,
reporter   
)

Definition at line 606 of file ImageFilterTest.cpp.

606 {
608}

◆ DEF_TEST() [31/42]

DEF_TEST ( ImageFilterNestedSaveLayer  ,
reporter   
)

Definition at line 1497 of file ImageFilterTest.cpp.

1497 {
1498 SkBitmap temp;
1499 temp.allocN32Pixels(50, 50);
1500 SkCanvas canvas(temp);
1501 canvas.clear(0x0);
1502
1504 bitmap.allocN32Pixels(10, 10);
1505 bitmap.eraseColor(SK_ColorGREEN);
1506
1508 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2));
1509 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20));
1510 sk_sp<SkImageFilter> matrixFilter(
1512
1513 // Test that saveLayer() with a filter nested inside another saveLayer() applies the
1514 // correct offset to the filter matrix.
1515 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30);
1516 canvas.saveLayer(&bounds1, nullptr);
1517 SkPaint filterPaint;
1518 filterPaint.setImageFilter(std::move(matrixFilter));
1519 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10);
1520 canvas.saveLayer(&bounds2, &filterPaint);
1521 SkPaint greenPaint;
1522 greenPaint.setColor(SK_ColorGREEN);
1523 canvas.drawRect(bounds2, greenPaint);
1524 canvas.restore();
1525 canvas.restore();
1526 SkPaint strokePaint;
1527 strokePaint.setStyle(SkPaint::kStroke_Style);
1528 strokePaint.setColor(SK_ColorRED);
1529
1531 uint32_t pixel;
1532 temp.readPixels(info, &pixel, 4, 25, 25);
1534
1535 // Test that drawSprite() with a filter nested inside a saveLayer() applies the
1536 // correct offset to the filter matrix.
1537 canvas.clear(0x0);
1538 temp.readPixels(info, &pixel, 4, 25, 25);
1539 canvas.saveLayer(&bounds1, nullptr);
1540 canvas.drawImage(bitmap.asImage(), 20, 20, SkSamplingOptions(), &filterPaint); // drawSprite
1541 canvas.restore();
1542
1543 temp.readPixels(info, &pixel, 4, 25, 25);
1545}
kUnpremul_SkAlphaType
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
bool readPixels(const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY) const
Definition: SkBitmap.cpp:488
static sk_sp< SkImageFilter > MatrixTransform(const SkMatrix &matrix, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input)
void setStyle(Style style)
Definition: SkPaint.cpp:105
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
SkSamplingOptions(SkFilterMode::kLinear))

◆ DEF_TEST() [32/42]

DEF_TEST ( ImageFilterScaledBlurRadius  ,
reporter   
)

Definition at line 989 of file ImageFilterTest.cpp.

989 {
990 // Each blur should spread 3*sigma, so 3 for the blur and 30 for the shadow
991 // (before the CTM). Bounds should be computed correctly in the presence of
992 // a (possibly negative) scale.
993 sk_sp<SkImageFilter> blur(make_blur(nullptr));
994 sk_sp<SkImageFilter> dropShadow(make_drop_shadow(nullptr));
995 {
996 // Uniform scale by 2.
998 scaleMatrix.setScale(2, 2);
999 static const SkIRect kBounds = SkIRect::MakeLTRB(0, 0, 200, 200);
1000
1001 static const SkIRect kExpectedBlurBounds = SkIRect::MakeLTRB(-6, -6, 206, 206);
1002 SkIRect blurBounds = blur->filterBounds(
1004 REPORTER_ASSERT(reporter, blurBounds == kExpectedBlurBounds);
1005 SkIRect reverseBlurBounds = blur->filterBounds(
1006 kExpectedBlurBounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &kBounds);
1007 REPORTER_ASSERT(reporter, reverseBlurBounds == kBounds);
1008
1009 static const SkIRect kExpectedShadowBounds = SkIRect::MakeLTRB(0, 0, 460, 460);
1010 SkIRect shadowBounds = dropShadow->filterBounds(
1012 REPORTER_ASSERT(reporter, shadowBounds == kExpectedShadowBounds);
1013
1014 SkIRect reverseShadowBounds = dropShadow->filterBounds(
1015 kExpectedShadowBounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &kBounds);
1016 REPORTER_ASSERT(reporter, reverseShadowBounds == kBounds);
1017 }
1018 {
1019 // Vertical flip.
1021 scaleMatrix.setScale(1, -1);
1022 static const SkIRect kBounds = SkIRect::MakeLTRB(0, -100, 100, 0);
1023
1024 static const SkIRect kExpectedBlurBounds = SkIRect::MakeLTRB(-3, -103, 103, 3);
1025 SkIRect blurBounds = blur->filterBounds(
1027 REPORTER_ASSERT(reporter, blurBounds == kExpectedBlurBounds);
1028 SkIRect reverseBlurBounds = blur->filterBounds(
1029 kExpectedBlurBounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &kBounds);
1030 REPORTER_ASSERT(reporter, reverseBlurBounds == kBounds);
1031
1032 SkIRect kExpectedShadowBounds = SkIRect::MakeLTRB(0, -230, 230, 0);
1033 SkIRect shadowBounds = dropShadow->filterBounds(
1035 REPORTER_ASSERT(reporter, shadowBounds == kExpectedShadowBounds);
1036 SkIRect reverseShadowBounds = dropShadow->filterBounds(
1037 kExpectedShadowBounds, scaleMatrix, SkImageFilter::kReverse_MapDirection, &kBounds);
1038 REPORTER_ASSERT(reporter, reverseShadowBounds == kBounds);
1039 }
1040}
static void scaleMatrix(const SkPath &one, const SkPath &two, SkMatrix &scale)

◆ DEF_TEST() [33/42]

DEF_TEST ( ImageFilterShadowThenBlurBounds  ,
reporter   
)

Definition at line 945 of file ImageFilterTest.cpp.

945 {
946 sk_sp<SkImageFilter> filter1(make_drop_shadow(nullptr));
947 sk_sp<SkImageFilter> filter2(make_blur(std::move(filter1)));
948
949 static const SkIRect kContentBounds = SkIRect::MakeXYWH(0, 0, 100, 100);
950 // For output, the [0,0,100,100] source is translated by 100px and outset by 30px for the drop
951 // shadow = [70,70,230,230], then blended back with its original to get [0,0,230,230]. This is
952 // then outset by 3px for the outer blur to get [-3,-3,233,233].
953 static const SkIRect kExpectedOutputBounds = SkIRect::MakeLTRB(-3, -3, 233, 233);
954 SkIRect outputBounds = filter2->filterBounds(kContentBounds,
955 SkMatrix::I(),
957 REPORTER_ASSERT(reporter, outputBounds == kExpectedOutputBounds);
958
959 // For input, it should be able to restrict itself to the source content.
960 SkIRect inputBounds = filter2->filterBounds(kExpectedOutputBounds,
961 SkMatrix::I(),
963 &kContentBounds);
964 REPORTER_ASSERT(reporter, inputBounds == kContentBounds);
965}

◆ DEF_TEST() [34/42]

DEF_TEST ( ImageFilterUnionBounds  ,
reporter   
)

Definition at line 1055 of file ImageFilterTest.cpp.

1055 {
1057 // Regardless of which order they appear in, the image filter bounds should
1058 // be combined correctly.
1059 {
1061 SkRect bounds = SkRect::MakeIWH(100, 100);
1062 // Intentionally aliasing here, as that's what the real callers do.
1063 bounds = composite->computeFastBounds(bounds);
1065 }
1066 {
1068 offset, nullptr));
1069 SkRect bounds = SkRect::MakeIWH(100, 100);
1070 // Intentionally aliasing here, as that's what the real callers do.
1071 bounds = composite->computeFastBounds(bounds);
1073 }
1074}
@ kSrcOver
r = s + (1-sa)*d
static sk_sp< SkImageFilter > Blend(SkBlendMode mode, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground=nullptr, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Offset(SkScalar dx, SkScalar dy, sk_sp< SkImageFilter > input, const CropRect &cropRect={})

◆ DEF_TEST() [35/42]

DEF_TEST ( ImageFilterZeroBlurSigma  ,
reporter   
)

Definition at line 738 of file ImageFilterTest.cpp.

738 {
740}

◆ DEF_TEST() [36/42]

DEF_TEST ( ImageSourceBounds  ,
reporter   
)

Definition at line 2216 of file ImageFilterTest.cpp.

2216 {
2217 sk_sp<SkImage> image(make_gradient_circle(64, 64).asImage());
2218 // Default src and dst rects.
2220 SkIRect imageBounds = SkIRect::MakeWH(64, 64);
2221 SkIRect input(SkIRect::MakeXYWH(10, 20, 30, 40));
2223 imageBounds == source1->filterBounds(input, SkMatrix::I(),
2225 nullptr));
2227 source1->filterBounds(input, SkMatrix::I(),
2228 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2230 SkIRect scaledBounds = SkIRect::MakeWH(128, 128);
2232 scaledBounds == source1->filterBounds(input, scale,
2234 nullptr));
2236 source1->filterBounds(input, scale,
2237 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2238
2239 // Specified src and dst rects (which are outside available pixels).
2240 SkRect src(SkRect::MakeXYWH(0.5, 0.5, 100.5, 100.5));
2241 SkRect dst(SkRect::MakeXYWH(-10.5, -10.5, 120.5, 120.5));
2245
2246 SkRect clippedSrc = src;
2248 SkRect clippedDst = SkMatrix::RectToRect(src, dst).mapRect(clippedSrc);
2249
2251 clippedDst.roundOut() ==
2252 source2->filterBounds(input, SkMatrix::I(),
2255 source2->filterBounds(input, SkMatrix::I(),
2256 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2257 scale.mapRect(&clippedDst);
2258 scale.mapRect(&clippedSrc);
2260 clippedDst.roundOut() ==
2261 source2->filterBounds(input, scale,
2264 source2->filterBounds(input, scale,
2265 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2266}
SkISize dimensions() const
Definition: SkImage.h:297
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
Definition: SkMatrix.h:157
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
static sk_sp< SkImage > make_gradient_circle(int width, int height)
dst
Definition: cp.py:12
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114
void roundOut(SkIRect *dst) const
Definition: SkRect.h:1241

◆ DEF_TEST() [37/42]

DEF_TEST ( MorphologyFilterRadiusWithMirrorCTM  ,
reporter   
)

Definition at line 695 of file ImageFilterTest.cpp.

◆ DEF_TEST() [38/42]

DEF_TEST ( OffsetImageFilterBounds  ,
reporter   
)

Definition at line 2051 of file ImageFilterTest.cpp.

2051 {
2052 const SkIRect src = SkIRect::MakeXYWH(0, 0, 100, 100);
2053 const SkVector srcOffset = {-50.5f, -50.5f};
2054 sk_sp<SkImageFilter> offset(SkImageFilters::Offset(srcOffset.fX, srcOffset.fY, nullptr));
2055
2056 // Because the offset has a fractional component, the final output and required input bounds
2057 // will be rounded out to include an extra pixel.
2058 SkIRect expectedForward = SkRect::Make(src).makeOffset(srcOffset.fX, srcOffset.fY).roundOut();
2059 SkIRect boundsForward = offset->filterBounds(src, SkMatrix::I(),
2061 REPORTER_ASSERT(reporter, boundsForward == expectedForward);
2062
2063 SkIRect expectedReverse = SkRect::Make(src).makeOffset(-srcOffset.fX, -srcOffset.fY).roundOut();
2064
2065 // Intersect 'expectedReverse' with the source because we are passing &src in as the known
2066 // input bounds, which is the bounds of non-transparent pixels that can be moved by the offset.
2067 // While the ::Offset filter could show all pixels inside 'expectedReverse' given that 'src'
2068 // is also the target device output of the filter, the required input can be made tighter.
2069 SkAssertResult(expectedReverse.intersect(src));
2070
2071 SkIRect boundsReverse = offset->filterBounds(src, SkMatrix::I(),
2073 REPORTER_ASSERT(reporter, boundsReverse == expectedReverse);
2074}
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
constexpr SkRect makeOffset(float dx, float dy) const
Definition: SkRect.h:965

◆ DEF_TEST() [39/42]

DEF_TEST ( OffsetImageFilterBoundsNoOverflow  ,
reporter   
)

Definition at line 2076 of file ImageFilterTest.cpp.

2076 {
2077 const SkIRect src = SkIRect::MakeXYWH(-10.f, -10.f, 20.f, 20.f);
2078 const SkScalar bigOffset = SkIntToScalar(std::numeric_limits<int>::max()) * 2.f / 3.f;
2079
2080 sk_sp<SkImageFilter> filter =
2082 SkImageFilters::Offset(-bigOffset, -bigOffset, nullptr),
2083 SkImageFilters::Offset(bigOffset, bigOffset, nullptr));
2084 SkIRect boundsForward = filter->filterBounds(src, SkMatrix::I(),
2086 // NOTE: isEmpty() will return true even if the l/r or t/b didn't overflow but the dimensions
2087 // would overflow an int32. However, when isEmpty64() is false, it means the actual edge coords
2088 // are valid, which is good enough for our purposes (and gfx::Rect has its own strategies for
2089 // ensuring such a rectangle doesn't get accidentally treated as empty during chromium's
2090 // conversions).
2091 REPORTER_ASSERT(reporter, !boundsForward.isEmpty64());
2092
2093 // When querying with unbounded input content, it should not overflow and should not be empty.
2094 SkIRect boundsReverse = filter->filterBounds(src, SkMatrix::I(),
2096 REPORTER_ASSERT(reporter, !boundsReverse.isEmpty64());
2097
2098 // However in this case, when 'src' is also passed as the content bounds, the ::Offset() filters
2099 // detect that they would be transparent black. This propagates up to the src-over blend and
2100 // the entire graph is identified as empty.
2101 boundsReverse = filter->filterBounds(src, SkMatrix::I(),
2103 REPORTER_ASSERT(reporter, boundsReverse.isEmpty64());
2104}
SkIRect filterBounds(const SkIRect &src, const SkMatrix &ctm, MapDirection, const SkIRect *inputRect=nullptr) const
static float max(float r, float g, float b)
Definition: hsl.cpp:49
bool isEmpty64() const
Definition: SkRect.h:196

◆ DEF_TEST() [40/42]

DEF_TEST ( PictureImageSourceBounds  ,
reporter   
)

Definition at line 2269 of file ImageFilterTest.cpp.

2269 {
2270 SkPictureRecorder recorder;
2271 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64);
2272
2273 SkPaint greenPaint;
2274 greenPaint.setColor(SK_ColorGREEN);
2275 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint);
2277
2278 // Default target rect.
2280 SkIRect pictureBounds = SkIRect::MakeWH(64, 64);
2281 SkIRect input(SkIRect::MakeXYWH(10, 20, 30, 40));
2283 pictureBounds == source1->filterBounds(input, SkMatrix::I(),
2285 nullptr));
2287 source1->filterBounds(input, SkMatrix::I(),
2288 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2290 SkIRect scaledPictureBounds = SkIRect::MakeWH(128, 128);
2292 scaledPictureBounds == source1->filterBounds(input, scale,
2294 nullptr));
2296 source1->filterBounds(input, scale,
2297 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2298
2299 // Specified target rect.
2300 SkRect targetRect(SkRect::MakeXYWH(9.5, 9.5, 31, 21));
2303 targetRect.roundOut() == source2->filterBounds(input, SkMatrix::I(),
2305 nullptr));
2307 source2->filterBounds(input, SkMatrix::I(),
2308 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2309 scale.mapRect(&targetRect);
2311 targetRect.roundOut() == source2->filterBounds(input, scale,
2313 nullptr));
2315 source2->filterBounds(input, scale,
2316 SkImageFilter::kReverse_MapDirection, &input).isEmpty());
2317}
static sk_sp< SkImageFilter > Picture(sk_sp< SkPicture > pic, const SkRect &targetRect)

◆ DEF_TEST() [41/42]

DEF_TEST ( XfermodeImageFilterBounds  ,
reporter   
)

Definition at line 2002 of file ImageFilterTest.cpp.

2002 {
2003 SkIRect background_rect = SkIRect::MakeXYWH(0, 0, 100, 100);
2004 SkIRect foreground_rect = SkIRect::MakeXYWH(50, 50, 100, 100);
2005 sk_sp<SkImageFilter> background = SkImageFilters::Crop(SkRect::Make(background_rect), nullptr);
2006 sk_sp<SkImageFilter> foreground = SkImageFilters::Crop(SkRect::Make(foreground_rect), nullptr);
2007
2008 SkIRect expectedBounds[kSkBlendModeCount];
2009 // Expect union of input rects by default.
2010 for (int i = 0; i < kSkBlendModeCount; ++i) {
2011 expectedBounds[i] = background_rect;
2012 expectedBounds[i].join(foreground_rect);
2013 }
2014
2015 SkIRect intersection = background_rect;
2016 intersection.intersect(foreground_rect);
2017 expectedBounds[static_cast<int>(SkBlendMode::kClear)] = SkIRect::MakeEmpty();
2018 expectedBounds[static_cast<int>(SkBlendMode::kSrc)] = foreground_rect;
2019 expectedBounds[static_cast<int>(SkBlendMode::kDst)] = background_rect;
2020 expectedBounds[static_cast<int>(SkBlendMode::kSrcIn)] = intersection;
2021 expectedBounds[static_cast<int>(SkBlendMode::kDstIn)] = intersection;
2022 expectedBounds[static_cast<int>(SkBlendMode::kSrcOut)] = foreground_rect;
2023 expectedBounds[static_cast<int>(SkBlendMode::kDstOut)] = background_rect;
2024 expectedBounds[static_cast<int>(SkBlendMode::kSrcATop)] = background_rect;
2025 expectedBounds[static_cast<int>(SkBlendMode::kDstATop)] = foreground_rect;
2026 expectedBounds[static_cast<int>(SkBlendMode::kModulate)] = intersection;
2027
2028 // Use a very large input bounds so that the crop rects stored in 'background' and 'foreground'
2029 // aren't restricted.
2031 for (int i = 0; i < kSkBlendModeCount; ++i) {
2033 background, foreground, nullptr));
2034 auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
2036 REPORTER_ASSERT(reporter, bounds == expectedBounds[i]);
2037 }
2038
2039 // Test empty intersection.
2040 sk_sp<SkImageFilter> background2 =
2041 SkImageFilters::Crop(SkRect::MakeXYWH(0, 0, 20, 20), nullptr);
2042 sk_sp<SkImageFilter> foreground2 =
2043 SkImageFilters::Crop(SkRect::MakeXYWH(40, 40, 50, 50), nullptr);
2045 SkBlendMode::kSrcIn, std::move(background2), std::move(foreground2), nullptr));
2046 auto bounds = xfermode->filterBounds(src, SkMatrix::I(),
2048 REPORTER_ASSERT(reporter, bounds.isEmpty());
2049}
static constexpr int kSkBlendModeCount
Definition: SkBlendMode.h:76
SkBlendMode
Definition: SkBlendMode.h:38
@ kSrcOut
r = s * (1-da)
@ kDstIn
r = d * sa
@ kModulate
r = s*d
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOut
r = d * (1-sa)
@ kSrcIn
r = s * da
@ kClear
r = 0
static sk_sp< SkImageFilter > Crop(const SkRect &rect, SkTileMode tileMode, sk_sp< SkImageFilter > input)
static SkIRect MakeILarge()
Definition: SkRectPriv.h:22
void join(const SkIRect &r)
Definition: SkRect.cpp:31
static constexpr SkIRect MakeEmpty()
Definition: SkRect.h:45

◆ DEF_TEST() [42/42]

DEF_TEST ( XfermodeImageFilterCroppedInput  ,
reporter   
)

Definition at line 1547 of file ImageFilterTest.cpp.

1547 {
1549 reporter);
1550}
const myers::Point & get(const myers::Segment &)

◆ draw_blurred_rect()

static void draw_blurred_rect ( SkCanvas canvas)
static

Definition at line 1107 of file ImageFilterTest.cpp.

1107 {
1108 SkPaint filterPaint;
1109 filterPaint.setColor(SK_ColorWHITE);
1110 filterPaint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(8), 0, nullptr));
1111 canvas->saveLayer(nullptr, &filterPaint);
1112 SkPaint whitePaint;
1113 whitePaint.setColor(SK_ColorWHITE);
1114 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint);
1115 canvas->restore();
1116}

◆ draw_picture_clipped()

static void draw_picture_clipped ( SkCanvas canvas,
const SkRect clipRect,
const SkPicture picture 
)
static

Definition at line 1118 of file ImageFilterTest.cpp.

1118 {
1119 canvas->save();
1120 canvas->clipRect(clipRect);
1121 canvas->drawPicture(picture);
1122 canvas->restore();
1123}
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void drawPicture(const SkPicture *picture)
Definition: SkCanvas.h:1961

◆ draw_saveLayer_picture()

static void draw_saveLayer_picture ( int  width,
int  height,
int  tileSize,
SkBBHFactory factory,
SkBitmap result 
)
static

Definition at line 860 of file ImageFilterTest.cpp.

861 {
862
864 matrix.setTranslate(SkIntToScalar(50), 0);
865
867 sk_sp<SkImageFilter> cfif(SkImageFilters::ColorFilter(std::move(cf), nullptr));
870 std::move(cfif)));
871
873 paint.setImageFilter(std::move(imageFilter));
874 SkPictureRecorder recorder;
876 SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
878 factory);
879 recordingCanvas->translate(-55, 0);
880 recordingCanvas->saveLayer(&bounds, &paint);
881 recordingCanvas->restore();
882 sk_sp<SkPicture> picture1(recorder.finishRecordingAsPicture());
883
884 result->allocN32Pixels(width, height);
885 SkCanvas canvas(*result);
886 canvas.clear(0);
887 canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize)));
888 canvas.drawPicture(picture1.get());
889}
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278

◆ make_blue()

static sk_sp< SkImageFilter > make_blue ( sk_sp< SkImageFilter input,
const SkIRect cropRect 
)
static

Definition at line 370 of file ImageFilterTest.cpp.

370 {
372 return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
373}

◆ make_blur()

static sk_sp< SkImageFilter > make_blur ( sk_sp< SkImageFilter input)
static

Definition at line 913 of file ImageFilterTest.cpp.

913 {
914 return SkImageFilters::Blur(SK_Scalar1, SK_Scalar1, std::move(input));
915}

◆ make_context() [1/2]

static skif::Context make_context ( const SkIRect out,
const SkSpecialImage src 
)
static

Definition at line 298 of file ImageFilterTest.cpp.

298 {
300 if (src->isGaneshBacked()) {
301 backend = skif::MakeGaneshBackend(sk_ref_sp(src->getContext()), kTestSurfaceOrigin,
302 src->props(), src->colorType());
303 } else {
304 backend = skif::MakeRasterBackend(src->props(), src->colorType());
305 }
306
307 return skif::Context{std::move(backend),
311 src->getColorSpace(),
312 /*stats=*/nullptr};
313}
const char * backend
sk_sp< Backend > MakeGaneshBackend(sk_sp< GrRecordingContext > context, GrSurfaceOrigin origin, const SkSurfaceProps &surfaceProps, SkColorType colorType)
sk_sp< Backend > MakeRasterBackend(const SkSurfaceProps &surfaceProps, SkColorType colorType)

◆ make_context() [2/2]

static skif::Context make_context ( int  outWidth,
int  outHeight,
const SkSpecialImage src 
)
static

Definition at line 314 of file ImageFilterTest.cpp.

314 {
315 return make_context(SkIRect::MakeWH(outWidth, outHeight), src);
316}
static skif::Context make_context(const SkIRect &out, const SkSpecialImage *src)

◆ make_drop_shadow()

static sk_sp< SkImageFilter > make_drop_shadow ( sk_sp< SkImageFilter input)
static

Definition at line 917 of file ImageFilterTest.cpp.

917 {
918 return SkImageFilters::DropShadow(100, 100, 10, 10, SK_ColorBLUE, std::move(input));
919}
static sk_sp< SkImageFilter > DropShadow(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})

◆ make_grayscale()

static sk_sp< SkImageFilter > make_grayscale ( sk_sp< SkImageFilter input,
const SkIRect cropRect 
)
static

Definition at line 358 of file ImageFilterTest.cpp.

359 {
360 float matrix[20];
361 memset(matrix, 0, 20 * sizeof(float));
362 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
363 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
364 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
365 matrix[18] = 1.0f;
367 return SkImageFilters::ColorFilter(std::move(filter), std::move(input), cropRect);
368}

◆ make_scale()

static sk_sp< SkImageFilter > make_scale ( float  amount,
sk_sp< SkImageFilter input 
)
static

Definition at line 348 of file ImageFilterTest.cpp.

348 {
349 float s = amount;
350 float matrix[20] = { s, 0, 0, 0, 0,
351 0, s, 0, 0, 0,
352 0, 0, s, 0, 0,
353 0, 0, 0, s, 0 };
355 return SkImageFilters::ColorFilter(std::move(filter), std::move(input));
356}
struct MyStruct s

◆ make_small_image()

static sk_sp< SkImage > make_small_image ( )
static

Definition at line 318 of file ImageFilterTest.cpp.

318 {
320 SkCanvas* canvas = surface->getCanvas();
321 canvas->clear(0x00000000);
322 SkPaint darkPaint;
323 darkPaint.setColor(0xFF804020);
324 SkPaint lightPaint;
325 lightPaint.setColor(0xFF244484);
326 const int kRectSize = kBitmapSize / 4;
327 static_assert(kBitmapSize % 4 == 0, "bitmap size not multiple of 4");
328
329 for (int y = 0; y < kBitmapSize; y += kRectSize) {
330 for (int x = 0; x < kBitmapSize; x += kRectSize) {
331 canvas->save();
333 canvas->drawRect(
334 SkRect::MakeXYWH(0, 0, kRectSize, kRectSize), darkPaint);
335 canvas->drawRect(
336 SkRect::MakeXYWH(kRectSize, 0, kRectSize, kRectSize), lightPaint);
337 canvas->drawRect(
338 SkRect::MakeXYWH(0, kRectSize, kRectSize, kRectSize), lightPaint);
339 canvas->drawRect(
340 SkRect::MakeXYWH(kRectSize, kRectSize, kRectSize, kRectSize), darkPaint);
341 canvas->restore();
342 }
343 }
344
345 return surface->makeImageSnapshot();
346}
void clear(SkColor color)
Definition: SkCanvas.h:1199

◆ special_image_to_bitmap()

static bool special_image_to_bitmap ( GrDirectContext dContext,
const SkSpecialImage src,
SkBitmap dst 
)
static

Definition at line 537 of file ImageFilterTest.cpp.

538 {
539 sk_sp<SkImage> img = src->asImage();
540 if (!img) {
541 return false;
542 }
543
544 if (!dst->tryAllocN32Pixels(src->width(), src->height())) {
545 return false;
546 }
547
548 return img->readPixels(dContext, dst->pixmap(), src->subset().fLeft, src->subset().fTop);
549}
bool readPixels(GrDirectContext *context, const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint cachingHint=kAllow_CachingHint) const
Definition: SkImage.cpp:42

◆ test_arithmetic_bounds()

static void test_arithmetic_bounds ( skiatest::Reporter reporter,
float  k1,
float  k2,
float  k3,
float  k4,
sk_sp< SkImageFilter background,
sk_sp< SkImageFilter foreground,
const SkIRect crop,
const SkIRect expected 
)
static

Definition at line 2106 of file ImageFilterTest.cpp.

2109 {
2111 k1, k2, k3, k4, false, std::move(background), std::move(foreground), crop));
2112 // Use a very large input bounds so that the crop rects stored in 'background' and 'foreground'
2113 // aren't restricted.
2115 SkIRect bounds = arithmetic->filterBounds(src, SkMatrix::I(),
2117 REPORTER_ASSERT(reporter, expected == bounds);
2118}
static sk_sp< SkImageFilter > Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground, const CropRect &cropRect={})

◆ test_arithmetic_combinations()

static void test_arithmetic_combinations ( skiatest::Reporter reporter,
float  v 
)
static

Definition at line 2120 of file ImageFilterTest.cpp.

2120 {
2121 SkIRect bgRect = SkIRect::MakeXYWH(0, 0, 100, 100);
2122 SkIRect fgRect = SkIRect::MakeXYWH(50, 50, 100, 100);
2123 sk_sp<SkImageFilter> background = SkImageFilters::Crop(SkRect::Make(bgRect), nullptr);
2124 sk_sp<SkImageFilter> foreground = SkImageFilters::Crop(SkRect::Make(fgRect), nullptr);
2125
2126 SkIRect unionRect = bgRect;
2127 unionRect.join(fgRect);
2128 SkIRect intersection = bgRect;
2129 intersection.intersect(fgRect);
2130
2131 // Test with crop. When k4 is non-zero, the result is expected to be cropRect
2132 // regardless of inputs because the filter affects the whole crop area. When there is no crop
2133 // rect, it should report an effectively infinite output.
2134 static const SkIRect kInf = SkRectPriv::MakeILarge();
2135 test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, nullptr,
2137 test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, nullptr, kInf);
2138 test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, nullptr, bgRect);
2139 test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, nullptr, kInf);
2140 test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, nullptr, fgRect);
2141 test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, nullptr, kInf);
2142 test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, nullptr, unionRect);
2143 test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, nullptr, kInf);
2144 test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, nullptr, intersection);
2145 test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, nullptr, kInf);
2146 test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, nullptr, bgRect);
2147 test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, nullptr, kInf);
2148 test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, nullptr, fgRect);
2149 test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, nullptr, kInf);
2150 test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, nullptr, unionRect);
2151 test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, nullptr, kInf);
2152
2153 SkIRect cropRect = SkIRect::MakeXYWH(-111, -222, 333, 444);
2154 test_arithmetic_bounds(reporter, 0, 0, 0, 0, background, foreground, &cropRect,
2156 test_arithmetic_bounds(reporter, 0, 0, 0, v, background, foreground, &cropRect, cropRect);
2157 test_arithmetic_bounds(reporter, 0, 0, v, 0, background, foreground, &cropRect, bgRect);
2158 test_arithmetic_bounds(reporter, 0, 0, v, v, background, foreground, &cropRect, cropRect);
2159 test_arithmetic_bounds(reporter, 0, v, 0, 0, background, foreground, &cropRect, fgRect);
2160 test_arithmetic_bounds(reporter, 0, v, 0, v, background, foreground, &cropRect, cropRect);
2161 test_arithmetic_bounds(reporter, 0, v, v, 0, background, foreground, &cropRect, unionRect);
2162 test_arithmetic_bounds(reporter, 0, v, v, v, background, foreground, &cropRect, cropRect);
2163 test_arithmetic_bounds(reporter, v, 0, 0, 0, background, foreground, &cropRect, intersection);
2164 test_arithmetic_bounds(reporter, v, 0, 0, v, background, foreground, &cropRect, cropRect);
2165 test_arithmetic_bounds(reporter, v, 0, v, 0, background, foreground, &cropRect, bgRect);
2166 test_arithmetic_bounds(reporter, v, 0, v, v, background, foreground, &cropRect, cropRect);
2167 test_arithmetic_bounds(reporter, v, v, 0, 0, background, foreground, &cropRect, fgRect);
2168 test_arithmetic_bounds(reporter, v, v, 0, v, background, foreground, &cropRect, cropRect);
2169 test_arithmetic_bounds(reporter, v, v, v, 0, background, foreground, &cropRect, unionRect);
2170 test_arithmetic_bounds(reporter, v, v, v, v, background, foreground, &cropRect, cropRect);
2171}
static void test_arithmetic_bounds(skiatest::Reporter *reporter, float k1, float k2, float k3, float k4, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground, const SkIRect *crop, const SkIRect &expected)

◆ test_big_kernel()

static void test_big_kernel ( skiatest::Reporter reporter,
GrRecordingContext rContext 
)
static

Definition at line 1225 of file ImageFilterTest.cpp.

1225 {
1226 // Check that a kernel that is too big for the GPU still works
1227 SkScalar identityKernel[49] = {
1228 0, 0, 0, 0, 0, 0, 0,
1229 0, 0, 0, 0, 0, 0, 0,
1230 0, 0, 0, 0, 0, 0, 0,
1231 0, 0, 0, 1, 0, 0, 0,
1232 0, 0, 0, 0, 0, 0, 0,
1233 0, 0, 0, 0, 0, 0, 0,
1234 0, 0, 0, 0, 0, 0, 0
1235 };
1236 SkISize kernelSize = SkISize::Make(7, 7);
1237 SkScalar gain = SK_Scalar1, bias = 0;
1238 SkIPoint kernelOffset = SkIPoint::Make(0, 0);
1239
1241 kernelSize, identityKernel, gain, bias, kernelOffset,
1242 SkTileMode::kClamp, true, nullptr));
1243
1245 SkASSERT(srcImg);
1246
1248 skif::Context ctx = make_context(100, 100, srcImg.get());
1249 sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx).imageAndOffset(ctx, &offset));
1250 REPORTER_ASSERT(reporter, resultImg);
1251 REPORTER_ASSERT(reporter, SkToBool(rContext) == resultImg->isGaneshBacked());
1252 REPORTER_ASSERT(reporter, resultImg->width() == 100 && resultImg->height() == 100);
1253 REPORTER_ASSERT(reporter, offset.fX == 0 && offset.fY == 0);
1254}
static sk_sp< SkSpecialImage > create_empty_special_image(GrRecordingContext *rContext, int widthHeight, SkColor4f color=SkColors::kTransparent)
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35

◆ test_clipped_picture_imagefilter()

static void test_clipped_picture_imagefilter ( skiatest::Reporter reporter,
GrRecordingContext rContext 
)
static

Definition at line 1304 of file ImageFilterTest.cpp.

1305 {
1307
1308 {
1309 SkRTreeFactory factory;
1310 SkPictureRecorder recorder;
1311 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory);
1312
1313 // Create an SkPicture which simply draws a green 1x1 rectangle.
1314 SkPaint greenPaint;
1315 greenPaint.setColor(SK_ColorGREEN);
1316 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint);
1317 picture = recorder.finishRecordingAsPicture();
1318 }
1319
1321
1323
1325 skif::Context ctx = make_context(SkIRect::MakeXYWH(1,1,1,1), srcImg.get());
1326
1327 sk_sp<SkSpecialImage> resultImage(
1328 as_IFB(imageFilter)->filterImage(ctx).imageAndOffset(ctx, &offset));
1329 REPORTER_ASSERT(reporter, !resultImage);
1330}

◆ test_composed_imagefilter_bounds()

static void test_composed_imagefilter_bounds ( skiatest::Reporter reporter,
GrDirectContext dContext 
)
static

Definition at line 1582 of file ImageFilterTest.cpp.

1583 {
1584 // The bounds passed to the inner filter must be filtered by the outer
1585 // filter, so that the inner filter produces the pixels that the outer
1586 // filter requires as input. This matters if the outer filter moves pixels.
1587 // Here, accounting for the outer offset is necessary so that the green
1588 // pixels of the picture are not clipped.
1589
1590 SkPictureRecorder recorder;
1591 SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeIWH(200, 100));
1592 recordingCanvas->clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
1593 recordingCanvas->clear(SK_ColorGREEN);
1596 SkIRect cropRect = SkIRect::MakeWH(100, 100);
1597 sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(-100, 0, nullptr, &cropRect));
1598 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(offsetFilter),
1599 std::move(pictureFilter)));
1600
1601 sk_sp<SkSpecialImage> sourceImage(create_empty_special_image(dContext, 100));
1602 skif::Context ctx = make_context(100, 100, sourceImage.get());
1603
1606 as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(ctx, &offset));
1607 REPORTER_ASSERT(reporter, offset.isZero());
1609 REPORTER_ASSERT(reporter, result->subset().size() == SkISize::Make(100, 100));
1610
1611 SkBitmap resultBM;
1612 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
1613 REPORTER_ASSERT(reporter, resultBM.getColor(50, 50) == SK_ColorGREEN);
1614}
static bool special_image_to_bitmap(GrDirectContext *dContext, const SkSpecialImage *src, SkBitmap *dst)
SkColor getColor(int x, int y) const
Definition: SkBitmap.h:874

◆ test_composed_imagefilter_offset()

static void test_composed_imagefilter_offset ( skiatest::Reporter reporter,
GrRecordingContext rContext 
)
static

Definition at line 1552 of file ImageFilterTest.cpp.

1553 {
1555
1556 SkIRect cropRect = SkIRect::MakeXYWH(1, 0, 20, 20);
1557 sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
1559 nullptr, &cropRect));
1560 sk_sp<SkImageFilter> composedFilter(SkImageFilters::Compose(std::move(blurFilter),
1561 std::move(offsetFilter)));
1563 skif::Context ctx = make_context(100, 100, srcImg.get());
1564
1565 sk_sp<SkSpecialImage> resultImg(
1566 as_IFB(composedFilter)->filterImage(ctx).imageAndOffset(ctx, &offset));
1567 REPORTER_ASSERT(reporter, resultImg);
1568 REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
1569}

◆ test_cropRects()

static void test_cropRects ( skiatest::Reporter reporter,
GrRecordingContext rContext 
)
static

Definition at line 513 of file ImageFilterTest.cpp.

513 {
514 // Check that all filters offset to their absolute crop rect,
515 // unaffected by the input crop rect.
516 // Tests pass by not asserting.
518 SkASSERT(srcImg);
519
520 SkIRect inputCropRect = SkIRect::MakeXYWH(8, 13, 80, 80);
521 SkIRect cropRect = SkIRect::MakeXYWH(20, 30, 60, 60);
522 sk_sp<SkImageFilter> input(make_grayscale(nullptr, &inputCropRect));
523
524 FilterList filters(input, &cropRect);
525
526 for (int i = 0; i < filters.count(); ++i) {
527 SkImageFilter* filter = filters.getFilter(i);
529 skif::Context ctx = make_context(100, 100, srcImg.get());
530 sk_sp<SkSpecialImage> resultImg(as_IFB(filter)->filterImage(ctx)
531 .imageAndOffset(ctx, &offset));
532 REPORTER_ASSERT(reporter, resultImg, "%s", filters.getName(i));
533 REPORTER_ASSERT(reporter, offset.fX == 20 && offset.fY == 30, "%s", filters.getName(i));
534 }
535}

◆ test_fail_affects_transparent_black()

static void test_fail_affects_transparent_black ( skiatest::Reporter reporter,
GrDirectContext dContext 
)
static

Definition at line 751 of file ImageFilterTest.cpp.

752 {
755 skif::Context ctx = make_context(1, 1, source.get());
756
758 SkASSERT(as_CFB(green)->affectsTransparentBlack());
759 sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(std::move(green),
760 std::move(failFilter)));
762 sk_sp<SkSpecialImage> result(as_IFB(greenFilter)->filterImage(ctx)
763 .imageAndOffset(ctx, &offset));
764 REPORTER_ASSERT(reporter, nullptr != result.get());
765 if (result) {
766 SkBitmap resultBM;
767 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
768 REPORTER_ASSERT(reporter, *resultBM.getAddr32(0, 0) == SK_ColorGREEN);
769 }
770}
static sk_sp< SkImageFilter > Empty()
SkBitmap source
Definition: examples.cpp:28

◆ test_huge_blur()

static void test_huge_blur ( SkCanvas canvas,
skiatest::Reporter reporter 
)
static

Definition at line 1394 of file ImageFilterTest.cpp.

1394 {
1396 bitmap.allocN32Pixels(100, 100);
1397 bitmap.eraseARGB(0, 0, 0, 0);
1398
1399 // Check that a blur with a very large radius does not crash or assert.
1400 SkPaint paint;
1401 paint.setImageFilter(SkImageFilters::Blur(SkIntToScalar(1<<30), SkIntToScalar(1<<30), nullptr));
1402 canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint);
1403}
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528

◆ test_imagefilter_merge_result_size()

static void test_imagefilter_merge_result_size ( skiatest::Reporter reporter,
GrRecordingContext rContext 
)
static

Definition at line 1076 of file ImageFilterTest.cpp.

1077 {
1078 SkBitmap greenBM;
1079 greenBM.allocN32Pixels(20, 20);
1080 greenBM.eraseColor(SK_ColorGREEN);
1081 sk_sp<SkImage> greenImage(greenBM.asImage());
1082 sk_sp<SkImageFilter> source(SkImageFilters::Image(std::move(greenImage), {}));
1084
1086
1087 skif::Context ctx = make_context(100, 100, srcImg.get());
1089
1090 sk_sp<SkSpecialImage> resultImg(as_IFB(merge)->filterImage(ctx).imageAndOffset(ctx, &offset));
1091 REPORTER_ASSERT(reporter, resultImg);
1092
1093 REPORTER_ASSERT(reporter, resultImg->width() == 20 && resultImg->height() == 20);
1094}
static void merge(const uint8_t *SK_RESTRICT row, int rowN, const SkAlpha *SK_RESTRICT srcAA, const int16_t *SK_RESTRICT srcRuns, SkAlpha *SK_RESTRICT dstAA, int16_t *SK_RESTRICT dstRuns, int width)
Definition: SkAAClip.cpp:1691
sk_sp< SkImage > asImage() const
Definition: SkBitmap.cpp:645

◆ test_large_blur_input()

static void test_large_blur_input ( skiatest::Reporter reporter,
SkCanvas canvas 
)
static

Definition at line 1726 of file ImageFilterTest.cpp.

1726 {
1727 SkBitmap largeBmp;
1728 int largeW = 5000;
1729 int largeH = 5000;
1730 // If we're GPU-backed make the bitmap too large to be converted into a texture.
1731 if (auto ctx = canvas->recordingContext()) {
1732 largeW = ctx->priv().caps()->maxTextureSize() + 1;
1733 }
1734
1735 largeBmp.allocN32Pixels(largeW, largeH);
1736 largeBmp.eraseColor(0);
1737 if (!largeBmp.getPixels()) {
1738 ERRORF(reporter, "Failed to allocate large bmp.");
1739 return;
1740 }
1741
1742 sk_sp<SkImage> largeImage(largeBmp.asImage());
1743 if (!largeImage) {
1744 ERRORF(reporter, "Failed to create large image.");
1745 return;
1746 }
1747
1748 sk_sp<SkImageFilter> largeSource(SkImageFilters::Image(std::move(largeImage), {}));
1749 if (!largeSource) {
1750 ERRORF(reporter, "Failed to create large SkImageSource.");
1751 return;
1752 }
1753
1754 sk_sp<SkImageFilter> blur(SkImageFilters::Blur(10.f, 10.f, std::move(largeSource)));
1755 if (!blur) {
1756 ERRORF(reporter, "Failed to create SkBlurImageFilter.");
1757 return;
1758 }
1759
1760 SkPaint paint;
1761 paint.setImageFilter(std::move(blur));
1762
1763 // This should not crash (http://crbug.com/570479).
1764 canvas->drawRect(SkRect::MakeIWH(largeW, largeH), paint);
1765}
void * getPixels() const
Definition: SkBitmap.h:283
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637

◆ test_make_with_filter()

static void test_make_with_filter ( skiatest::Reporter reporter,
const std::function< sk_sp< SkSurface >(int width, int height)> &  createSurface,
const std::function< sk_sp< SkImage >(sk_sp< SkImage > src, const SkImageFilter *filter, const SkIRect &subset, const SkIRect &clipBounds, SkIRect *outSubset, SkIPoint *offset)> &  makeWithFilter 
)
static

Definition at line 1772 of file ImageFilterTest.cpp.

1780 {
1781 sk_sp<SkSurface> surface(createSurface(192, 128));
1782 surface->getCanvas()->clear(SK_ColorRED);
1783 SkPaint bluePaint;
1784 bluePaint.setColor(SK_ColorBLUE);
1785 SkIRect subset = SkIRect::MakeXYWH(25, 20, 50, 50);
1786 surface->getCanvas()->drawRect(SkRect::Make(subset), bluePaint);
1787 sk_sp<SkImage> sourceImage = surface->makeImageSnapshot();
1788
1789 sk_sp<SkImageFilter> filter = make_grayscale(nullptr, nullptr);
1790 SkIRect clipBounds = SkIRect::MakeXYWH(30, 35, 100, 100);
1791 SkIRect outSubset;
1794
1795 result = makeWithFilter(sourceImage, nullptr, subset, clipBounds, &outSubset, &offset);
1796 REPORTER_ASSERT(reporter, !result); // filter is required
1797
1798 result = makeWithFilter(sourceImage, filter.get(), subset, clipBounds, nullptr, &offset);
1799 REPORTER_ASSERT(reporter, !result); // outSubset is required
1800
1801 result = makeWithFilter(sourceImage, filter.get(), subset, clipBounds, &outSubset, nullptr);
1802 REPORTER_ASSERT(reporter, !result); // offset is required
1803
1804 SkIRect bigSubset = SkIRect::MakeXYWH(-10000, -10000, 20000, 20000);
1805 result = makeWithFilter(sourceImage, filter.get(), bigSubset, clipBounds, &outSubset, &offset);
1806 REPORTER_ASSERT(reporter, !result); // subset needs to be w/in source's bounds
1807
1809 result = makeWithFilter(sourceImage, filter.get(), kEmpty, clipBounds, &outSubset, &offset);
1810 REPORTER_ASSERT(reporter, !result); // subset can't be empty
1811
1812 result = makeWithFilter(sourceImage, filter.get(), subset, kEmpty, &outSubset, &offset);
1813 REPORTER_ASSERT(reporter, !result); // clipBounds can't be empty
1814
1815 const SkIRect kLeftField = SkIRect::MakeXYWH(-1000, 0, 100, 100);
1816 result = makeWithFilter(sourceImage, filter.get(), subset, kLeftField, &outSubset, &offset);
1818
1819 result = makeWithFilter(sourceImage, filter.get(), subset, clipBounds, &outSubset, &offset);
1820
1822 REPORTER_ASSERT(reporter, result->bounds().contains(outSubset));
1823 SkIRect destRect = SkIRect::MakeXYWH(offset.x(), offset.y(),
1824 outSubset.width(), outSubset.height());
1825 REPORTER_ASSERT(reporter, clipBounds.contains(destRect));
1826
1827 // In GPU-mode, this case creates a special image with a backing size that differs from
1828 // the content size
1829 {
1830 clipBounds.setXYWH(0, 0, 170, 100);
1831 subset.setXYWH(0, 0, 160, 90);
1832
1834 result = makeWithFilter(sourceImage, filter.get(), subset, clipBounds, &outSubset, &offset);
1836
1837 // In Ganesh, we want the result image (and all intermediate steps) to have used the same
1838 // origin as the original surface.
1839 if (result && as_IB(result)->isGaneshBacked()) {
1840 SkImage_GaneshBase* base = static_cast<SkImage_GaneshBase*>(result.get());
1841 REPORTER_ASSERT(reporter, base->origin() == kTestSurfaceOrigin);
1842 }
1843 }
1844}
T * get() const
Definition: SkRefCnt.h:303
constexpr int32_t height() const
Definition: SkRect.h:165
constexpr int32_t width() const
Definition: SkRect.h:158
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
Definition: SkRect.h:268
bool contains(int32_t x, int32_t y) const
Definition: SkRect.h:463

◆ test_morphology_radius_with_mirror_ctm()

static void test_morphology_radius_with_mirror_ctm ( skiatest::Reporter reporter,
GrDirectContext dContext 
)
static

Definition at line 617 of file ImageFilterTest.cpp.

618 {
619 // Check that SkMorphologyImageFilter maps the radius correctly when the
620 // CTM contains a mirroring transform.
621 static const int kWidth = 32, kHeight = 32;
622 static const int kRadius = 8;
623
625
627 bitmap.allocN32Pixels(kWidth, kHeight);
628 SkCanvas canvas(bitmap);
629 canvas.clear(SK_ColorTRANSPARENT);
631 paint.setColor(SK_ColorWHITE);
632 canvas.drawRect(SkRect::MakeXYWH(kWidth / 4, kHeight / 4, kWidth / 2, kHeight / 2),
633 paint);
634 sk_sp<SkImage> image = bitmap.asImage();
636 if (dContext) {
639 } else {
641 }
642
644 skif::Context ctx = make_context(32, 32, imgSrc.get());
645
646 sk_sp<SkSpecialImage> normalResult(
647 as_IFB(filter)->filterImage(ctx).imageAndOffset(ctx, &offset));
648 REPORTER_ASSERT(reporter, normalResult);
649
650 SkMatrix mirrorX;
651 mirrorX.setTranslate(0, SkIntToScalar(32));
652 mirrorX.preScale(SK_Scalar1, -SK_Scalar1);
653 skif::Context mirrorXCTX = ctx.withNewMapping(skif::Mapping(mirrorX));
654
655 sk_sp<SkSpecialImage> mirrorXResult(
656 as_IFB(filter)->filterImage(mirrorXCTX).imageAndOffset(ctx, &offset));
657 REPORTER_ASSERT(reporter, mirrorXResult);
658
659 SkMatrix mirrorY;
660 mirrorY.setTranslate(SkIntToScalar(32), 0);
661 mirrorY.preScale(-SK_Scalar1, SK_Scalar1);
662 skif::Context mirrorYCTX = ctx.withNewMapping(skif::Mapping(mirrorY));
663
664 sk_sp<SkSpecialImage> mirrorYResult(
665 as_IFB(filter)->filterImage(mirrorYCTX).imageAndOffset(ctx, &offset));
666 REPORTER_ASSERT(reporter, mirrorYResult);
667
668 SkBitmap normalResultBM, mirrorXResultBM, mirrorYResultBM;
669
670 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, normalResult.get(),
671 &normalResultBM));
672 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, mirrorXResult.get(),
673 &mirrorXResultBM));
674 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, mirrorYResult.get(),
675 &mirrorYResultBM));
676
677 for (int y = 0; y < kHeight; y++) {
678 int diffs = memcmp(normalResultBM.getAddr32(0, y),
679 mirrorXResultBM.getAddr32(0, y),
680 normalResultBM.rowBytes());
681 REPORTER_ASSERT(reporter, !diffs);
682 if (diffs) {
683 break;
684 }
685 diffs = memcmp(normalResultBM.getAddr32(0, y),
686 mirrorYResultBM.getAddr32(0, y),
687 normalResultBM.rowBytes());
688 REPORTER_ASSERT(reporter, !diffs);
689 if (diffs) {
690 break;
691 }
692 }
693}
SkMatrix & setTranslate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.cpp:254
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:315
Context withNewMapping(const Mapping &mapping) const
sk_sp< SkSpecialImage > MakeFromRaster(const SkIRect &subset, const SkBitmap &bm, const SkSurfaceProps &props)
sk_sp< SkSpecialImage > MakeFromTextureImage(GrRecordingContext *rContext, const SkIRect &subset, sk_sp< SkImage > image, const SkSurfaceProps &props)
constexpr int kRadius
constexpr size_t kHeight
constexpr size_t kWidth

◆ test_negative_blur_sigma()

static void test_negative_blur_sigma ( skiatest::Reporter reporter,
GrDirectContext dContext 
)
static

Definition at line 551 of file ImageFilterTest.cpp.

552 {
553 // Check that SkBlurImageFilter will reject a negative sigma on creation, but properly uses the
554 // absolute value of the mapped sigma after CTM application.
555 static const int kWidth = 32, kHeight = 32;
556 static const SkScalar kBlurSigma = SkIntToScalar(5);
557
558 sk_sp<SkImageFilter> positiveFilter(SkImageFilters::Blur(kBlurSigma, kBlurSigma, nullptr));
559 sk_sp<SkImageFilter> negativeFilter(SkImageFilters::Blur(-kBlurSigma, kBlurSigma, nullptr));
560 REPORTER_ASSERT(reporter, !negativeFilter);
561
562 sk_sp<SkImage> gradient = make_gradient_circle(kWidth, kHeight).asImage();
564 if (dContext) {
566 dContext, SkIRect::MakeWH(kWidth, kHeight), gradient, SkSurfaceProps());
567 } else {
569 }
570
572 skif::Context ctx = make_context(32, 32, imgSrc.get());
573
574 sk_sp<SkSpecialImage> positiveResult(
575 as_IFB(positiveFilter)->filterImage(ctx).imageAndOffset(ctx, &offset));
576 REPORTER_ASSERT(reporter, positiveResult);
577
578 SkMatrix negativeScale;
579 negativeScale.setScale(-SK_Scalar1, SK_Scalar1);
580 skif::Context negativeCTX = ctx.withNewMapping(skif::Mapping(negativeScale));
581
582 sk_sp<SkSpecialImage> negativeResult(
583 as_IFB(positiveFilter)->filterImage(negativeCTX).imageAndOffset(ctx, &offset));
584 REPORTER_ASSERT(reporter, negativeResult);
585
586
587 SkBitmap positiveResultBM;
588 SkBitmap negativeResultBM;
589
590 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, positiveResult.get(),
591 &positiveResultBM));
592 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, negativeResult.get(),
593 &negativeResultBM));
594
595 for (int y = 0; y < kHeight; y++) {
596 int diffs = memcmp(positiveResultBM.getAddr32(0, y),
597 negativeResultBM.getAddr32(0, y),
598 positiveResultBM.rowBytes());
599 REPORTER_ASSERT(reporter, !diffs);
600 if (diffs) {
601 break;
602 }
603 }
604}
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:296

◆ test_xfermode_cropped_input()

static void test_xfermode_cropped_input ( SkSurface surf,
skiatest::Reporter reporter 
)
static

Definition at line 1446 of file ImageFilterTest.cpp.

1446 {
1447 auto canvas = surf->getCanvas();
1448 canvas->clear(SK_ColorRED);
1449
1451 bitmap.allocN32Pixels(1, 1);
1452 bitmap.eraseARGB(255, 255, 255, 255);
1453
1455 sk_sp<SkImageFilter> greenFilter(SkImageFilters::ColorFilter(green, nullptr));
1456 SkIRect cropRect = SkIRect::MakeEmpty();
1457 sk_sp<SkImageFilter> croppedOut(SkImageFilters::ColorFilter(green, nullptr, &cropRect));
1458
1459 // Check that an blend image filter whose input has been cropped out still draws the other
1460 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning.
1463 mode, greenFilter, croppedOut, nullptr));
1465 mode, croppedOut, greenFilter, nullptr));
1467 mode, croppedOut, croppedOut, nullptr));
1468
1469 SkPaint paint;
1470 paint.setImageFilter(std::move(xfermodeNoFg));
1471 canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); // drawSprite
1472
1473 // xfermodeNoFg is a src-over blend between a green image and a transparent black image,
1474 // so should just be green.
1475 uint32_t pixel;
1477 surf->readPixels(info, &pixel, 4, 0, 0);
1479
1480 // xfermodeNoBg is the reverse of the above, but because it's src-over the final blend
1481 // between transparent black and green is still green.
1482 canvas->clear(SK_ColorRED); // should be overwritten
1483 paint.setImageFilter(std::move(xfermodeNoBg));
1484 canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); // drawSprite
1485 surf->readPixels(info, &pixel, 4, 0, 0);
1487
1488 // xfermodeNoFgNoBg is a src-over blend of two empty images, so should produce no change
1489 // to the image.
1490 canvas->clear(SK_ColorRED); // should not be overwritten
1491 paint.setImageFilter(std::move(xfermodeNoFgNoBg));
1492 canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); // drawSprite
1493 surf->readPixels(info, &pixel, 4, 0, 0);
1495}
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
bool readPixels(const SkPixmap &dst, int srcX, int srcY)
Definition: SkSurface.cpp:125

◆ test_zero_blur_sigma()

static void test_zero_blur_sigma ( skiatest::Reporter reporter,
GrDirectContext dContext 
)
static

Definition at line 706 of file ImageFilterTest.cpp.

706 {
707 // Check that SkBlurImageFilter with a zero sigma and a non-zero srcOffset works correctly.
708 SkIRect cropRect = SkIRect::MakeXYWH(5, 0, 5, 10);
709 sk_sp<SkImageFilter> input(SkImageFilters::Offset(0, 0, nullptr, &cropRect));
710 sk_sp<SkImageFilter> filter(SkImageFilters::Blur(0, 0, std::move(input), &cropRect));
711
713
715 skif::Context ctx = make_context(32, 32, image.get());
716
717
718 sk_sp<SkSpecialImage> result(as_IFB(filter)->filterImage(ctx).imageAndOffset(ctx, &offset));
719 REPORTER_ASSERT(reporter, offset.fX == 5 && offset.fY == 0);
721 REPORTER_ASSERT(reporter, result->width() == 5 && result->height() == 10);
722
723 SkBitmap resultBM;
724
725 REPORTER_ASSERT(reporter, special_image_to_bitmap(dContext, result.get(), &resultBM));
726
727 for (int y = 0; y < resultBM.height(); y++) {
728 for (int x = 0; x < resultBM.width(); x++) {
729 bool diff = *resultBM.getAddr32(x, y) != SK_ColorGREEN;
731 if (diff) {
732 break;
733 }
734 }
735 }
736}
int width() const
Definition: SkBitmap.h:149
int height() const
Definition: SkBitmap.h:158
constexpr SkColor4f kGreen
Definition: SkColor.h:441

Variable Documentation

◆ kBitmapSize

const int kBitmapSize = 4
static

Definition at line 93 of file ImageFilterTest.cpp.