| Flutter Impeller |

Classes | Typedefs | Functions | Variables
impeller::testing Namespace Reference

## Classes
struct | Foo
struct | RWFoo
struct | CVTest
struct | BlendModeSelection
struct | MaskBlurTestConfig
struct | TextRenderOptions
class | BlendFilterContentsTest
class | GaussianBlurFilterContentsTest
class | MatrixFilterContentsTest
class | MockIdleWaiter
class | FailingAllocator
class | FlushTestDeviceBuffer
class | FlushTestAllocator
class | FlushTestContentContext
class | TestAllocator
struct | ColorBlendTestData
class | GoldenDigest
| Manages a global variable for tracking instances of golden images. More...
class | GoldenTests
class | MetalScreenshot
| A screenshot that was produced from `MetalScreenshotter`. More...
class | MetalScreenshotter
class | Screenshot
class | Screenshotter
class | VulkanScreenshotter
class | WorkingDirectory
class | TestReactorGLES
class | MockWorker
struct | DiscardFrameBufferParams
class | RenderPassGLESWithDiscardFrameBufferExtTest
class | RendererDartTest
class | CompareFunctionUIData
class | MockPathVertexWriter
class | MockSegmentReceiver

## Typedefs
using | AiksTest = AiksPlayground
using | DisplayListTest = DlPlayground
using | HostBufferTest = EntityPlayground
using | TextContentsTest = PlaygroundTest
using | EntityTest = EntityPlayground
using | EntityPassTargetTest = EntityPlayground
using | RenderTargetCacheTest = EntityPlayground
using | SaveLayerUtilsTest = ::testing::Test
using | AllocatorMTLTest = PlaygroundTest
using | ContextMTLTest = PlaygroundTest
using | SwapchainTransientsMTLTest = PlaygroundTest
using | DriverInfoVKTest = PlaygroundTest
using | PipelineCacheDataVKPlaygroundTest = PlaygroundTest
using | RendererTest = PlaygroundTest
using | BlitPassTest = AiksTest
using | ComputeTest = ComputePlaygroundTest
using | DeviceBufferTest = Playground
using | RuntimeStageTest = RuntimeStagePlayground
using | TessellatorPlaygroundTest = PlaygroundTest
using | TypographerTest = PlaygroundTest

## Functions
| TEST (AllocationSizeTest, CanCreateTypedAllocations)
| TEST (AllocationSizeTest, CanCreateTypedAllocationsWithLiterals)
| TEST (AllocationSizeTest, CanConvert)
| TEST (AllocationSizeTest, ConversionsAreNonTruncating)
| TEST (AllocationSizeTest, CanGetFloatValues)
| TEST (AllocationSizeTest, RelationalOperatorsAreFunctional)
| TEST (AllocationSizeTest, CanCast)
| TEST (AllocationSizeTest, CanPerformSimpleArithmetic)
| TEST (AllocationSizeTest, CanConstructWithArith)
| TEST (ThreadTest, CanCreateMutex)
| TEST (ThreadTest, CanCreateMutexLock)
| TEST (ThreadTest, CanCreateRWMutex)
| TEST (ThreadTest, CanCreateRWMutexLock)
| TEST (ConditionVariableTest, WaitUntil)
| TEST (ConditionVariableTest, WaitFor)
| TEST (ConditionVariableTest, WaitForever)
| TEST (ConditionVariableTest, TestsCriticalSectionAfterWaitForUntil)
| TEST (ConditionVariableTest, TestsCriticalSectionAfterWait)
| TEST (BaseTest, NoExceptionPromiseValue)
| TEST (BaseTest, NoExceptionPromiseEmpty)
| TEST (BaseTest, CanUseTypedMasks)
| TEST (AllocatorTest, TextureDescriptorCompatibility)
| TEST (AllocatorTest, RangeTest)
| TEST (BufferViewTest, Empty)
| TEST (BufferViewTest, TakeRaw)
| TEST_P (AiksTest, DrawAtlasNoColor)
| TEST_P (AiksTest, DrawAtlasWithColorAdvanced)
| TEST_P (AiksTest, DrawAtlasWithColorSimple)
| TEST_P (AiksTest, DrawAtlasWithOpacity)
| TEST_P (AiksTest, DrawAtlasNoColorFullSize)
| TEST_P (AiksTest, DrawAtlasAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasWithColorAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasPlusWideGamut)
| TEST_P (AiksTest, DlAtlasGeometryNoBlendRenamed)
| TEST_P (AiksTest, DlAtlasGeometryBlend)
| TEST_P (AiksTest, DlAtlasGeometryColorButNoBlend)
| TEST_P (AiksTest, DlAtlasGeometrySkip)
| TEST_P (AiksTest, DrawImageRectWithBlendColorFilter)
| TEST_P (AiksTest, DrawImageRectWithMatrixColorFilter)
| TEST_P (AiksTest, DrawAtlasWithColorBurn)
| TEST_P (AiksTest, CanRenderColoredRect)
| TEST_P (AiksTest, CanRenderWideStrokedRectWithoutOverlap)
| TEST_P (AiksTest, CanRenderWideStrokedRectPathWithoutOverlap)
| TEST_P (AiksTest, CanRenderImage)
| TEST_P (AiksTest, CanRenderInvertedImageWithColorFilter)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColors)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint)
| TEST_P (AiksTest, CanRenderTiledTextureClamp)
| TEST_P (AiksTest, CanRenderTiledTextureRepeat)
| TEST_P (AiksTest, CanRenderTiledTextureMirror)
| TEST_P (AiksTest, CanRenderTiledTextureDecal)
| TEST_P (AiksTest, CanRenderTiledTextureClampWithTranslate)
| TEST_P (AiksTest, CanRenderImageRect)
| TEST_P (AiksTest, DrawImageRectSrcOutsideBounds)
| TEST_P (AiksTest, CanRenderSimpleClips)
| TEST_P (AiksTest, CanSaveLayerStandalone)
| TEST_P (AiksTest, CanRenderDifferentShapesWithSameColorSource)
| TEST_P (AiksTest, CanRenderRoundedRectWithNonUniformRadii)
| TEST_P (AiksTest, CanDrawPaint)
| TEST_P (AiksTest, CanDrawPaintMultipleTimes)
| TEST_P (AiksTest, StrokedRectsRenderCorrectly)
| TEST_P (AiksTest, FilledCirclesRenderCorrectly)
| TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
| TEST_P (AiksTest, ZoomedStrokedPathRendersCorrectly)
| TEST_P (AiksTest, StrokedPathWithLargeStrokeWidthRendersCorrectly)
| TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
| TEST_P (AiksTest, FilledArcsRenderCorrectly)
| TEST_P (AiksTest, TranslucentFilledArcsRenderCorrectly)
| TEST_P (AiksTest, FilledArcsRenderCorrectlyWithCenter)
| TEST_P (AiksTest, NonSquareFilledArcsRenderCorrectly)
| TEST_P (AiksTest, NonSquareFilledArcsRenderCorrectlyWithCenter)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithButtEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithSquareEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithTranslucencyAndSquareEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithRoundEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithTranslucencyAndRoundEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds)
| TEST_P (AiksTest, StrokedArcsCoverFullArcWithButtEnds)
| TEST_P (AiksTest, FilledRoundRectsRenderCorrectly)
| TEST_P (AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly)
| TEST_P (AiksTest, CanRenderClippedBackdropFilter)
| TEST_P (AiksTest, CanDrawPerspectiveTransformWithClips)
| TEST_P (AiksTest, ImageColorSourceEffectTransform)
| TEST_P (AiksTest, SubpassWithClearColorOptimization)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
| TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
| TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
| TEST_P (AiksTest, FormatWideGamut)
| TEST_P (AiksTest, FormatSRGB)
| TEST_P (AiksTest, CoordinateConversionsAreCorrect)
| TEST_P (AiksTest, CanPerformFullScreenMSAA)
| TEST_P (AiksTest, CanPerformSkew)
| TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
| TEST_P (AiksTest, FilledRoundRectPathsRenderCorrectly)
| TEST_P (AiksTest, CoverageOriginShouldBeAccountedForInSubpasses)
| TEST_P (AiksTest, SaveLayerDrawsBehindSubsequentEntities)
| TEST_P (AiksTest, SiblingSaveLayerBoundsAreRespected)
| TEST_P (AiksTest, CanRenderClippedLayers)
| TEST_P (AiksTest, SaveLayerFiltersScaleWithTransform)
| TEST_P (AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly)
| TEST_P (AiksTest, PipelineBlendSingleParameter)
| TEST_P (AiksTest, MassiveScalingMatrixImageFilter)
| TEST_P (AiksTest, NoDimplesInRRectPath)
| TEST_P (AiksTest, BackdropFilterOverUnclosedClip)
| TEST_P (AiksTest, PerspectiveRectangle)
static BlendModeSelection | GetBlendModeSelection ()
| TEST_P (AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
| TEST_P (AiksTest, BlendModeShouldCoverWholeScreen)
| TEST_P (AiksTest, CanDrawPaintWithAdvancedBlend)
| TEST_P (AiksTest, DrawPaintWithAdvancedBlendOverFilter)
| TEST_P (AiksTest, DrawAdvancedBlendPartlyOffscreen)
| TEST_P (AiksTest, PaintBlendModeIsRespected)
| TEST_P (AiksTest, ColorFilterBlend)
| TEST_P (AiksTest, ColorFilterAdvancedBlend)
| TEST_P (AiksTest, ColorFilterAdvancedBlendNoFbFetch)
| TEST_P (AiksTest, BlendModePlusAlphaWideGamut)
| TEST_P (AiksTest, BlendModePlusAlphaColorFilterWideGamut)
| TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
| TEST_P (AiksTest, ClearBlend)
static sk_sp< DisplayList > | BlendModeTest (Vector2 content_scale, BlendMode blend_mode, const sk_sp< DlImageImpeller > &src_image, const sk_sp< DlImageImpeller > &dst_image, Scalar src_alpha)
| TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
| TEST_P (AiksTest, ForegroundPipelineBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, ForegroundAdvancedBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, FramebufferAdvancedBlendCoverage)
| TEST_P (AiksTest, ColorWheel)
| TEST_P (AiksTest, DestructiveBlendColorFilterFloodsClip)
| TEST_P (AiksTest, AdvancedBlendColorFilterWithDestinationOpacity)
| TEST_P (AiksTest, EmulatedAdvancedBlendRestore)
| TEST_P (AiksTest, SolidColorOvalsMaskBlurTinySigma)
sk_sp< flutter::DisplayList > | DoGradientOvalStrokeMaskBlur (Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlur)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurSigmaZero)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurOuter)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurInner)
| TEST_P (AiksTest, GradientOvalStrokeMaskBlurSolid)
| TEST_P (AiksTest, SolidColorCircleMaskBlurTinySigma)
| TEST_P (AiksTest, CanRenderMaskBlurHugeSigma)
| TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
| TEST_P (AiksTest, CanRenderBackdropBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurWithSingleBackdropId)
| TEST_P (AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropId)
| TEST_P (AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters)
| TEST_P (AiksTest, CanRenderBackdropBlurHugeSigma)
| TEST_P (AiksTest, CanRenderBoundedBlur)
| TEST_P (AiksTest, CanRenderClippedBlur)
| TEST_P (AiksTest, ComposePaintBlurOuter)
| TEST_P (AiksTest, ComposePaintBlurInner)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectlyInteractive)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectly)
| TEST_P (AiksTest, ClearBlendWithBlur)
| TEST_P (AiksTest, BlurHasNoEdge)
| TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
| TEST_P (AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut)
static sk_sp< DisplayList > | MaskBlurVariantTest (const AiksTest &test_context, const MaskBlurTestConfig &config)
| TEST_P (AiksTest, GaussianBlurStyleInner)
| TEST_P (AiksTest, GaussianBlurStyleOuter)
| TEST_P (AiksTest, GaussianBlurStyleSolid)
| TEST_P (AiksTest, MaskBlurTexture)
| TEST_P (AiksTest, MaskBlurDoesntStretchContents)
| TEST_P (AiksTest, GaussianBlurAtPeripheryVertical)
| TEST_P (AiksTest, GaussianBlurAtPeripheryHorizontal)
| TEST_P (AiksTest, GaussianBlurAnimatedBackdrop)
| TEST_P (AiksTest, GaussianBlurStyleInnerGradient)
| TEST_P (AiksTest, GaussianBlurStyleSolidGradient)
| TEST_P (AiksTest, GaussianBlurStyleOuterGradient)
| TEST_P (AiksTest, GaussianBlurScaledAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedAndClippedInteractive)
| TEST_P (AiksTest, GaussianBlurOneDimension)
| TEST_P (AiksTest, GaussianBlurRotatedAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedNonUniform)
| TEST_P (AiksTest, BlurredRectangleWithShader)
| TEST_P (AiksTest, GaussianBlurSolidColorTinyMipMap)
| TEST_P (AiksTest, GaussianBlurBackdropTinyMipMap)
| TEST_P (AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers)
| TEST_P (AiksTest, BlurGradientWithOpacity)
| TEST_P (AiksTest, CanRenderNestedBackdropBlur)
| TEST_P (AiksTest, CanRenderNestedClips)
| TEST_P (AiksTest, CanRenderDifferenceClips)
| TEST_P (AiksTest, CanRenderWithContiguousClipRestores)
| TEST_P (AiksTest, ClipsUseCurrentTransform)
| TEST_P (AiksTest, FramebufferBlendsRespectClips)
| TEST_P (AiksTest, CanRenderLinearGradientClamp)
| TEST_P (AiksTest, CanRenderLinearGradientRepeat)
| TEST_P (AiksTest, CanRenderLinearGradientMirror)
| TEST_P (AiksTest, CanRenderLinearGradientDecal)
| TEST_P (AiksTest, CanRenderLinearGradientDecalWithColorFilter)
static void | CanRenderLinearGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringEnabled)
static void | CanRenderRadialGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringEnabled)
static void | CanRenderSweepGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringEnabled)
static void | CanRenderConicalGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderConicalGradientWithDitheringEnabled)
| TEST_P (AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderRadialGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderConicalGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderSweepGradientWithIncompleteStops)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsRepeat)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsMirror)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsDecal)
| TEST_P (AiksTest, CanRenderLinearGradientWayManyColorsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsUnevenStops)
| TEST_P (AiksTest, CanRenderLinearGradientMaskBlur)
| TEST_P (AiksTest, CanRenderRadialGradient)
| TEST_P (AiksTest, CanRenderRadialGradientManyColors)
| TEST_P (AiksTest, CanRenderSweepGradientClamp)
| TEST_P (AiksTest, CanRenderSweepGradientRepeat)
| TEST_P (AiksTest, CanRenderSweepGradientMirror)
| TEST_P (AiksTest, CanRenderSweepGradientDecal)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsClamp)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsRepeat)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsMirror)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsDecal)
| TEST_P (AiksTest, CanRenderConicalGradient)
| TEST_P (AiksTest, CanRenderGradientDecalWithBackground)
| TEST_P (AiksTest, GradientStrokesRenderCorrectly)
| TEST_P (AiksTest, FastGradientTestHorizontal)
| TEST_P (AiksTest, FastGradientTestVertical)
| TEST_P (AiksTest, FastGradientTestHorizontalReversed)
| TEST_P (AiksTest, FastGradientTestVerticalReversed)
| TEST_P (AiksTest, VerifyNonOptimizedGradient)
| TEST_P (AiksTest, DrawOpacityPeephole)
| TEST_P (AiksTest, CanRenderGroupOpacity)
| TEST_P (AiksTest, CanRenderGroupOpacityToSavelayer)
| TEST_P (AiksTest, RotateColorFilteredPath)
| TEST_P (AiksTest, CanRenderStrokes)
| TEST_P (AiksTest, CanRenderCurvedStrokes)
| TEST_P (AiksTest, CanRenderThickCurvedStrokes)
| TEST_P (AiksTest, CanRenderThinCurvedStrokes)
| TEST_P (AiksTest, CanRenderStrokePathThatEndsAtSharpTurn)
| TEST_P (AiksTest, CanRenderStrokePathWithCubicLine)
| TEST_P (AiksTest, CanRenderQuadraticStrokeWithInstantTurn)
| TEST_P (AiksTest, CanRenderFilledConicPaths)
| TEST_P (AiksTest, CanRenderStrokedConicPaths)
| TEST_P (AiksTest, HairlinePath)
| TEST_P (AiksTest, HairlineDrawLine)
| TEST_P (AiksTest, CanRenderTightConicPath)
| TEST_P (AiksTest, CanRenderDifferencePaths)
| TEST_P (AiksTest, CanDrawAnOpenPath)
| TEST_P (AiksTest, CanDrawAnOpenPathThatIsntARect)
| TEST_P (AiksTest, SolidStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawLinesRenderCorrectly)
| TEST_P (AiksTest, ScaleExperimentAntialiasLines)
| TEST_P (AiksTest, HexagonExperimentAntialiasLines)
| TEST_P (AiksTest, SimpleExperimentAntialiasLines)
| TEST_P (AiksTest, DrawRectStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly)
| TEST_P (AiksTest, CanDrawMultiContourConvexPath)
| TEST_P (AiksTest, ArcWithZeroSweepAndBlur)
| TEST_P (AiksTest, CanRenderClips)
| TEST_P (AiksTest, FatStrokeArc)
| TEST_P (AiksTest, CanRenderOverlappingMultiContourPath)
| TEST_P (AiksTest, TwoContourPathWithSinglePointContour)
| TEST_P (AiksTest, StrokeCapsAndJoins)
| TEST_P (AiksTest, BlurredCircleWithStrokeWidth)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
| TEST_P (AiksTest, CanRenderRuntimeEffectFilter)
| TEST_P (AiksTest, RuntimeEffectWithInvalidSamplerDoesNotCrash)
| TEST_P (AiksTest, ComposePaintRuntimeOuter)
| TEST_P (AiksTest, ComposePaintRuntimeInner)
| TEST_P (AiksTest, ComposeBackdropRuntimeOuterBlurInner)
| TEST_P (AiksTest, ComposeBackdropRuntimeOuterBlurInnerSmallSigma)
| TEST_P (AiksTest, ClippedBackdropFilterWithShader)
| TEST_P (AiksTest, RuntimeEffectImageFilterRotated)
| TEST_P (AiksTest, RuntimeEffectVectorArray)
| TEST_P (AiksTest, DrawShadowDoesNotOptimizeHourglass)
| TEST_P (AiksTest, DrawShadowDoesNotOptimizeInnerOuterSpiral)
| TEST_P (AiksTest, DrawShadowDoesNotOptimizeOuterInnerSpiral)
| TEST_P (AiksTest, DrawShadowDoesNotOptimizeMultipleContours)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseTriangle)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseTriangle)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseCircle)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseCircle)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseOval)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseOval)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseUniformRoundRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseUniformRoundRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseMultiRadiiRoundRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseMultiRadiiRoundRect)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseQuadratic)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseQuadratic)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseConic)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseConic)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseCubic)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseCubic)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseOctagon)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseOctagon)
| TEST_P (AiksTest, DrawShadowCanOptimizeWithExtraneousMoveTos)
| TEST_P (AiksTest, DrawShadowCanOptimizeClockwiseWithExtraColinearVertices)
| TEST_P (AiksTest, DrawShadowCanOptimizeCounterClockwiseWithExtraColinearVertices)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &font_fixture, const TextRenderOptions &options={}, const std::optional< SkFont > &font=std::nullopt)
| TEST_P (AiksTest, CanRenderTextFrame)
| TEST_P (AiksTest, CanRenderTextFrameWithInvertedTransform)
| TEST_P (AiksTest, CanRenderStrokedTextFrame)
| TEST_P (AiksTest, CanRenderTextStrokeWidth)
| TEST_P (AiksTest, CanRenderTextFrameWithHalfScaling)
| TEST_P (AiksTest, ScaledK)
| TEST_P (AiksTest, MassiveScaleConvertToPath)
| TEST_P (AiksTest, CanRenderTextFrameWithScalingOverflow)
| TEST_P (AiksTest, CanRenderTextFrameWithFractionScaling)
| TEST_P (AiksTest, TextRotated180Degrees)
| TEST_P (AiksTest, TextFrameSubpixelAlignment)
| TEST_P (AiksTest, CanRenderItalicizedText)
| TEST_P (AiksTest, CanRenderEmojiTextFrame)
| TEST_P (AiksTest, CanRenderEmojiTextFrameWithBlur)
| TEST_P (AiksTest, CanRenderEmojiTextFrameWithAlpha)
| TEST_P (AiksTest, CanRenderTextInSaveLayer)
| TEST_P (AiksTest, CanRenderTextOutsideBoundaries)
| TEST_P (AiksTest, TextRotated)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
| TEST_P (AiksTest, CanRenderTextWithLargePerspectiveTransform)
| TEST_P (AiksTest, CanRenderTextWithPerspectiveTransformInSublist)
| TEST_P (AiksTest, TextForegroundShaderWithTransform)
| TEST_P (AiksTest, DifferenceClipsMustRenderIdenticallyAcrossBackends)
| TEST_P (AiksTest, TextContentsMismatchedTransformTest)
| TEST_P (AiksTest, TextWithShadowCache)
| TEST_P (AiksTest, MultipleTextWithShadowCache)
| TEST_P (AiksTest, MultipleColorWithShadowCache)
| TEST_P (AiksTest, SingleIconShadowTest)
| TEST_P (AiksTest, VarietyOfTextScalesShowingRasterAndPath)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpass)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpassBackdropFilter)
| TEST_P (AiksTest, ColorMatrixFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, LinearToSrgbFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, SrgbToLinearFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, TranslucentSaveLayerDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents)
| TEST_P (AiksTest, TranslucentSaveLayerImageDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly)
| TEST_P (AiksTest, CanRenderTinyOverlappingSubpasses)
| TEST_P (AiksTest, CanRenderDestructiveSaveLayer)
| TEST_P (AiksTest, CanDrawPoints)
| TEST_P (AiksTest, CanDrawPointsWithTextureMap)
| TEST_P (AiksTest, MipmapGenerationWorksCorrectly)
| TEST_P (AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly)
| TEST_P (AiksTest, SetContentsWithRegion)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, ImageFilteredSaveLayerWithUnboundedContents)
| TEST_P (AiksTest, MatrixBackdropFilter)
| TEST_P (AiksTest, MatrixSaveLayerFilter)
| TEST_P (AiksTest, CanDrawScaledPointsSmallScaleLargeRadius)
| TEST_P (AiksTest, CanDrawScaledPointsLargeScaleSmallRadius)
| TEST_P (AiksTest, TransparentShadowProducesCorrectColor)
| TEST_P (AiksTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
| TEST_P (AiksTest, BackdropRestoreUsesCorrectCoverageForFirstRestoredClip)
| TEST_P (AiksTest, CanPictureConvertToImage)
| TEST_P (AiksTest, CanEmptyPictureConvertToImage)
| TEST_P (AiksTest, DepthValuesForLineMode)
| TEST_P (AiksTest, DepthValuesForPolygonMode)
| TEST_P (AiksTest, ToImageFromImage)
| TEST_P (AiksTest, DisplayListToTextureAllocationFailure)
| TEST_P (AiksTest, DisplayListToTextureWithMipGeneration)
| TEST_P (AiksTest, VerticesGeometryUVPositionData)
| TEST_P (AiksTest, VerticesGeometryUVPositionDataWithTranslate)
| TEST_P (AiksTest, VerticesGeometryColorUVPositionData)
| TEST_P (AiksTest, VerticesGeometryColorUVPositionDataAdvancedBlend)
| TEST_P (AiksTest, CanConvertTriangleFanToTriangles)
| TEST_P (AiksTest, DrawVerticesSolidColorTrianglesWithoutIndices)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithoutIndices)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithTextureCoordinates)
| TEST_P (AiksTest, DrawVerticesImageSourceWithTextureCoordinates)
| TEST_P (AiksTest, DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending)
| TEST_P (AiksTest, DrawVerticesSolidColorTrianglesWithIndices)
| TEST_P (AiksTest, DrawVerticesPremultipliesColors)
| TEST_P (AiksTest, DrawVerticesWithInvalidIndices)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShader)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShaderNonZeroOrigin)
| TEST_P (AiksTest, VerticesGeometryWithMaskFilter)
| INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
std::unique_ptr< Canvas > | CreateTestCanvas (ContentContext &context, std::optional< Rect > cull_rect=std::nullopt, bool requires_readback=false)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
| TEST_P (AiksTest, BackdropCountDownNormal)
| TEST_P (AiksTest, BackdropCountDownBackdropId)
| TEST_P (AiksTest, BackdropCountDownBackdropIdMixed)
| TEST_P (AiksTest, BackdropCountDownWithNestedSaveLayers)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithEmptySize)
| TEST_P (AiksTest, DrawVerticesWithEmptyTextureCoordinates)
| TEST_P (AiksTest, SupportsBlitToOnscreen)
| TEST_P (AiksTest, RoundSuperellipseShadowComparison)
flutter::DlColor | toColor (const float *components)
| INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
| TEST_P (DisplayListTest, CanDrawRect)
| TEST_P (DisplayListTest, CanDrawTextBlob)
| TEST_P (DisplayListTest, CanDrawTextBlobWithGradient)
| TEST_P (DisplayListTest, CanDrawTextWithSaveLayer)
| TEST_P (DisplayListTest, CanDrawImage)
| TEST_P (DisplayListTest, CanDrawCapsAndJoins)
| TEST_P (DisplayListTest, CanDrawArc)
| TEST_P (DisplayListTest, StrokedPathsDrawCorrectly)
| TEST_P (DisplayListTest, CanDrawWithOddPathWinding)
| TEST_P (DisplayListTest, CanDrawAnOpenPath)
| TEST_P (DisplayListTest, CanDrawWithMaskBlur)
| TEST_P (DisplayListTest, CanDrawStrokedText)
| TEST_P (DisplayListTest, StrokedTextNotOffsetFromNormalText)
| TEST_P (DisplayListTest, IgnoreMaskFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawWithBlendColorFilter)
| TEST_P (DisplayListTest, CanDrawWithColorFilterImageFilter)
| TEST_P (DisplayListTest, CanDrawWithImageBlurFilter)
| TEST_P (DisplayListTest, CanDrawWithComposeImageFilter)
| TEST_P (DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter)
| TEST_P (DisplayListTest, CanDrawBackdropFilter)
| TEST_P (DisplayListTest, CanDrawBoundedBlur)
| TEST_P (DisplayListTest, CanDrawNinePatchImage)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCornersScaledDown)
| TEST_P (DisplayListTest, NinePatchImagePrecision)
| TEST_P (DisplayListTest, NinePatchImageColorFilter)
| TEST_P (DisplayListTest, CanDrawPoints)
| TEST_P (DisplayListTest, CanDrawZeroLengthLine)
| TEST_P (DisplayListTest, CanDrawShadow)
| TEST_P (DisplayListTest, CanDrawZeroWidthLine)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilter)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawRectWithLinearToSrgbColorFilter)
| TEST_P (DisplayListTest, CanDrawPaintWithColorSource)
| TEST_P (DisplayListTest, CanBlendDstOverAndDstCorrectly)
| TEST_P (DisplayListTest, CanDrawCorrectlyWithColorFilterAndImageFilter)
| TEST_P (DisplayListTest, MaskBlursApplyCorrectlyToColorSources)
| TEST_P (DisplayListTest, DrawShapes)
| TEST_P (DisplayListTest, DrawCirclesWithTransformations)
| TEST_P (DisplayListTest, ClipDrawRRectWithNonCircularRadii)
| TEST_P (DisplayListTest, DrawVerticesBlendModes)
| TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
| TEST_P (DisplayListTest, DrawMaskBlursThatMightUseSaveLayers)
| TEST (PaintTest, GradientStopConversion)
| TEST (PaintTest, GradientMissing0)
| TEST (PaintTest, GradientMissingLastValue)
| TEST (PaintTest, GradientStopGreaterThan1)
| TEST (PaintTest, GradientConversionNonMonotonic)
| TEST (SkiaConversionTest, ToSamplerDescriptor)
| TEST (SkiaConversionsTest, ToColor)
| TEST (EntityPassClipStackTest, CanPushAndPopEntities)
| TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverageNonAA)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverage)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverageWithDifferenceOrNonSquare)
| TEST (EntityPassClipStackTest, AppendDecreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, AppendIncreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpassesNonAA)
| INSTANTIATE_PLAYGROUND_SUITE (BlendFilterContentsTest)
| TEST_P (BlendFilterContentsTest, AdvancedBlendColorAlignsColorTo4)
| INSTANTIATE_PLAYGROUND_SUITE (GaussianBlurFilterContentsTest)
| TEST (GaussianBlurFilterContentsTest, Create)
| TEST (GaussianBlurFilterContentsTest, CoverageEmpty)
| TEST (GaussianBlurFilterContentsTest, CoverageSimple)
| TEST (GaussianBlurFilterContentsTest, CoverageWithSigma)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithTexture)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, FilterSourceCoverage)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaValues)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageRotated)
| TEST_P (GaussianBlurFilterContentsTest, CalculateUVsSimple)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRect)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRectScaled)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaForBlurRadius)
| TEST (GaussianBlurFilterContentsTest, Coefficients)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesSimple)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesComplex)
| TEST (GaussianBlurFilterContentsTest, ChopHugeBlurs)
| TEST (FilterInputTest, CanSetLocalTransformForTexture)
| INSTANTIATE_PLAYGROUND_SUITE (MatrixFilterContentsTest)
| TEST (MatrixFilterContentsTest, CoverageEmpty)
| TEST (MatrixFilterContentsTest, CoverageSimple)
| TEST (MatrixFilterContentsTest, Coverage2x)
| TEST (MatrixFilterContentsTest, Coverage2xEffect)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageIdentity)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageSubpassScale)
| INSTANTIATE_PLAYGROUND_SUITE (HostBufferTest)
| TEST_P (HostBufferTest, IdleWaiter)
| TEST_P (HostBufferTest, CanEmplace)
| TEST_P (HostBufferTest, CanEmplaceWithAlignment)
| TEST_P (HostBufferTest, HostBufferInitialState)
| TEST_P (HostBufferTest, ResetIncrementsFrameCounter)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer)
| TEST_P (HostBufferTest, UnusedBuffersAreDiscardedWhenResetting)
| TEST_P (HostBufferTest, EmplaceWithProcIsAligned)
| TEST_P (HostBufferTest, EmplaceWithFailingAllocationDoesntCrash)
| TEST (LineContents, Create)
| TEST (LineContents, CalculatePerVertex)
| TEST (LineContents, CreateCurveData)
| TEST (LineContents, CreateCurveDataScaled)
| TEST (LineContents, CalculatePerVertexLimit)
| INSTANTIATE_PLAYGROUND_SUITE (TextContentsTest)
| TEST_P (TextContentsTest, SimpleComputeVertexData)
| TEST_P (TextContentsTest, SimpleComputeVertexData2x)
| TEST_P (TextContentsTest, MaintainsShape)
| TEST_P (TextContentsTest, SimpleSubpixel)
| TEST_P (TextContentsTest, SimpleSubpixel3x)
| TEST_P (TextContentsTest, SimpleSubpixel26)
| TEST_P (TextContentsTest, SimpleSubpixel80)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithNoClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsRespectsSkipCounts)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithFlush)
| TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
| TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
Rect | RectMakeCenterSize (Point center, Size size)
| TEST_P (EntityTest, CanCreateEntity)
| TEST_P (EntityTest, FilterCoverageRespectsCropRect)
| TEST_P (EntityTest, GeometryBoundsAreTransformed)
| TEST_P (EntityTest, ThreeStrokesInOnePath)
| TEST_P (EntityTest, StrokeWithTextureContents)
| TEST_P (EntityTest, TriangleInsideASquare)
| TEST_P (EntityTest, StrokeCapAndJoinTest)
| TEST_P (EntityTest, CubicCurveTest)
| TEST_P (EntityTest, CanDrawCorrectlyWithRotatedTransform)
| TEST_P (EntityTest, CubicCurveAndOverlapTest)
| TEST_P (EntityTest, SolidColorContentsStrokeSetStrokeCapsAndJoins)
| TEST_P (EntityTest, SolidColorContentsStrokeSetMiterLimit)
| TEST_P (EntityTest, BlendingModeOptions)
| TEST_P (EntityTest, BezierCircleScaled)
| TEST_P (EntityTest, Filters)
| TEST_P (EntityTest, GaussianBlurFilter)
| TEST_P (EntityTest, MorphologyFilter)
| TEST_P (EntityTest, SetBlendMode)
| TEST_P (EntityTest, ContentsGetBoundsForEmptyPathReturnsNullopt)
| TEST_P (EntityTest, SolidStrokeCoverageIsCorrect)
| TEST_P (EntityTest, BorderMaskBlurCoverageIsCorrect)
| TEST_P (EntityTest, SolidFillCoverageIsCorrect)
| TEST_P (EntityTest, RRectShadowTest)
| TEST_P (EntityTest, ColorMatrixFilterCoverageIsCorrect)
| TEST_P (EntityTest, ColorMatrixFilterEditable)
| TEST_P (EntityTest, LinearToSrgbFilterCoverageIsCorrect)
| TEST_P (EntityTest, LinearToSrgbFilter)
| TEST_P (EntityTest, SrgbToLinearFilterCoverageIsCorrect)
| TEST_P (EntityTest, SrgbToLinearFilter)
static Vector3 | RGBToYUV (Vector3 rgb, YUVColorSpace yuv_color_space)
static std::vector< std::shared_ptr< Texture > > | CreateTestYUVTextures (Context *context, YUVColorSpace yuv_color_space)
| TEST_P (EntityTest, YUVToRGBFilter)
| TEST_P (EntityTest, RuntimeEffect)
| TEST_P (EntityTest, RuntimeEffectCanSuccessfullyRender)
| TEST_P (EntityTest, RuntimeEffectCanPrecache)
| TEST_P (EntityTest, RuntimeEffectSetsRightSizeWhenUniformIsStruct)
| TEST_P (EntityTest, ColorFilterWithForegroundColorAdvancedBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorClearBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorDstBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcInBlend)
| TEST_P (EntityTest, CoverageForStrokePathWithNegativeValuesInTransform)
| TEST_P (EntityTest, SolidColorContentsIsOpaque)
| TEST_P (EntityTest, ConicalGradientContentsIsOpaque)
| TEST_P (EntityTest, LinearGradientContentsIsOpaque)
| TEST_P (EntityTest, RadialGradientContentsIsOpaque)
| TEST_P (EntityTest, SweepGradientContentsIsOpaque)
| TEST_P (EntityTest, TiledTextureContentsIsOpaque)
| TEST_P (EntityTest, PointFieldGeometryCoverage)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, SpecializationConstantsAreAppliedToVariants)
| TEST_P (EntityTest, DecalSpecializationAppliedToMorphologyFilter)
| TEST_P (EntityTest, ContentContextOptionsHasReasonableHashFunctions)
| TEST_P (EntityTest, FillPathGeometryGetPositionBufferReturnsExpectedMode)
| TEST_P (EntityTest, StrokeArcGeometryGetPositionBufferReturnsExpectedMode)
| TEST_P (EntityTest, FailOnValidationError)
| TEST_P (EntityTest, CanComputeGeometryForEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, CanRenderEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, DrawSuperEllipse)
| TEST_P (EntityTest, DrawRoundSuperEllipse)
| TEST_P (EntityTest, DrawRoundSuperEllipseWithLargeN)
| TEST_P (EntityTest, CanDrawRoundSuperEllipseWithTinyRadius)
| TEST_P (EntityTest, CanDrawRoundSuperEllipseWithJustEnoughRadius)
| TEST_P (EntityTest, SolidColorApplyColorFilter)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Linear)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Radial)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Conical)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Sweep)
| TEST_P (EntityTest, GiantStrokePathAllocation)
| TEST_P (EntityTest, RoundSuperellipseGetPositionBufferFlushes)
| TEST (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (EntityGeometryTest, FillArcGeometryCoverage)
| TEST (EntityGeometryTest, StrokeArcGeometryCoverage)
| TEST (EntityGeometryTest, FillRoundRectGeometryCoversArea)
| TEST (EntityGeometryTest, LineGeometryCoverage)
| TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
| TEST (EntityGeometryTest, GeometryResultHasReasonableDefaults)
| TEST (EntityGeometryTest, AlphaCoverageStrokePaths)
| TEST (EntityGeometryTest, SimpleTwoLineStrokeVerticesButtCap)
| TEST (EntityGeometryTest, SimpleTwoLineStrokeVerticesRoundCap)
| TEST (EntityGeometryTest, SimpleTwoLineStrokeVerticesSquareCap)
| TEST (EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesBevelJoin)
| TEST (EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesBevelJoin)
| TEST (EntityGeometryTest, TwoLineSegmentsRightTurnStrokeVerticesMiterJoin)
| TEST (EntityGeometryTest, TwoLineSegmentsLeftTurnStrokeVerticesMiterJoin)
| TEST (EntityGeometryTest, TinyQuadGeneratesCaps)
| TEST (EntityGeometryTest, TinyConicGeneratesCaps)
| TEST (EntityGeometryTest, TinyCubicGeneratesCaps)
| TEST (EntityGeometryTest, TwoLineSegmentsMiterLimit)
| TEST (EntityGeometryTest, TwoLineSegments180DegreeJoins)
| TEST (EntityGeometryTest, TightQuadratic180DegreeJoins)
| TEST (EntityGeometryTest, TightConic180DegreeJoins)
| TEST (EntityGeometryTest, TightCubic180DegreeJoins)
| TEST (EntityGeometryTest, RotatedFilledCircleGeometryCoverage)
| TEST (EntityGeometryTest, RotatedStrokedCircleGeometryCoverage)
| TEST (ShadowPathGeometryTest, EmptyPathTest)
| TEST (ShadowPathGeometryTest, MoveToOnlyTest)
| TEST (ShadowPathGeometryTest, OnePathSegmentTest)
| TEST (ShadowPathGeometryTest, TwoColinearSegmentsTest)
| TEST (ShadowPathGeometryTest, EmptyRectTest)
| TEST (ShadowPathGeometryTest, GetAndTakeVertices)
| TEST (ShadowPathGeometryTest, ClockwiseTriangleTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseTriangleTest)
| TEST (ShadowPathGeometryTest, ClockwiseRectTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseRectTest)
| TEST (ShadowPathGeometryTest, ClockwiseRectExtraColinearPointsTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseRectExtraColinearPointsTest)
| TEST (ShadowPathGeometryTest, ClockwiseRectTrickyColinearPointsTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseRectTrickyColinearPointsTest)
| TEST (ShadowPathGeometryTest, ClockwiseRectTrickyDupColinearPointsTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseRectTrickyDupColinearPointsTest)
| TEST (ShadowPathGeometryTest, ClockwiseRectNearlyColinearPointsTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseRectNearlyColinearPointsTest)
| TEST (ShadowPathGeometryTest, ScaledRectTest)
| TEST (ShadowPathGeometryTest, EllipseTest)
| TEST (ShadowPathGeometryTest, RoundRectTest)
| TEST (ShadowPathGeometryTest, HourglassSelfIntersectingTest)
| TEST (ShadowPathGeometryTest, ReverseHourglassSelfIntersectingTest)
| TEST (ShadowPathGeometryTest, InnerToOuterOverturningSpiralTest)
| TEST (ShadowPathGeometryTest, ReverseInnerToOuterOverturningSpiralTest)
| TEST (ShadowPathGeometryTest, OuterToInnerOverturningSpiralTest)
| TEST (ShadowPathGeometryTest, ReverseOuterToInnerOverturningSpiralTest)
| TEST (ShadowPathGeometryTest, ClockwiseOctagonCollapsedUmbraPolygonTest)
| TEST (ShadowPathGeometryTest, CounterClockwiseOctagonCollapsedUmbraPolygonTest)
| TEST (ShadowPathGeometryTest, MultipleContoursTest)
| TEST_P (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
| TEST_P (RenderTargetCacheTest, CachesUsedTexturesAcrossFramesWithKeepAlive)
| TEST_P (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
| TEST_P (RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig)
| TEST_P (RenderTargetCacheTest, CreateWithEmptySize)
| TEST (SaveLayerUtilsTest, SimplePaintComputedCoverage)
| TEST (SaveLayerUtilsTest, BackdropFiterComputedCoverage)
| TEST (SaveLayerUtilsTest, ImageFiterComputedCoverage)
| TEST (SaveLayerUtilsTest, ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit)
| TEST (SaveLayerUtilsTest, ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit)
| TEST (SaveLayerUtilsTest, DisjointCoverage)
| TEST (SaveLayerUtilsTest, DisjointCoverageTransformedByImageFilter)
| TEST (SaveLayerUtilsTest, DisjointCoveragTransformedByCTM)
| TEST (SaveLayerUtilsTest, BasicEmptyCoverage)
| TEST (SaveLayerUtilsTest, ImageFilterEmptyCoverage)
| TEST (SaveLayerUtilsTest, BackdropFilterEmptyCoverage)
| TEST (SaveLayerUtilsTest, FloodInputCoverage)
| TEST (SaveLayerUtilsTest, FloodInputCoverageWithImageFilter)
| TEST (SaveLayerUtilsTest, FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage)
| TEST (SaveLayerUtilsTest, CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter)
| TEST (SaveLayerUtilsTest, CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter)
| TEST (SaveLayerUtilsTest, CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverage)
| TEST (SaveLayerUtilsTest, RoundUpCoverageWhenCloseToCoverageLimit)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight)
| TEST (SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight)
| TEST (ArcTest, ArcIterationsFullCircle)
| TEST (ArcTest, ArcIterationsVariousStartAnglesNearQuadrantAxis)
| TEST (ArcTest, ArcIterationsVariousEndAnglesNearQuadrantAxis)
| TEST (ArcTest, ArcIterationsVariousTinyArcsNearQuadrantAxis)
| TEST (ArcTest, ArcIterationsOnlyFirstQuadrant)
| TEST (ArcTest, ArcIterationsOnlySecondQuadrant)
| TEST (ArcTest, ArcIterationsOnlyThirdQuadrant)
| TEST (ArcTest, ArcIterationsOnlyFourthQuadrant)
| TEST (ArcTest, ArcIterationsAllQuadrantsFromFirst)
| TEST (ArcTest, ArcIterationsAllQuadrantsFromSecond)
| TEST (ArcTest, ArcIterationsAllQuadrantsFromThird)
| TEST (ArcTest, ArcIterationsAllQuadrantsFromFourth)
| TEST (GeometryTest, ScalarNearlyEqual)
| TEST (GeometryTest, MakeColumn)
| TEST (GeometryTest, MakeRow)
| TEST (GeometryTest, RotationMatrix)
| TEST (GeometryTest, InvertMultMatrix)
| TEST (GeometryTest, MatrixBasis)
| TEST (GeometryTest, MutliplicationMatrix)
| TEST (GeometryTest, DeterminantTest)
| TEST (GeometryTest, InvertMatrix)
| TEST (GeometryTest, TestDecomposition)
| TEST (GeometryTest, TestDecomposition2)
| TEST (GeometryTest, TestRecomposition)
| TEST (GeometryTest, TestRecomposition2)
| TEST (GeometryTest, MatrixVectorMultiplication)
| TEST (GeometryTest, MatrixMakeRotationFromQuaternion)
| TEST (GeometryTest, MatrixTransformDirection)
| TEST (GeometryTest, MatrixGetMaxBasisLengthXY)
| TEST (GeometryTest, MatrixMakeOrthographic)
| TEST (GeometryTest, MatrixMakePerspective)
| TEST (GeometryTest, MatrixGetBasisVectors)
| TEST (GeometryTest, MatrixGetDirectionScale)
| TEST (GeometryTest, MatrixTranslationScaleOnly)
| TEST (GeometryTest, MatrixLookAt)
| TEST (GeometryTest, QuaternionLerp)
| TEST (GeometryTest, QuaternionVectorMultiply)
| TEST (GeometryTest, CanGenerateMipCounts)
| TEST (GeometryTest, CanConvertTTypesExplicitly)
| TEST (GeometryTest, CanPerformAlgebraicPointOps)
| TEST (GeometryTest, CanPerformAlgebraicPointOpsWithArithmeticTypes)
| TEST (GeometryTest, PointIntegerCoercesToFloat)
| TEST (GeometryTest, SizeCoercesToPoint)
| TEST (GeometryTest, CanUsePointAssignmentOperators)
| TEST (GeometryTest, PointDotProduct)
| TEST (GeometryTest, PointCrossProduct)
| TEST (GeometryTest, PointReflect)
| TEST (GeometryTest, PointAbs)
| TEST (GeometryTest, PointRotate)
| TEST (GeometryTest, PointAngleTo)
| TEST (GeometryTest, PointMin)
| TEST (GeometryTest, Vector4IsFinite)
| TEST (GeometryTest, Vector3Min)
| TEST (GeometryTest, Vector4Min)
| TEST (GeometryTest, PointMax)
| TEST (GeometryTest, Vector3Max)
| TEST (GeometryTest, Vector4Max)
| TEST (GeometryTest, PointFloor)
| TEST (GeometryTest, Vector3Floor)
| TEST (GeometryTest, Vector4Floor)
| TEST (GeometryTest, PointCeil)
| TEST (GeometryTest, Vector3Ceil)
| TEST (GeometryTest, Vector4Ceil)
| TEST (GeometryTest, PointRound)
| TEST (GeometryTest, Vector3Round)
| TEST (GeometryTest, Vector4Round)
| TEST (GeometryTest, PointLerp)
| TEST (GeometryTest, Vector3Lerp)
| TEST (GeometryTest, Vector4Lerp)
| TEST (GeometryTest, SeparatedVector2NormalizesWithConstructor)
| TEST (GeometryTest, SeparatedVector2GetVector)
| TEST (GeometryTest, SeparatedVector2GetAlignment)
| TEST (GeometryTest, SeparatedVector2AngleTo)
| TEST (GeometryTest, CanUseVector3AssignmentOperators)
| TEST (GeometryTest, CanPerformAlgebraicVector3Ops)
| TEST (GeometryTest, CanPerformAlgebraicVector3OpsWithArithmeticTypes)
| TEST (GeometryTest, ColorPremultiply)
| TEST (GeometryTest, ColorR8G8B8A8)
| TEST (GeometryTest, ColorLerp)
| TEST (GeometryTest, ColorClamp01)
| TEST (GeometryTest, ColorMakeRGBA8)
| TEST (GeometryTest, ColorApplyColorMatrix)
| TEST (GeometryTest, ColorLinearToSRGB)
| TEST (GeometryTest, ColorSRGBToLinear)
| TEST (GeometryTest, ColorBlendReturnsExpectedResults)
| TEST (GeometryTest, BlendModeToString)
| TEST (GeometryTest, CanConvertBetweenDegressAndRadians)
| TEST (GeometryTest, MatrixPrinting)
| TEST (GeometryTest, PointPrinting)
| TEST (GeometryTest, Vector3Printing)
| TEST (GeometryTest, Vector4Printing)
| TEST (GeometryTest, ColorPrinting)
| TEST (GeometryTest, ToIColor)
| TEST (GeometryTest, Gradient)
| TEST (GeometryTest, HalfConversions)
| TEST (MatrixTest, Multiply)
| TEST (MatrixTest, Equals)
| TEST (MatrixTest, NotEquals)
| TEST (MatrixTest, HasPerspective2D)
| TEST (MatrixTest, HasPerspective)
| TEST (MatrixTest, HasTranslation)
| TEST (MatrixTest, IsTranslationOnly)
| TEST (MatrixTest, IsTranslationScaleOnly)
| TEST (MatrixTest, IsInvertibleGetDeterminant)
| TEST (MatrixTest, IsFinite)
| TEST (MatrixTest, IsAligned2D)
| TEST (MatrixTest, IsAligned)
| TEST (MatrixTest, TransformHomogenous)
| TEST (MatrixTest, GetMaxBasisXYNegativeScale)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactor)
| TEST (MatrixTest, GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate)
| TEST (MatrixTest, TranslateWithPerspective)
| TEST (MatrixTest, MakeScaleTranslate)
| TEST (MatrixTest, To3x3)
| TEST (MatrixTest, MinMaxScales2D)
| TEST (PathSourceTest, RectSourceTest)
| TEST (PathSourceTest, EllipseSourceTest)
| TEST (PathSourceTest, RoundRectSourceTest)
| TEST (PathSourceTest, DiffRoundRectSourceTest)
| TEST (PathSourceTest, DashedLinePathSource)
| TEST (PathSourceTest, EmptyDashedLinePathSource)
| TEST (PathSourceTest, DashedLinePathSourceZeroOffGaps)
| TEST (PathSourceTest, DashedLinePathSourceInvalidOffGaps)
| TEST (PathSourceTest, DashedLinePathSourceInvalidOnRegion)
| TEST (PathSourceTest, PathTransformerRectSourceTest)
| TEST (PathSourceTest, PathTransformerAllSegmentsTest)
| TEST (PointTest, Length)
| TEST (PointTest, Distance)
| TEST (PointTest, PerpendicularLeft)
| TEST (PointTest, PerpendicularRight)
| TEST (PointTest, PointToSegment)
| TEST (PointTest, CrossProductThreePoints)
| TEST (RectTest, RectEmptyDeclaration)
| TEST (RectTest, IRectEmptyDeclaration)
| TEST (RectTest, RectDefaultConstructor)
| TEST (RectTest, IRectDefaultConstructor)
| TEST (RectTest, RectSimpleLTRB)
| TEST (RectTest, IRectSimpleLTRB)
| TEST (RectTest, RectSimpleXYWH)
| TEST (RectTest, IRectSimpleXYWH)
| TEST (RectTest, RectSimpleWH)
| TEST (RectTest, IRectSimpleWH)
| TEST (RectTest, RectFromIRect)
| TEST (RectTest, RectOverflowXYWH)
| TEST (RectTest, IRectOverflowXYWH)
| TEST (RectTest, RectOverflowLTRB)
| TEST (RectTest, IRectOverflowLTRB)
| TEST (RectTest, RectMakeSize)
| TEST (RectTest, RectMakeMaximum)
| TEST (RectTest, IRectMakeMaximum)
| TEST (RectTest, RectFromRect)
| TEST (RectTest, IRectFromIRect)
| TEST (RectTest, RectCopy)
| TEST (RectTest, IRectCopy)
| TEST (RectTest, RectOriginSizeXYWHGetters)
| TEST (RectTest, IRectOriginSizeXYWHGetters)
| TEST (RectTest, RectRoundOutEmpty)
| TEST (RectTest, RectRoundOutSimple)
| TEST (RectTest, RectRoundOutToIRectHuge)
| TEST (RectTest, RectDoesNotIntersectEmpty)
| TEST (RectTest, IRectDoesNotIntersectEmpty)
| TEST (RectTest, EmptyRectDoesNotIntersect)
| TEST (RectTest, EmptyIRectDoesNotIntersect)
| TEST (RectTest, RectScale)
| TEST (RectTest, IRectScale)
| TEST (RectTest, RectArea)
| TEST (RectTest, IRectArea)
| TEST (RectTest, RectGetNormalizingTransform)
| TEST (RectTest, IRectGetNormalizingTransform)
| TEST (RectTest, RectXYWHIsEmpty)
| TEST (RectTest, IRectXYWHIsEmpty)
| TEST (RectTest, MakePointBoundsQuad)
| TEST (RectTest, IsSquare)
| TEST (RectTest, GetCenter)
| TEST (RectTest, RectExpand)
| TEST (RectTest, IRectExpand)
| TEST (RectTest, ContainsFloatingPoint)
template<typename R >
static constexpr R | flip_lr (R rect)
template<typename R >
static constexpr R | flip_tb (R rect)
template<typename R >
static constexpr R | flip_lrtb (R rect)
static constexpr Rect | swap_nan (const Rect &rect, int index)
static constexpr Point | swap_nan (const Point &point, int index)
| TEST (RectTest, RectUnion)
| TEST (RectTest, OptRectUnion)
| TEST (RectTest, IRectUnion)
| TEST (RectTest, OptIRectUnion)
| TEST (RectTest, RectIntersection)
| TEST (RectTest, OptRectIntersection)
| TEST (RectTest, IRectIntersection)
| TEST (RectTest, OptIRectIntersection)
| TEST (RectTest, RectIntersectsWithRect)
| TEST (RectTest, IRectIntersectsWithRect)
| TEST (RectTest, RectContainsPoint)
| TEST (RectTest, IRectContainsIPoint)
| TEST (RectTest, RectContainsInclusivePoint)
| TEST (RectTest, IRectContainsInclusiveIPoint)
| TEST (RectTest, RectContainsRect)
| TEST (RectTest, IRectContainsIRect)
| TEST (RectTest, RectCutOut)
| TEST (RectTest, IRectCutOut)
| TEST (RectTest, RectGetPoints)
| TEST (RectTest, RectShift)
| TEST (RectTest, RectGetTransformedPoints)
| TEST (RectTest, RectMakePointBounds)
| TEST (RectTest, RectGetPositive)
| TEST (RectTest, RectDirections)
| TEST (RectTest, RectProject)
| TEST (RectTest, RectRoundOut)
| TEST (RectTest, IRectRoundOut)
| TEST (RectTest, RectRound)
| TEST (RectTest, IRectRound)
| TEST (RectTest, TransformAndClipBoundsNoCornersClipped)
| TEST (RectTest, TransformAndClipBoundsOneCornerClipped)
| TEST (RectTest, TransformAndClipBoundsTwoCornersClipped)
| TEST (RectTest, TransformAndClipBoundsThreeCornersClipped)
| TEST (RectTest, TransformAndClipBoundsAllFourCornersClipped)
| TEST (RoundRectTest, EmptyDeclaration)
| TEST (RoundRectTest, DefaultConstructor)
| TEST (RoundRectTest, EmptyRectConstruction)
| TEST (RoundRectTest, RectConstructor)
| TEST (RoundRectTest, InvertedRectConstruction)
| TEST (RoundRectTest, EmptyOvalConstruction)
| TEST (RoundRectTest, OvalConstructor)
| TEST (RoundRectTest, InvertedOvalConstruction)
| TEST (RoundRectTest, RectRadiusConstructor)
| TEST (RoundRectTest, RectXYConstructor)
| TEST (RoundRectTest, RectSizeConstructor)
| TEST (RoundRectTest, RectRadiiConstructor)
| TEST (RoundRectTest, RectRadiiOverflowWidthConstructor)
| TEST (RoundRectTest, RectRadiiOverflowHeightConstructor)
| TEST (RoundRectTest, Shift)
| TEST (RoundRectTest, ExpandScalar)
| TEST (RoundRectTest, ExpandTwoScalars)
| TEST (RoundRectTest, ExpandFourScalars)
| TEST (RoundRectTest, ContractScalar)
| TEST (RoundRectTest, ContractTwoScalars)
| TEST (RoundRectTest, ContractFourScalars)
| TEST (RoundRectTest, ContractAndRequireRadiiAdjustment)
| TEST (RoundRectTest, NoCornerRoundRectContains)
| TEST (RoundRectTest, TinyCornerRoundRectContains)
| TEST (RoundRectTest, UniformCircularRoundRectContains)
| TEST (RoundRectTest, UniformEllipticalRoundRectContains)
| TEST (RoundRectTest, DifferingCornersRoundRectContains)
| TEST (RoundSuperellipseTest, EmptyDeclaration)
| TEST (RoundSuperellipseTest, DefaultConstructor)
| TEST (RoundSuperellipseTest, EmptyRectConstruction)
| TEST (RoundSuperellipseTest, RectConstructor)
| TEST (RoundSuperellipseTest, InvertedRectConstruction)
| TEST (RoundSuperellipseTest, EmptyOvalConstruction)
| TEST (RoundSuperellipseTest, OvalConstructor)
| TEST (RoundSuperellipseTest, InvertedOvalConstruction)
| TEST (RoundSuperellipseTest, RectRadiusConstructor)
| TEST (RoundSuperellipseTest, RectXYConstructor)
| TEST (RoundSuperellipseTest, RectSizeConstructor)
| TEST (RoundSuperellipseTest, RectRadiiConstructor)
| TEST (RoundSuperellipseTest, RectRadiiOverflowWidthConstructor)
| TEST (RoundSuperellipseTest, RectRadiiOverflowHeightConstructor)
| TEST (RoundSuperellipseTest, Shift)
| TEST (RoundSuperellipseTest, ExpandScalar)
| TEST (RoundSuperellipseTest, ExpandTwoScalars)
| TEST (RoundSuperellipseTest, ExpandFourScalars)
| TEST (RoundSuperellipseTest, ContractScalar)
| TEST (RoundSuperellipseTest, ContractTwoScalars)
| TEST (RoundSuperellipseTest, ContractFourScalars)
| TEST (RoundSuperellipseTest, ContractAndRequireRadiiAdjustment)
| TEST (RoundSuperellipseTest, NoCornerRoundSuperellipseContains)
| TEST (RoundSuperellipseTest, TinyCornerContains)
| TEST (RoundSuperellipseTest, UniformSquareContains)
| TEST (RoundSuperellipseTest, UniformEllipticalContains)
| TEST (RoundSuperellipseTest, UniformRectangularContains)
| TEST (RoundSuperellipseTest, SlimDiagonalContains)
| TEST (RoundSuperellipseTest, PointsOutsideOfSharpCorner)
| TEST (RoundSuperellipseTest, PathForRectangularRseWithShapeCornersShouldBeWithinBounds)
| TEST (RoundSuperellipseTest, PathForLongRseShouldBeCorrect)
| TEST (RoudingRadiiTest, RoundingRadiiEmptyDeclaration)
| TEST (RoudingRadiiTest, RoundingRadiiDefaultConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiScalarConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiEmptyScalarConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiSizeConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiEmptySizeConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiNamedSizesConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiPartialNamedSizesConstructor)
| TEST (RoudingRadiiTest, RoundingRadiiMultiply)
| TEST (RoudingRadiiTest, RoundingRadiiEquals)
| TEST (RoudingRadiiTest, RoundingRadiiNotEquals)
| TEST (RoudingRadiiTest, RoundingRadiiCornersSameTolerance)
| TEST (RSTransformTest, Construction)
| TEST (RSTransformTest, CompareToMatrix)
| TEST (SaturatedMath, ExplicitAddOfSignedInts)
| TEST (SaturatedMath, ImplicitAddOfSignedInts)
| TEST (SaturatedMath, ExplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ExplicitSubOfSignedInts)
| TEST (SaturatedMath, ImplicitSubOfSignedInts)
| TEST (SaturatedMath, ExplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ImplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ExplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ImplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ExplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, CastingFiniteDoubleToFloatStaysFinite)
| TEST (SaturatedMath, CastingInfiniteDoubleToFloatStaysInfinite)
| TEST (SaturatedMath, CastingNaNDoubleToFloatStaysNaN)
| TEST (SaturatedMath, CastingLargeScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingInfiniteScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingNaNScalarToSignedIntProducesZero)
| TEST (SizeTest, SizeIsEmpty)
| TEST (SizeTest, ISizeIsEmpty)
| TEST (SizeTest, IsSquare)
| TEST (SizeTest, MaxDimension)
| TEST (SizeTest, NegationOperator)
| TEST (TrigTest, TrigAngles)
| TEST (TrigTest, MultiplyByScalarRadius)
| TEST (WangsFormulaTest, Cubic)
| TEST (WangsFormulaTest, Quadratic)
| TEST_F (GoldenTests, ConicalGradient)
| TEST (BlitCommandGLESTest, BlitCopyTextureToBufferCommandGLESBindsFramebuffer)
| FML_TEST_CLASS (BufferBindingsGLESTest, BindUniformData)
| FML_TEST_CLASS (BufferBindingsGLESTest, BindArrayData)
| TEST (BufferBindingsGLESTest, BindUniformData)
| TEST (BufferBindingsGLESTest, BindArrayData)
| TEST (DeviceBufferGLESTest, BindUniformData)
| TEST_P (RenderPassGLESWithDiscardFrameBufferExtTest, DiscardFramebufferExt)
| INSTANTIATE_TEST_SUITE_P (FrameBufferObject, RenderPassGLESWithDiscardFrameBufferExtTest, ::testing::ValuesIn(std::vector< DiscardFrameBufferParams >{ {.frame_buffer_id=0,.expected_attachments={GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT}}, {.frame_buffer_id=1,.expected_attachments={GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}}}), [](const ::testing::TestParamInfo< DiscardFrameBufferParams > &info) { return(info.param.frame_buffer_id==0) ? "Default" :"NonDefault";})
| TEST (UniqueHandleGLES, MakeUntracked)
| INSTANTIATE_METAL_PLAYGROUND_SUITE (AllocatorMTLTest)
| TEST_P (AllocatorMTLTest, DebugTraceMemoryStatistics)
| TEST_P (AllocatorMTLTest, ManagedMemory)
| TEST_P (ContextMTLTest, FlushTask)
| TEST_P (ContextMTLTest, FlushTaskWithGPULoss)
| TEST_P (SwapchainTransientsMTLTest, CanAllocateSwapchainTextures)
| TEST (AllocatorVKTest, ToVKImageUsageFlags)
| TEST (AllocatorVKTest, MemoryTypeSelectionSingleHeap)
| TEST (AllocatorVKTest, MemoryTypeSelectionTwoHeap)
| TEST (AllocatorVKTest, ImageResourceKeepsVulkanDeviceAlive)
| TEST (CommandEncoderVKTest, DeleteEncoderAfterThreadDies)
| TEST (CommandEncoderVKTest, CleanupAfterSubmit)
| TEST (CommandPoolRecyclerVKTest, GetsACommandPoolPerThread)
| TEST (CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread)
| TEST (CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable)
| TEST (CommandPoolRecyclerVKTest, CommandBuffersAreRecycled)
| TEST (CommandPoolRecyclerVKTest, ExtraCommandBufferAllocationsTriggerTrim)
| TEST (CommandPoolRecyclerVKTest, RecyclerGlobalPoolMapSize)
| TEST (ContextVKTest, CommonHardwareConcurrencyConfigurations)
| TEST (ContextVKTest, DeletesCommandPools)
| TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
| TEST (ContextVKTest, ThreadLocalCleanupDeletesCommandPool)
| TEST (ContextVKTest, DeletePipelineAfterContext)
| TEST (ContextVKTest, DeleteShaderFunctionAfterContext)
| TEST (ContextVKTest, DeletePipelineLibraryAfterContext)
| TEST (ContextVKTest, CanCreateContextInAbsenceOfValidationLayers)
| TEST (ContextVKTest, CanCreateContextWithValidationLayers)
| TEST (CapabilitiesVKTest, ContextInitializesWithNoStencilFormat)
| TEST (CapabilitiesVKTest, ContextFailsInitializationForNoCombinedDepthStencilFormat)
| TEST (ContextVKTest, WarmUpFunctionCreatesRenderPass)
| TEST (ContextVKTest, FatalMissingValidations)
| TEST (ContextVKTest, HasDefaultColorFormat)
| TEST (ContextVKTest, EmbedderOverridesUsesInstanceExtensions)
| TEST (ContextVKTest, EmbedderOverrides)
| TEST (ContextVKTest, BatchSubmitCommandBuffersOnArm)
| TEST (ContextVKTest, BatchSubmitCommandBuffersOnNonArm)
| TEST (ContextVKTest, AHBSwapchainCapabilitiesCanBeMissing)
| TEST (ContextVKTest, HashIsUniqueAcrossThreads)
| TEST (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
| TEST (DescriptorPoolRecyclerVKTest, MultipleCommandBuffersShareDescriptorPool)
| TEST (DescriptorPoolRecyclerVKTest, DescriptorsAreRecycled)
| INSTANTIATE_VULKAN_PLAYGROUND_SUITE (DriverInfoVKTest)
| TEST_P (DriverInfoVKTest, CanQueryDriverInfo)
| TEST_P (DriverInfoVKTest, CanDumpToLog)
| TEST (DriverInfoVKTest, CanIdentifyBadMaleoonDriver)
bool | IsBadVersionTest (std::string_view driver_name, bool qc=true)
bool | CanBatchSubmitTest (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanBatchSubmitCommandBuffers)
bool | CanUsePrimitiveRestartSubmitTest (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanUsePrimitiveRestart)
bool | CanUseMipgeneration (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanGenerateMipMaps)
| TEST (DriverInfoVKTest, DriverParsingMali)
| TEST (DriverInfoVKTest, DriverParsingAdreno)
| TEST (DriverInfoVKTest, DisabledDevices)
| TEST (DriverInfoVKTest, EnabledDevicesMali)
| TEST (DriverInfoVKTest, EnabledDevicesAdreno)
bool | CanUseFramebufferFetch (std::string_view driver_name, bool qc=true)
| TEST (DriverInfoVKTest, CanUseFramebufferFetch)
| TEST (DriverInfoVKTest, DisableOldXclipseDriver)
| TEST (DriverInfoVKTest, OldPowerVRDisabled)
| TEST (DriverInfoVKTest, NewPowerVREnabled)
| TEST (DriverInfoVKTest, PowerVRBSeries)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (FormatsVKTest, DescriptorMapping)
| TEST (PipelineCacheDataVKTest, CanTestHeaderCompatibility)
| TEST (PipelineCacheDataVKTest, CanCreateFromDeviceProperties)
| TEST (PipelineCacheDataVKTest, WritesIncompleteCacheData)
| TEST_P (PipelineCacheDataVKPlaygroundTest, CanPersistAndRetrievePipelineCache)
| TEST_P (PipelineCacheDataVKPlaygroundTest, IntegrityChecksArePerformedOnPersistedData)
| TEST (RenderPassBuilder, CreatesRenderPassWithNoDepthStencil)
| TEST (RenderPassBuilder, RenderPassWithLoadOpUsesCurrentLayout)
| TEST (RenderPassBuilder, CreatesRenderPassWithCombinedDepthStencil)
| TEST (RenderPassBuilder, CreatesRenderPassWithOnlyStencil)
| TEST (RenderPassBuilder, CreatesMSAAResolveWithCorrectStore)
| TEST_P (RendererTest, CachesRenderPassAndFramebuffer)
| TEST_P (RendererTest, CachesRenderPassAndFramebufferNonMSAA)
| TEST_P (RendererTest, CachesRenderPassAndFramebufferMixed)
| TEST (RenderPassVK, DoesNotRedundantlySetStencil)
| TEST (ResourceManagerVKTest, CreatesANewInstance)
| TEST (ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt)
| TEST (ResourceManagerVKTest, TerminatesWhenOutOfScope)
| TEST (ResourceManagerVKTest, IsThreadSafe)
| TEST (SurfaceContextVK, TearsDownSwapchain)
| TEST_P (BlitPassTest, BlitAcrossDifferentPixelFormatsFails)
| TEST_P (BlitPassTest, BlitAcrossDifferentSampleCountsFails)
| TEST_P (BlitPassTest, BlitPassesForMatchingFormats)
| TEST_P (BlitPassTest, ChecksInvalidSliceParameters)
| TEST_P (BlitPassTest, CanBlitSmallRegionToUninitializedTexture)
| TEST_P (BlitPassTest, ChecksInvalidMipLevelParameter)
| TEST_P (BlitPassTest, CanBlitToHigherTextureMipLevels)
| TEST_P (BlitPassTest, CanResizeTextures)
| TEST_P (BlitPassTest, CanResizeTexturesPlayground)
| CAPABILITY_TEST (SupportsOffscreenMSAA, false)
| CAPABILITY_TEST (SupportsSSBO, false)
| CAPABILITY_TEST (SupportsTextureToTextureBlits, false)
| CAPABILITY_TEST (SupportsFramebufferFetch, false)
| CAPABILITY_TEST (SupportsCompute, false)
| CAPABILITY_TEST (SupportsComputeSubgroups, false)
| CAPABILITY_TEST (SupportsReadFromResolve, false)
| CAPABILITY_TEST (SupportsDecalSamplerAddressMode, false)
| CAPABILITY_TEST (SupportsDeviceTransientTextures, false)
| CAPABILITY_TEST (SupportsTriangleFan, false)
| CAPABILITY_TEST (SupportsExtendedRangeFormats, false)
| CAPABILITY_TEST (NeedsPartitionedHostBuffer, false)
| TEST (CapabilitiesTest, DefaultColorFormat)
| TEST (CapabilitiesTest, DefaultStencilFormat)
| TEST (CapabilitiesTest, DefaultDepthStencilFormat)
| TEST (CapabilitiesTest, DefaultGlyphAtlasFormat)
| TEST (CapabilitiesTest, MaxRenderPassAttachmentSize)
| TEST (CapabilitiesTest, MinUniformAlignment)
| INSTANTIATE_COMPUTE_SUITE (ComputeTest)
| TEST_P (ComputeTest, CapabilitiesReportSupport)
| TEST_P (ComputeTest, CanCreateComputePass)
| TEST_P (ComputeTest, CanComputePrefixSum)
| TEST_P (ComputeTest, 1DThreadgroupSizingIsCorrect)
| TEST_P (ComputeTest, CanComputePrefixSumLargeInteractive)
| TEST_P (ComputeTest, MultiStageInputAndOutput)
| TEST_P (ComputeTest, CanCompute1DimensionalData)
| TEST_P (ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero)
| TEST (PipelineDescriptorTest, PrimitiveTypeHashEquality)
| TEST (MockPipelineLibrary, LogAndGetPipelineUsageSinglePipeline)
| TEST (MockPipelineLibrary, LogAndGetPipelineUsageMultiplePipelines)
| TEST (PoolTest, Simple)
| TEST (PoolTest, Overload)
static void | InstantiateTestShaderLibrary (Context::BackendType backend_type)
| INSTANTIATE_PLAYGROUND_SUITE (RendererDartTest)
| TEST_P (RendererDartTest, CanRunDartInPlaygroundFrame)
| TEST_P (RendererDartTest, CanInstantiateFlutterGPUContext)
| TEST_P (RendererDartTest, CanCreateShaderLibrary)
| TEST_P (RendererDartTest, CanReflectUniformStructs)
| TEST_P (RendererDartTest, CanCreateRenderPassAndSubmit)
| TEST_P (RendererTest, CanCreateBoxPrimitive)
| TEST_P (RendererTest, BabysFirstTriangle)
| TEST_P (RendererTest, CanRenderPerspectiveCube)
| TEST_P (RendererTest, CanRenderMultiplePrimitives)
| TEST_P (RendererTest, CanRenderToTexture)
| TEST_P (RendererTest, CanRenderInstanced)
| TEST_P (RendererTest, CanBlitTextureToTexture)
| TEST_P (RendererTest, CanBlitTextureToBuffer)
| TEST_P (RendererTest, CanGenerateMipmaps)
| TEST_P (RendererTest, TheImpeller)
| TEST_P (RendererTest, Planet)
| TEST_P (RendererTest, ArrayUniforms)
| TEST_P (RendererTest, InactiveUniforms)
| TEST_P (RendererTest, DefaultIndexSize)
| TEST_P (RendererTest, DefaultIndexBehavior)
| TEST_P (RendererTest, VertexBufferBuilder)
static const CompareFunctionUIData & | CompareFunctionUI ()
| TEST_P (RendererTest, StencilMask)
| TEST_P (RendererTest, CanLookupRenderTargetProperties)
| TEST_P (RendererTest, RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat)
template<class VertexShader , class FragmentShader >
std::shared_ptr< Pipeline< PipelineDescriptor > > | CreateDefaultPipeline (const std::shared_ptr< Context > &context)
| TEST_P (RendererTest, CanSepiaToneWithSubpasses)
| TEST_P (RendererTest, CanSepiaToneThenSwizzleWithSubpasses)
| TEST_P (RendererTest, BindingNullTexturesDoesNotCrash)
| INSTANTIATE_PLAYGROUND_SUITE (RuntimeStageTest)
| TEST_P (RuntimeStageTest, CanReadValidBlob)
| TEST_P (RuntimeStageTest, RejectInvalidFormatVersion)
| TEST_P (RuntimeStageTest, CanRejectInvalidBlob)
| TEST_P (RuntimeStageTest, CanReadUniforms)
| TEST_P (RuntimeStageTest, CanReadUniformsSamplerBeforeUBO)
| TEST_P (RuntimeStageTest, CanReadUniformsSamplerAfterUBO)
| TEST_P (RuntimeStageTest, CanRegisterStage)
| TEST_P (RuntimeStageTest, CanCreatePipelineFromRuntimeStage)
| TEST_P (RuntimeStageTest, ContainsExpectedShaderTypes)
static std::shared_ptr< fml::Mapping > | CreateMappingFromString (std::string p_string)
const std::string | CreateStringFromMapping (const fml::Mapping &mapping)
| TEST (ShaderArchiveTest, CanReadAndWriteBlobs)
| TEST (ShaderArchiveTest, ReturnsErrorOnInvalidVersion)
| TEST (PathTessellatorTest, EmptyPath)
| TEST (PathTessellatorTest, EmptyPathMultipleMoveTo)
| TEST (PathTessellatorTest, SimpleClosedPath)
| TEST (PathTessellatorTest, SimpleUnclosedPath)
| TEST (PathTessellatorTest, SimplePathTrailingMoveTo)
| TEST (PathTessellatorTest, DegenerateSegmentsPath)
| TEST (PathTessellatorTest, QuadToLineToOptimization)
| TEST (PathTessellatorTest, ConicToLineToOptimization)
| TEST (PathTessellatorTest, ConicToQuadToOptimization)
| TEST (PathTessellatorTest, SimplePathMultipleMoveTo)
| TEST (PathTessellatorTest, ComplexPath)
| TEST (PathTessellatorTest, ComplexPathTrailingMoveTo)
| TEST (PathTessellatorTest, LinearQuadToPointCount)
| TEST (PathTessellatorTest, LinearConicToPointCount)
| TEST (PathTessellatorTest, LinearCubicToPointCount)
template<typename T >
std::vector< T > | CopyBufferView (const BufferView &vertex_buffer)
| TEST_P (TessellatorPlaygroundTest, TessellateConvex16or32Bit)
| TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
| TEST (TessellatorTest, TessellateConvex)
| TEST (TessellatorTest, TessellateConvexUnclosedPath)
| TEST (TessellatorTest, CircleVertexCounts)
| TEST (TessellatorTest, FilledCircleTessellationVertices)
| TEST (TessellatorTest, StrokedCircleTessellationVertices)
| TEST (TessellatorTest, FilledArcStripTessellationVertices)
| TEST (TessellatorTest, RoundCapLineTessellationVertices)
| TEST (TessellatorTest, FilledEllipseTessellationVertices)
| TEST (TessellatorTest, FilledRoundRectTessellationVertices)
| TEST (TessellatorTest, EarlyReturnEmptyConvexShape)
static std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, HostBuffer &data_host_buffer, GlyphAtlas::Type type, Rational scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::shared_ptr< TextFrame > &frame)
static std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, HostBuffer &data_host_buffer, GlyphAtlas::Type type, Rational scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< std::shared_ptr< TextFrame >> &frames, const std::vector< std::optional< GlyphProperties >> &properties)
| TEST_P (TypographerTest, CanConvertTextBlob)
| TEST_P (TypographerTest, CanCreateRenderContext)
| TEST_P (TypographerTest, CanCreateGlyphAtlas)
| TEST_P (TypographerTest, LazyAtlasTracksColor)
| TEST_P (TypographerTest, GlyphAtlasWithOddUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphColorIsPartOfCacheKey)
| TEST_P (TypographerTest, GlyphColorIsIgnoredForNonEmojiFonts)
| TEST_P (TypographerTest, RectanglePackerAddsNonoverlapingRectangles)
| TEST (TypographerTest, RectanglePackerFillsRows)
| TEST_P (TypographerTest, GlyphAtlasTextureWillGrowTilMaxTextureSize)
| TEST_P (TypographerTest, TextFrameInitialBoundsArePlaceholder)
| TEST_P (TypographerTest, TextFrameInvalidationWithScale)
| TEST_P (TypographerTest, TextFrameAtlasGenerationTracksState)
| TEST_P (TypographerTest, InvalidAtlasForcesRepopulation)

## Variables
static const std::map< std::string, MaskBlurTestConfig > | kPaintVariations
static constexpr std::string_view | kFontFixture
static constexpr const size_t | kMagicFailingAllocation = 1024000 * 2
std::vector< Point > | golden_cubic_and_quad_points

## Typedef Documentation

## ◆ AiksTest

using impeller::testing::AiksTest = typedef AiksPlayground

Definition at line 17 of file aiks_unittests.h.

## ◆ AllocatorMTLTest

using impeller::testing::AllocatorMTLTest = typedef PlaygroundTest

Definition at line 25 of file allocator_mtl_unittests.mm.

## ◆ BlitPassTest

using impeller::testing::BlitPassTest = typedef AiksTest

Definition at line 27 of file blit_pass_unittests.cc.

## ◆ ComputeTest

using impeller::testing::ComputeTest = typedef ComputePlaygroundTest

Definition at line 30 of file compute_unittests.cc.

## ◆ ContextMTLTest

using impeller::testing::ContextMTLTest = typedef PlaygroundTest

Definition at line 25 of file context_mtl_unittests.mm.

## ◆ DeviceBufferTest

using impeller::testing::DeviceBufferTest = typedef Playground

Definition at line 12 of file device_buffer_unittests.cc.

## ◆ DisplayListTest

using impeller::testing::DisplayListTest = typedef DlPlayground

Definition at line 44 of file dl_unittests.cc.

## ◆ DriverInfoVKTest

using impeller::testing::DriverInfoVKTest = typedef PlaygroundTest

Definition at line 14 of file driver_info_vk_unittests.cc.

## ◆ EntityPassTargetTest

using impeller::testing::EntityPassTargetTest = typedef EntityPlayground

Definition at line 16 of file entity_pass_target_unittests.cc.

## ◆ EntityTest

typedef EntityPlayground impeller::testing::EntityTest

Definition at line 19 of file tiled_texture_contents_unittests.cc.

## ◆ HostBufferTest

using impeller::testing::HostBufferTest = typedef EntityPlayground

Definition at line 24 of file host_buffer_unittests.cc.

## ◆ PipelineCacheDataVKPlaygroundTest

using impeller::testing::PipelineCacheDataVKPlaygroundTest = typedef PlaygroundTest

Definition at line 114 of file pipeline_cache_data_vk_unittests.cc.

## ◆ RendererTest

typedef PlaygroundTest impeller::testing::RendererTest

Definition at line 15 of file render_pass_cache_unittests.cc.

## ◆ RenderTargetCacheTest

using impeller::testing::RenderTargetCacheTest = typedef EntityPlayground

Definition at line 20 of file render_target_cache_unittests.cc.

## ◆ RuntimeStageTest

using impeller::testing::RuntimeStageTest = typedef RuntimeStagePlayground

Definition at line 30 of file runtime_stage_unittests.cc.

## ◆ SaveLayerUtilsTest

using impeller::testing::SaveLayerUtilsTest = typedef ::testing::Test

Definition at line 15 of file save_layer_utils_unittests.cc.

## ◆ SwapchainTransientsMTLTest

using impeller::testing::SwapchainTransientsMTLTest = typedef PlaygroundTest

Definition at line 24 of file swapchain_transients_mtl_unittests.mm.

## ◆ TessellatorPlaygroundTest

using impeller::testing::TessellatorPlaygroundTest = typedef PlaygroundTest

Definition at line 15 of file tessellator_playground_unittests.cc.

## ◆ TextContentsTest

using impeller::testing::TextContentsTest = typedef PlaygroundTest

Definition at line 20 of file text_contents_unittests.cc.

## ◆ TypographerTest

using impeller::testing::TypographerTest = typedef PlaygroundTest

Definition at line 29 of file typographer_unittests.cc.

## Function Documentation

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [1/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Conical |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [2/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Linear |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [3/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Radial |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [4/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Sweep |  | ) |

## ◆ BlendModeTest()

static sk_sp<DisplayList> impeller::testing::BlendModeTest | ( | Vector2 | content_scale,
|  | BlendMode | blend_mode,
|  | const sk_sp< DlImageImpeller > & | src_image,
|  | const sk_sp< DlImageImpeller > & | dst_image,
|  | Scalar | src_alpha
| ) |  |
| static

1. Save layer blending (top squares).
2. CPU blend modes (bottom squares).
3. Image blending (bottom images).

Compare these results with the images in the Flutter blend mode documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html

Definition at line 500 of file aiks_dl_blend_unittests.cc.

504 {
505 if (AiksTest::ImGuiBegin("Controls", nullptr,
506 ImGuiWindowFlags_AlwaysAutoResize)) {
507 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
508 ImGui::End();
509 }
510
511 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
512 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
513 Color::LimeGreen().WithAlpha(0.75),
514 Color::Black().WithAlpha(0.75)});
515
516 DisplayListBuilder builder;
517 {
518 DlPaint paint;
519 paint.setColor(DlColor::kBlack());
520 builder.DrawPaint(paint);
521 }
522 // TODO(bdero): Why does this cause the left image to double scale on high DPI
523 // displays.
524 // builder.Scale(content_scale);
525
526 //----------------------------------------------------------------------------
527 /// 1. Save layer blending (top squares).
528 ///
529
530 builder.Save();
531 for (const auto& color : source_colors) {
532 builder.Save();
533 {
534 builder.ClipRect(DlRect::MakeXYWH(25, 25, 100, 100));
535 // Perform the blend in a SaveLayer so that the initial backdrop color is
536 // fully transparent black. SourceOver blend the result onto the parent
537 // pass.
538 builder.SaveLayer(std::nullopt);
539 {
540 DlPaint draw_paint;
541 draw_paint.setColor(
542 DlColor::RGBA(destination_color.red, destination_color.green,
543 destination_color.blue, destination_color.alpha));
544 builder.DrawPaint(draw_paint);
545
546 // Draw the source color in an offscreen pass and blend it to the parent
547 // pass.
548 DlPaint save_paint;
549 save_paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
550 builder.SaveLayer(std::nullopt, &save_paint);
551 { //
552 DlPaint paint;
553 paint.setColor(
554 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
555 builder.DrawRect(DlRect::MakeXYWH(25, 25, 100, 100), paint);
556 }
557 builder.Restore();
558 }
559 builder.Restore();
560 }
561 builder.Restore();
562 builder.Translate(100, 0);
563 }
564 builder.RestoreToCount(0);
565
566 //----------------------------------------------------------------------------
567 /// 2. CPU blend modes (bottom squares).
568 ///
569
570 builder.Save();
571 builder.Translate(0, 100);
572 // Perform the blend in a SaveLayer so that the initial backdrop color is
573 // fully transparent black. SourceOver blend the result onto the parent pass.
574 builder.SaveLayer(std::nullopt);
575 for (const auto& color : source_colors) {
576 // Simply write the CPU blended color to the pass.
577 DlPaint paint;
578 auto dest = destination_color.Blend(color, blend_mode);
579 paint.setColor(DlColor::RGBA(dest.red, dest.green, dest.blue, dest.alpha));
580 paint.setBlendMode(DlBlendMode::kSrcOver);
581 builder.DrawRect(DlRect::MakeXYWH(25, 25, 100, 100), paint);
582 builder.Translate(100, 0);
583 }
584 builder.Restore();
585 builder.Restore();
586
587 //----------------------------------------------------------------------------
588 /// 3. Image blending (bottom images).
589 ///
590 /// Compare these results with the images in the Flutter blend mode
591 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
592 ///
593
594 builder.Translate(0, 250);
595
596 // Draw grid behind the images.
597 {
598 DlPaint paint;
599 paint.setColor(DlColor::RGBA(41 / 255.0, 41 / 255.0, 41 / 255.0, 1));
600 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 400), paint);
601 }
602
603 DlPaint square_paint;
604 square_paint.setColor(DlColor::RGBA(15 / 255.0, 15 / 255.0, 15 / 255.0, 1));
605 for (int y = 0; y < 400 / 8; y++) {
606 for (int x = 0; x < 800 / 16; x++) {
607 builder.DrawRect(DlRect::MakeXYWH(x * 16 + (y % 2) * 8, y * 8, 8, 8),
608 square_paint);
609 }
610 }
611
612 // Uploaded image source (left image).
613 DlPaint paint;
614 paint.setBlendMode(DlBlendMode::kSrcOver);
615 builder.Save();
616 builder.SaveLayer(std::nullopt, &paint);
617 {
618 builder.DrawImage(dst_image, DlPoint(0, 0), DlImageSampling::kMipmapLinear,
619 &paint);
620
621 paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
622 paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
623 builder.DrawImage(src_image, DlPoint(0, 0), DlImageSampling::kMipmapLinear,
624 &paint);
625 }
626 builder.Restore();
627 builder.Restore();
628
629 // Rendered image source (right image).
630 builder.Save();
631
632 DlPaint save_paint;
633 builder.SaveLayer(std::nullopt, &save_paint);
634 {
635 builder.DrawImage(dst_image, DlPoint(400, 0),
636 DlImageSampling::kMipmapLinear, nullptr);
637
638 DlPaint save_paint;
639 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
640 save_paint.setBlendMode(static_cast<DlBlendMode>(blend_mode));
641 builder.SaveLayer(std::nullopt, &save_paint);
642 {
643 builder.DrawImage(src_image, DlPoint(400, 0),
644 DlImageSampling::kMipmapLinear, nullptr);
645 }
646 builder.Restore();
647 }
648 builder.Restore();
649 builder.Restore();
650
651 return builder.Build();
652 }
x
int32_t x
Definition: dl_golden_unittests.cc:458
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24

References impeller::Color::alpha, impeller::Color::Black(), impeller::Color::Blend(), impeller::Color::blue, impeller::Color::CornflowerBlue(), impeller::Color::green, impeller::AiksPlayground::ImGuiBegin(), impeller::Color::LimeGreen(), impeller::Color::red, impeller::Color::White(), impeller::Color::WithAlpha(), and x.

## ◆ CanBatchSubmitTest()

bool impeller::testing::CanBatchSubmitTest | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 71 of file driver_info_vk_unittests.cc.

71 {
72 auto const context =
73 MockVulkanContextBuilder()
74 .SetPhysicalPropertiesCallback(
75 [&driver_name, qc](VkPhysicalDevice device,
76 VkPhysicalDeviceProperties* prop) {
77 if (qc) {
78 prop->vendorID = 0x168C; // Qualcomm
79 } else {
80 prop->vendorID = 0x13B5; // ARM
81 }
82 driver_name.copy(prop->deviceName, driver_name.size());
83 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
84 })
85 .Build();
86 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
87 .batch_submit_command_buffer_timeout;
88 }
impeller::GetWorkaroundsFromDriverInfo
WorkaroundsVK GetWorkaroundsFromDriverInfo(DriverInfoVK &driver_info)
Definition: workarounds_vk.cc:10
impeller::WorkaroundsVK::batch_submit_command_buffer_timeout
bool batch_submit_command_buffer_timeout
Definition: workarounds_vk.h:24

References impeller::WorkaroundsVK::batch_submit_command_buffer_timeout, and impeller::GetWorkaroundsFromDriverInfo().

Referenced by TEST().

## ◆ CanRenderConicalGradientWithDithering()

static void impeller::testing::CanRenderConicalGradientWithDithering | ( | AiksTest * | aiks_test | ) |
| static

Definition at line 155 of file aiks_dl_gradient_unittests.cc.

155 {
156 DisplayListBuilder builder;
157 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
158 DlPaint paint;
159 builder.Translate(100.0, 100.0);
160
161 // #FFF -> #000
162 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
163 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
164 std::vector<Scalar> stops = {0.0, 1.0};
165
166 paint.setColorSource(DlColorSource::MakeConical({0, 1}, 0, {100, 100}, 100, 2,
167 colors.data(), stops.data(),
168 DlTileMode::kMirror));
169
170 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
171 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
172 }

References impeller::Playground::GetContentScale(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ CanRenderLinearGradientWithDithering()

static void impeller::testing::CanRenderLinearGradientWithDithering | ( | AiksTest * | aiks_test | ) |
| static

Definition at line 92 of file aiks_dl_gradient_unittests.cc.

92 {
93 DisplayListBuilder builder;
94 DlPaint paint;
95 builder.Translate(100.0, 100.0);
96
97 // 0xffcccccc --> 0xff333333, taken from
98 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
99 std::vector<DlColor> colors = {DlColor(0xFFCCCCCC), DlColor(0xFF333333)};
100 std::vector<Scalar> stops = {0.0, 1.0};
101
102 paint.setColorSource(DlColorSource::MakeLinear(
103 {0, 0}, {800, 500}, 2, colors.data(), stops.data(), DlTileMode::kClamp));
104 builder.DrawRect(DlRect::MakeXYWH(0, 0, 800, 500), paint);
105 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
106 }

References impeller::AiksPlayground::OpenPlaygroundHere().

Referenced by TEST_P().

## ◆ CanRenderRadialGradientWithDithering()

static void impeller::testing::CanRenderRadialGradientWithDithering | ( | AiksTest * | aiks_test | ) |
| static

Definition at line 112 of file aiks_dl_gradient_unittests.cc.

112 {
113 DisplayListBuilder builder;
114 DlPaint paint;
115 builder.Translate(100.0, 100.0);
116
117 // #FFF -> #000
118 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
119 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
120 std::vector<Scalar> stops = {0.0, 1.0};
121
122 paint.setColorSource(DlColorSource::MakeRadial(
123 {600, 600}, 600, 2, colors.data(), stops.data(), DlTileMode::kClamp));
124 builder.DrawRect(DlRect::MakeXYWH(0, 0, 1200, 1200), paint);
125 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
126 }

References impeller::AiksPlayground::OpenPlaygroundHere(), and impeller::Color::ToARGB().

Referenced by TEST_P().

## ◆ CanRenderSweepGradientWithDithering()

static void impeller::testing::CanRenderSweepGradientWithDithering | ( | AiksTest * | aiks_test | ) |
| static

Definition at line 132 of file aiks_dl_gradient_unittests.cc.

132 {
133 DisplayListBuilder builder;
134 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
135 DlPaint paint;
136 builder.Translate(100.0, 100.0);
137
138 // #FFF -> #000
139 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
140 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
141 std::vector<Scalar> stops = {0.0, 1.0};
142
143 paint.setColorSource(DlColorSource::MakeSweep(
144 {100, 100}, /*start=*/45, /*end=*/135, 2, colors.data(), stops.data(),
145 DlTileMode::kMirror));
146
147 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
148 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
149 }

References impeller::Playground::GetContentScale(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ CanUseFramebufferFetch()

bool impeller::testing::CanUseFramebufferFetch | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 197 of file driver_info_vk_unittests.cc.

197 {
198 auto const context =
199 MockVulkanContextBuilder()
200 .SetPhysicalPropertiesCallback(
201 [&driver_name, qc](VkPhysicalDevice device,
202 VkPhysicalDeviceProperties* prop) {
203 if (qc) {
204 prop->vendorID = 0x168C; // Qualcomm
205 } else {
206 prop->vendorID = 0x13B5; // ARM
207 }
208 driver_name.copy(prop->deviceName, driver_name.size());
209 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
210 })
211 .Build();
212 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
213 .input_attachment_self_dependency_broken;
214 }
impeller::WorkaroundsVK::input_attachment_self_dependency_broken
bool input_attachment_self_dependency_broken
Definition: workarounds_vk.h:30

References impeller::GetWorkaroundsFromDriverInfo(), and impeller::WorkaroundsVK::input_attachment_self_dependency_broken.

Referenced by TEST().

## ◆ CanUseMipgeneration()

bool impeller::testing::CanUseMipgeneration | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 127 of file driver_info_vk_unittests.cc.

127 {
128 auto const context =
129 MockVulkanContextBuilder()
130 .SetPhysicalPropertiesCallback(
131 [&driver_name, qc](VkPhysicalDevice device,
132 VkPhysicalDeviceProperties* prop) {
133 if (qc) {
134 prop->vendorID = 0x168C; // Qualcomm
135 } else {
136 prop->vendorID = 0x13B5; // ARM
137 }
138 driver_name.copy(prop->deviceName, driver_name.size());
139 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
140 })
141 .Build();
142 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
143 .broken_mipmap_generation;
144 }
impeller::WorkaroundsVK::broken_mipmap_generation
bool broken_mipmap_generation
Definition: workarounds_vk.h:38

References impeller::WorkaroundsVK::broken_mipmap_generation, and impeller::GetWorkaroundsFromDriverInfo().

Referenced by TEST().

## ◆ CanUsePrimitiveRestartSubmitTest()

bool impeller::testing::CanUsePrimitiveRestartSubmitTest | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 98 of file driver_info_vk_unittests.cc.

99 {
100 auto const context =
101 MockVulkanContextBuilder()
102 .SetPhysicalPropertiesCallback(
103 [&driver_name, qc](VkPhysicalDevice device,
104 VkPhysicalDeviceProperties* prop) {
105 if (qc) {
106 prop->vendorID = 0x168C; // Qualcomm
107 } else {
108 prop->vendorID = 0x13B5; // ARM
109 }
110 driver_name.copy(prop->deviceName, driver_name.size());
111 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
112 })
113 .Build();
114 return !GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
115 .slow_primitive_restart_performance;
116 }
impeller::WorkaroundsVK::slow_primitive_restart_performance
bool slow_primitive_restart_performance
Definition: workarounds_vk.h:18

References impeller::GetWorkaroundsFromDriverInfo(), and impeller::WorkaroundsVK::slow_primitive_restart_performance.

Referenced by TEST().

## ◆ CAPABILITY_TEST() [1/12]

impeller::testing::CAPABILITY_TEST | ( | NeedsPartitionedHostBuffer | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [2/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsCompute | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [3/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsComputeSubgroups | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [4/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsDecalSamplerAddressMode | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [5/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsDeviceTransientTextures | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [6/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsExtendedRangeFormats | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [7/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsFramebufferFetch | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [8/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsOffscreenMSAA | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [9/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsReadFromResolve | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [10/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsSSBO | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [11/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsTextureToTextureBlits | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [12/12]

impeller::testing::CAPABILITY_TEST | ( | SupportsTriangleFan | ,
|  | false |
| ) |  |

## ◆ CompareFunctionUI()

static const CompareFunctionUIData& impeller::testing::CompareFunctionUI | ( |  | ) |
| static

Definition at line 1212 of file renderer_unittests.cc.

1212 {
1213 static CompareFunctionUIData data;
1214 return data;
1215 }
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:69

References data.

Referenced by TEST_P().

## ◆ CopyBufferView()

template<typename T >

std::vector<T> impeller::testing::CopyBufferView | ( | const BufferView & | vertex_buffer | ) |

Definition at line 19 of file tessellator_playground_unittests.cc.

19 {
20 Range range = vertex_buffer.GetRange();
21 uint8_t* base_ptr = vertex_buffer.GetBuffer()->OnGetContents() + range.offset;
22 return std::vector<T>(reinterpret_cast<T*>(base_ptr),
23 reinterpret_cast<T*>(base_ptr + range.length));
24 }

References impeller::BufferView::GetBuffer(), impeller::BufferView::GetRange(), impeller::Range::length, impeller::Range::offset, and impeller::DeviceBuffer::OnGetContents().

## ◆ CreateDefaultPipeline()

template<class VertexShader , class FragmentShader >

std::shared_ptr<Pipeline<PipelineDescriptor> > impeller::testing::CreateDefaultPipeline | ( | const std::shared_ptr< Context > & | context | ) |

Definition at line 1403 of file renderer_unittests.cc.

1404 {
1405 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1406 auto pipeline_desc =
1407 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1408 if (!pipeline_desc.has_value()) {
1409 return nullptr;
1410 }
1411 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1412 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1413 auto pipeline =
1414 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1415 if (!pipeline || !pipeline->IsValid()) {
1416 return nullptr;
1417 }
1418 return pipeline;
1419 }

References impeller::kCount4.

## ◆ CreateGlyphAtlas() [1/2]

static std::shared_ptr<GlyphAtlas> impeller::testing::CreateGlyphAtlas | ( | Context & | context,
|  | const TypographerContext * | typographer_context,
|  | HostBuffer & | data_host_buffer,
|  | GlyphAtlas::Type | type,
|  | Rational | scale,
|  | const std::shared_ptr< GlyphAtlasContext > & | atlas_context,
|  | const std::shared_ptr< TextFrame > & | frame
| ) |  |
| static

Definition at line 32 of file typographer_unittests.cc.

39 {
40 frame->SetPerFrameData(scale, {0, 0}, Matrix(), std::nullopt);
41 return typographer_context->CreateGlyphAtlas(context, type, data_host_buffer,
42 atlas_context, {frame});
43 }
type
GLenum type
Definition: blit_command_gles.cc:153

References impeller::TypographerContext::CreateGlyphAtlas(), and type.

Referenced by TEST_P().

## ◆ CreateGlyphAtlas() [2/2]

static std::shared_ptr<GlyphAtlas> impeller::testing::CreateGlyphAtlas | ( | Context & | context,
|  | const TypographerContext * | typographer_context,
|  | HostBuffer & | data_host_buffer,
|  | GlyphAtlas::Type | type,
|  | Rational | scale,
|  | const std::shared_ptr< GlyphAtlasContext > & | atlas_context,
|  | const std::vector< std::shared_ptr< TextFrame >> & | frames,
|  | const std::vector< std::optional< GlyphProperties >> & | properties
| ) |  |
| static

Definition at line 45 of file typographer_unittests.cc.

53 {
54 size_t offset = 0;
55 for (auto& frame : frames) {
56 frame->SetPerFrameData(scale, {0, 0}, Matrix(), properties[offset++]);
57 }
58 return typographer_context->CreateGlyphAtlas(context, type, data_host_buffer,
59 atlas_context, frames);
60 }

References impeller::TypographerContext::CreateGlyphAtlas(), and type.

## ◆ CreateMappingFromString()

static std::shared_ptr<fml::Mapping> impeller::testing::CreateMappingFromString | ( | std::string | p_string | ) |
| static

Definition at line 17 of file shader_archive_unittests.cc.

18 {
19 auto string = std::make_shared<std::string>(std::move(p_string));
20 return std::make_shared<fml::NonOwnedMapping>(
21 reinterpret_cast<const uint8_t*>(string->data()), string->size(),
22 [string](auto, auto) {});
23 }

Referenced by TEST().

## ◆ CreateStringFromMapping()

const std::string impeller::testing::CreateStringFromMapping | ( | const fml::Mapping & | mapping | ) |

Definition at line 25 of file shader_archive_unittests.cc.

25 {
26 return std::string{reinterpret_cast<const char*>(mapping.GetMapping()),
27 mapping.GetSize()};
28 }

Referenced by TEST().

## ◆ CreateTestCanvas()

std::unique_ptr<Canvas> impeller::testing::CreateTestCanvas | ( | ContentContext & | context,
|  | std::optional< Rect > | cull_rect = `std::nullopt`,
|  | bool | requires_readback = `false`
| ) |  |

Definition at line 27 of file canvas_unittests.cc.

30 {
31 TextureDescriptor onscreen_desc;
32 onscreen_desc.size = {100, 100};
33 onscreen_desc.format =
34 context.GetDeviceCapabilities().GetDefaultColorFormat();
35 onscreen_desc.usage = TextureUsage::kRenderTarget;
36 onscreen_desc.storage_mode = StorageMode::kDevicePrivate;
37 onscreen_desc.sample_count = SampleCount::kCount1;
38 std::shared_ptr<Texture> onscreen =
39 context.GetContext()->GetResourceAllocator()->CreateTexture(
40 onscreen_desc);
41
42 ColorAttachment color0;
43 color0.load_action = LoadAction::kClear;
44 if (context.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
45 TextureDescriptor onscreen_msaa_desc = onscreen_desc;
46 onscreen_msaa_desc.sample_count = SampleCount::kCount4;
47 onscreen_msaa_desc.storage_mode = StorageMode::kDeviceTransient;
48 onscreen_msaa_desc.type = TextureType::kTexture2DMultisample;
49
50 std::shared_ptr<Texture> onscreen_msaa =
51 context.GetContext()->GetResourceAllocator()->CreateTexture(
52 onscreen_msaa_desc);
53 color0.resolve_texture = onscreen;
54 color0.texture = onscreen_msaa;
55 color0.store_action = StoreAction::kMultisampleResolve;
56 } else {
57 color0.texture = onscreen;
58 }
59
60 RenderTarget render_target;
61 render_target.SetColorAttachment(color0, 0);
62
63 if (cull_rect.has_value()) {
64 return std::make_unique<Canvas>(
65 context, render_target, /*is_onscreen=*/false,
66 /*requires_readback=*/requires_readback, cull_rect.value());
67 }
68 return std::make_unique<Canvas>(context, render_target, /*is_onscreen=*/false,
69 /*requires_readback=*/requires_readback);
70 }

References impeller::TextureDescriptor::format, impeller::ContentContext::GetContext(), impeller::Capabilities::GetDefaultColorFormat(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kClear, impeller::kCount1, impeller::kCount4, impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kMultisampleResolve, impeller::kRenderTarget, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, impeller::TextureDescriptor::type, and impeller::TextureDescriptor::usage.

Referenced by TEST_P().

## ◆ CreateTestYUVTextures()

static std::vector<std::shared_ptr<Texture> > impeller::testing::CreateTestYUVTextures | ( | Context * | context,
|  | YUVColorSpace | yuv_color_space
| ) |  |
| static

Definition at line 1661 of file entity_unittests.cc.

1663 {
1664 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1665 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1666 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1667 Vector3 white = {1.0, 1.0, 1.0};
1668 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
1669 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
1670 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
1671 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
1672 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1673 std::vector<uint8_t> y_data;
1674 std::vector<uint8_t> uv_data;
1675 for (int i = 0; i < 4; i++) {
1676 auto yuv = yuvs[i];
1677 uint8_t y = std::round(yuv.x * 255.0);
1678 uint8_t u = std::round(yuv.y * 255.0);
1679 uint8_t v = std::round(yuv.z * 255.0);
1680 for (int j = 0; j < 16; j++) {
1681 y_data.push_back(y);
1682 }
1683 for (int j = 0; j < 8; j++) {
1684 uv_data.push_back(j % 2 == 0 ? u : v);
1685 }
1686 }
1687 auto cmd_buffer = context->CreateCommandBuffer();
1688 auto blit_pass = cmd_buffer->CreateBlitPass();
1689
1690 impeller::TextureDescriptor y_texture_descriptor;
1691 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1692 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
1693 y_texture_descriptor.size = {8, 8};
1694 auto y_texture =
1695 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
1696 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1697 auto y_mapping_buffer =
1698 context->GetResourceAllocator()->CreateBufferWithCopy(*y_mapping);
1699
1700 blit_pass->AddCopy(DeviceBuffer::AsBufferView(y_mapping_buffer), y_texture);
1701
1702 impeller::TextureDescriptor uv_texture_descriptor;
1703 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1704 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
1705 uv_texture_descriptor.size = {4, 4};
1706 auto uv_texture =
1707 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
1708 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1709 auto uv_mapping_buffer =
1710 context->GetResourceAllocator()->CreateBufferWithCopy(*uv_mapping);
1711
1712 blit_pass->AddCopy(DeviceBuffer::AsBufferView(uv_mapping_buffer), uv_texture);
1713
1714 if (!blit_pass->EncodeCommands() ||
1715 !context->GetCommandQueue()->Submit({cmd_buffer}).ok()) {
1716 FML_DLOG(ERROR) << "Could not copy contents into Y/UV texture.";
1717 }
1718
1719 return {y_texture, uv_texture};
1720 }
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1644
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41

References impeller::DeviceBuffer::AsBufferView(), impeller::Context::CreateCommandBuffer(), impeller::TextureDescriptor::format, impeller::Context::GetCommandQueue(), impeller::Context::GetResourceAllocator(), impeller::kHostVisible, impeller::kR8G8UNormInt, impeller::kR8UNormInt, RGBToYUV(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

Referenced by TEST_P().

## ◆ DoGradientOvalStrokeMaskBlur()

sk_sp<flutter::DisplayList> impeller::testing::DoGradientOvalStrokeMaskBlur | ( | Vector2 | content_Scale,
|  | Scalar | sigma,
|  | DlBlurStyle | style
| ) |  |

Definition at line 63 of file aiks_dl_blur_unittests.cc.

65 {
66 DisplayListBuilder builder;
67 builder.Scale(content_Scale.x, content_Scale.y);
68
69 DlPaint background_paint;
70 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
71 builder.DrawPaint(background_paint);
72
73 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
74 std::vector<Scalar> stops = {0.0, 1.0};
75
76 DlPaint paint;
77 paint.setMaskFilter(DlBlurMaskFilter::Make(style, sigma));
78 auto gradient = DlColorSource::MakeLinear(
79 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
80 paint.setColorSource(gradient);
81 paint.setColor(DlColor::kWhite());
82 paint.setDrawStyle(DlDrawStyle::kStroke);
83 paint.setStrokeWidth(20);
84
85 builder.Save();
86 builder.Translate(100, 100);
87
88 {
89 DlPaint line_paint;
90 line_paint.setColor(DlColor::kWhite());
91 builder.DrawLine(DlPoint(100, 0), DlPoint(100, 60), line_paint);
92 builder.DrawLine(DlPoint(0, 30), DlPoint(200, 30), line_paint);
93 }
94
95 DlRoundRect rrect =
96 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 200.0f, 60.0f), 50, 100);
97 builder.DrawRoundRect(rrect, paint);
98 builder.Restore();
99
100 return builder.Build();
101 }
impeller::DlRoundRect
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ flip_lr()

template<typename R >

static constexpr R impeller::testing::flip_lr | ( | R | rect | ) |
| inline static constexpr

Definition at line 1324 of file rect_unittests.cc.

1324 {
1325 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1326 rect.GetLeft(), rect.GetBottom());
1327 }

Referenced by flip_lrtb(), and TEST().

## ◆ flip_lrtb()

template<typename R >

static constexpr R impeller::testing::flip_lrtb | ( | R | rect | ) |
| inline static constexpr

Definition at line 1336 of file rect_unittests.cc.

1336 {
1337 return flip_lr(flip_tb(rect));
1338 }
impeller::testing::flip_tb
static constexpr R flip_tb(R rect)
Definition: rect_unittests.cc:1330
impeller::testing::flip_lr
static constexpr R flip_lr(R rect)
Definition: rect_unittests.cc:1324

References flip_lr(), and flip_tb().

Referenced by TEST().

## ◆ flip_tb()

template<typename R >

static constexpr R impeller::testing::flip_tb | ( | R | rect | ) |
| inline static constexpr

Definition at line 1330 of file rect_unittests.cc.

1330 {
1331 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1332 rect.GetRight(), rect.GetTop());
1333 }

Referenced by flip_lrtb(), and TEST().

## ◆ FML_TEST_CLASS() [1/2]

impeller::testing::FML_TEST_CLASS | ( | BufferBindingsGLESTest | ,
|  | BindArrayData |
| ) |  |

## ◆ FML_TEST_CLASS() [2/2]

impeller::testing::FML_TEST_CLASS | ( | BufferBindingsGLESTest | ,
|  | BindUniformData |
| ) |  |

## ◆ GetBlendModeSelection()

static BlendModeSelection impeller::testing::GetBlendModeSelection | ( |  | ) |
| static

Definition at line 44 of file aiks_dl_blend_unittests.cc.

44 {
45 std::vector<const char*> blend_mode_names;
46 std::vector<BlendMode> blend_mode_values;
47 {
48 const std::vector<std::tuple<const char*, BlendMode>> blends = {
49 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
50 assert(blends.size() ==
51 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
52 for (const auto& [name, mode] : blends) {
53 blend_mode_names.push_back(name);
54 blend_mode_values.push_back(mode);
55 }
56 }
57
58 return {blend_mode_names, blend_mode_values};
59 }
BLEND_MODE_TUPLE
#define BLEND_MODE_TUPLE(blend_mode)
Definition: aiks_dl_blend_unittests.cc:37
IMPELLER_FOR_EACH_BLEND_MODE
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition: color.h:19

References BLEND_MODE_TUPLE, IMPELLER_FOR_EACH_BLEND_MODE, and impeller::Entity::kLastAdvancedBlendMode.

Referenced by TEST_P().

## ◆ INSTANTIATE_COMPUTE_SUITE()

impeller::testing::INSTANTIATE_COMPUTE_SUITE | ( | ComputeTest |  | ) |

## ◆ INSTANTIATE_METAL_PLAYGROUND_SUITE()

impeller::testing::INSTANTIATE_METAL_PLAYGROUND_SUITE | ( | AllocatorMTLTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [1/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | AiksTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [2/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | BlendFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [3/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | DisplayListTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | GaussianBlurFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | HostBufferTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | MatrixFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [7/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | RendererDartTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [8/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | RuntimeStageTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [9/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | TextContentsTest |  | ) |

## ◆ INSTANTIATE_TEST_SUITE_P()

impeller::testing::INSTANTIATE_TEST_SUITE_P | ( | FrameBufferObject | ,
|  | RenderPassGLESWithDiscardFrameBufferExtTest | ,
|  | ::testing::ValuesIn(std::vector< DiscardFrameBufferParams >{ {.frame_buffer_id=0,.expected_attachments={GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT}}, {.frame_buffer_id=1,.expected_attachments={GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}}}) | ,
|  | [] (const ::testing::TestParamInfo< DiscardFrameBufferParams > &info) { return(info.param.frame_buffer_id==0) ? "Default" :"NonDefault";} |
| ) |  |

## ◆ INSTANTIATE_VULKAN_PLAYGROUND_SUITE()

impeller::testing::INSTANTIATE_VULKAN_PLAYGROUND_SUITE | ( | DriverInfoVKTest |  | ) |

## ◆ InstantiateTestShaderLibrary()

static void impeller::testing::InstantiateTestShaderLibrary | ( | Context::BackendType | backend_type | ) |
| static

Definition at line 34 of file renderer_dart_unittests.cc.

34 {
35 auto fixture =
36 flutter::testing::OpenFixtureAsMapping("playground.shaderbundle");
37 auto library = flutter::gpu::ShaderLibrary::MakeFromFlatbuffer(
38 backend_type, std::move(fixture));
39 flutter::gpu::ShaderLibrary::SetOverride(library);
40 }

Referenced by impeller::testing::RendererDartTest::GetIsolate().

## ◆ IsBadVersionTest()

bool impeller::testing::IsBadVersionTest | ( | std::string_view | driver_name,
|  | bool | qc = `true`
| ) |  |

Definition at line 53 of file driver_info_vk_unittests.cc.

53 {
54 auto const context =
55 MockVulkanContextBuilder()
56 .SetPhysicalPropertiesCallback(
57 [&driver_name, qc](VkPhysicalDevice device,
58 VkPhysicalDeviceProperties* prop) {
59 if (qc) {
60 prop->vendorID = 0x168C; // Qualcomm
61 } else {
62 prop->vendorID = 0x13B5; // ARM
63 }
64 driver_name.copy(prop->deviceName, driver_name.size());
65 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
66 })
67 .Build();
68 return context->GetDriverInfo()->IsKnownBadDriver();
69 }

Referenced by TEST().

## ◆ MaskBlurVariantTest()

static sk_sp<DisplayList> impeller::testing::MaskBlurVariantTest | ( | const AiksTest & | test_context,
|  | const MaskBlurTestConfig & | config
| ) |  |
| static

Definition at line 598 of file aiks_dl_blur_unittests.cc.

600 {
601 DisplayListBuilder builder;
602 builder.Scale(test_context.GetContentScale().x,
603 test_context.GetContentScale().y);
604 builder.Scale(0.8f, 0.8f);
605 builder.Translate(50.f, 50.f);
606
607 DlPaint draw_paint;
608 draw_paint.setColor(
609 DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
610 Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
611 builder.DrawPaint(draw_paint);
612
613 DlPaint paint;
614 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
615 paint.setInvertColors(config.invert_colors);
616 paint.setImageFilter(config.image_filter);
617 paint.setBlendMode(config.blend_mode);
618
619 const Scalar x = 50;
620 const Scalar radius = 20.0f;
621 const Scalar y_spacing = 100.0f;
622 Scalar alpha = config.alpha * 255;
623
624 Scalar y = 50;
625 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
626 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
627 radius, 60.0f - radius),
628 paint);
629
630 y += y_spacing;
631 paint.setColor(DlColor::kBlue().withAlpha(alpha));
632 builder.DrawCircle(DlPoint{x + 25, y + 25}, radius, paint);
633
634 y += y_spacing;
635 paint.setColor(DlColor::kGreen().withAlpha(alpha));
636 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
637 radius, 60.0f - radius),
638 paint);
639
640 y += y_spacing;
641 paint.setColor(DlColor::kPurple().withAlpha(alpha));
642 DlRoundRect rrect = DlRoundRect::MakeRectXY(
643 DlRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
644 builder.DrawRoundRect(rrect, paint);
645
646 y += y_spacing;
647 paint.setColor(DlColor::kOrange().withAlpha(alpha));
648
649 rrect = DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
650 radius, 5.0);
651 builder.DrawRoundRect(rrect, paint);
652
653 y += y_spacing;
654 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
655
656 {
657 DlPathBuilder path_builder;
658 path_builder.MoveTo(DlPoint(x + 0, y + 60));
659 path_builder.LineTo(DlPoint(x + 30, y + 0));
660 path_builder.LineTo(DlPoint(x + 60, y + 60));
661 path_builder.Close();
662
663 builder.DrawPath(path_builder.TakePath(), paint);
664 }
665
666 y += y_spacing;
667 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
668 {
669 DlPath path = DlPath::MakeArc(Rect::MakeXYWH(x + 5, y, 50, 50), //
670 Degrees(90), Degrees(180), false) +
671 DlPath::MakeArc(Rect::MakeXYWH(x + 25, y, 50, 50), //
672 Degrees(90), Degrees(180), false);
673 builder.DrawPath(path, paint);
674 }
675
676 return builder.Build();
677 }
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29

References impeller::testing::MaskBlurTestConfig::alpha, impeller::Color::AntiqueWhite(), impeller::testing::MaskBlurTestConfig::blend_mode, impeller::Playground::GetContentScale(), impeller::testing::MaskBlurTestConfig::image_filter, impeller::testing::MaskBlurTestConfig::invert_colors, impeller::TRect< Scalar >::MakeXYWH(), impeller::testing::MaskBlurTestConfig::sigma, impeller::testing::MaskBlurTestConfig::style, x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ RectMakeCenterSize()

Rect impeller::testing::RectMakeCenterSize | ( | Point | center,
|  | Size | size
| ) |  |

Definition at line 69 of file entity_unittests.cc.

69 {
70 return Rect::MakeSize(size).Shift(center - size / 2);
71 }

References impeller::TRect< Scalar >::MakeSize(), and impeller::TRect< T >::Shift().

Referenced by TEST_P().

## ◆ RenderTextInCanvasSkia()

bool impeller::testing::RenderTextInCanvasSkia | ( | const std::shared_ptr< Context > & | context,
|  | DisplayListBuilder & | canvas,
|  | const std::string & | text,
|  | const std::string_view & | font_fixture,
|  | const TextRenderOptions & | options = `{}`,
|  | const std::optional< SkFont > & | font = `std::nullopt`
| ) |  |

Definition at line 46 of file aiks_dl_text_unittests.cc.

50 {},
51 const std::optional<SkFont>& font = std::nullopt) {
52 // Draw the baseline.
53 DlPaint paint;
54 paint.setColor(DlColor::kAqua().withAlpha(255 * 0.25));
55 canvas.DrawRect(
56 DlRect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
57 paint);
58
59 // Mark the point at which the text is drawn.
60 paint.setColor(DlColor::kRed().withAlpha(255 * 0.25));
61 canvas.DrawCircle(options.position, 5.0, paint);
62
63 // Construct the text blob.
64 SkFont selected_font;
65 if (!font.has_value()) {
66 auto c_font_fixture = std::string(font_fixture);
67 auto mapping =
68 flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
69 if (!mapping) {
70 return false;
71 }
72 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
73 selected_font = SkFont(font_mgr->makeFromData(mapping), options.font_size);
74 if (options.is_subpixel) {
75 selected_font.setSubpixel(true);
76 }
77 } else {
78 selected_font = font.value();
79 }
80 auto blob = SkTextBlob::MakeFromString(text.c_str(), selected_font);
81 if (!blob) {
82 return false;
83 }
84
85 // Create the Impeller text frame and draw it at the designated baseline.
86 auto frame = MakeTextFrameFromTextBlobSkia(blob);
87
88 DlPaint text_paint;
89 text_paint.setColor(options.color);
90 text_paint.setMaskFilter(options.filter);
91 text_paint.setStrokeWidth(options.stroke_width);
92 text_paint.setDrawStyle(options.stroke ? DlDrawStyle::kStroke
93 : DlDrawStyle::kFill);
94 canvas.DrawText(DlTextImpeller::Make(frame), options.position.x,
95 options.position.y, text_paint);
96 return true;
97 }
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:45

Referenced by TEST_P(), and flutter::testing::TEST_P().

## ◆ RGBToYUV()

static Vector3 impeller::testing::RGBToYUV | ( | Vector3 | rgb,
|  | YUVColorSpace | yuv_color_space
| ) |  |
| static

Definition at line 1644 of file entity_unittests.cc.

1644 {
1645 Vector3 yuv;
1646 switch (yuv_color_space) {
1647 case YUVColorSpace::kBT601FullRange:
1648 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
1649 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
1650 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
1651 break;
1652 case YUVColorSpace::kBT601LimitedRange:
1653 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
1654 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
1655 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
1656 break;
1657 }
1658 return yuv;
1659 }

References impeller::kBT601FullRange, impeller::kBT601LimitedRange, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by CreateTestYUVTextures().

## ◆ swap_nan() [1/2]

static constexpr Point impeller::testing::swap_nan | ( | const Point & | point,
|  | int | index
| ) |  |
| inline static constexpr

Definition at line 1350 of file rect_unittests.cc.

1350 {
1351 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1352 FML_DCHECK(index >= 0 && index <= 3);
1353 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1354 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1355 return Point(x, y);
1356 }
impeller::Point
TPoint< Scalar > Point
Definition: point.h:425

References x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ swap_nan() [2/2]

static constexpr Rect impeller::testing::swap_nan | ( | const Rect & | rect,
|  | int | index
| ) |  |
| inline static constexpr

Definition at line 1340 of file rect_unittests.cc.

1340 {
1341 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1342 FML_DCHECK(index >= 0 && index <= 15);
1343 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1344 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1345 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1346 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1347 return Rect::MakeLTRB(l, t, r, b);
1348 }
impeller::saturated::b
SI b
Definition: saturated_math.h:87

References impeller::saturated::b, impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), and impeller::TRect< Scalar >::MakeLTRB().

Referenced by TEST().

## ◆ TEST() [1/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCast |
| ) |  |

Definition at line 77 of file allocation_size_unittests.cc.

77 {
78 using namespace allocation_size_literals;
79 {
80 auto a = KiloBytes{1500_bytes};
81 ASSERT_DOUBLE_EQ(a.GetSize(), 1.5);
82 }
83 {
84 auto a = KiloBytes{Bytes{1500}};
85 ASSERT_DOUBLE_EQ(a.GetSize(), 1.5);
86 }
87
88 ASSERT_DOUBLE_EQ(MebiBytes{Bytes{4194304}}.GetSize(), 4);
89 }
impeller::AllocationSize::GetSize
constexpr double GetSize() const
Definition: allocation_size.h:77
impeller::MebiBytes
AllocationSize< 1 '024u *1 '024u > MebiBytes
Definition: allocation_size.h:136
impeller::Bytes
AllocationSize< 1u > Bytes
Definition: allocation_size.h:129
impeller::KiloBytes
AllocationSize< 1 '000u > KiloBytes
Definition: allocation_size.h:131

References impeller::AllocationSize< Period >::GetSize().

## ◆ TEST() [2/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanConstructWithArith |
| ) |  |

Definition at line 110 of file allocation_size_unittests.cc.

110 {
111 {
112 Bytes a(1u);
113 ASSERT_EQ(a.GetByteSize(), 1u);
114 }
115 {
116 Bytes a(1.5);
117 ASSERT_EQ(a.GetByteSize(), 2u);
118 }
119 {
120 Bytes a(1.5f);
121 ASSERT_EQ(a.GetByteSize(), 2u);
122 }
123 }

References impeller::AllocationSize< Period >::GetByteSize().

## ◆ TEST() [3/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanConvert |
| ) |  |

Definition at line 44 of file allocation_size_unittests.cc.

44 {
45 using namespace allocation_size_literals;
46 ASSERT_EQ((5_gb).ConvertTo<MegaBytes>().GetSize(), 5000u);
47 }

## ◆ TEST() [4/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCreateTypedAllocations |
| ) |  |

Definition at line 10 of file allocation_size_unittests.cc.

10 {
11 auto bytes = Bytes{1024};
12 ASSERT_EQ(bytes.GetByteSize(), 1024u);
13
14 auto kilobytes = KiloBytes{5};
15 ASSERT_EQ(kilobytes.GetByteSize(), 5u * 1e3);
16
17 auto megabytes = MegaBytes{5};
18 ASSERT_EQ(megabytes.GetByteSize(), 5u * 1e6);
19
20 auto gigabytes = GigaBytes{5};
21 ASSERT_EQ(gigabytes.GetByteSize(), 5u * 1e9);
22
23 auto kibibytes = KibiBytes{1};
24 ASSERT_EQ(kibibytes.GetByteSize(), 1024u);
25
26 auto mebibytes = MebiBytes{1};
27 ASSERT_EQ(mebibytes.GetByteSize(), 1048576u);
28
29 auto gigibytes = GibiBytes{1};
30 ASSERT_EQ(gigibytes.GetByteSize(), 1073741824u);
31 }
e3
Vector3 e3
Definition: line_contents.cc:109
impeller::GibiBytes
AllocationSize< 1 '024u *1 '024u *1 '024u > GibiBytes
Definition: allocation_size.h:137
impeller::GigaBytes
AllocationSize< 1 '000u *1 '000u *1 '000u > GigaBytes
Definition: allocation_size.h:133
impeller::KibiBytes
AllocationSize< 1 '024u > KibiBytes
Definition: allocation_size.h:135
impeller::MegaBytes
AllocationSize< 1 '000u *1 '000u > MegaBytes
Definition: allocation_size.h:132

References e3.

## ◆ TEST() [5/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanCreateTypedAllocationsWithLiterals |
| ) |  |

Definition at line 33 of file allocation_size_unittests.cc.

33 {
34 using namespace allocation_size_literals;
35 ASSERT_EQ((1024_bytes).GetByteSize(), 1024u);
36 ASSERT_EQ((5_kb).GetByteSize(), 5u * 1e3);
37 ASSERT_EQ((5_mb).GetByteSize(), 5u * 1e6);
38 ASSERT_EQ((5_gb).GetByteSize(), 5u * 1e9);
39 ASSERT_EQ((1_kib).GetByteSize(), 1024u);
40 ASSERT_EQ((1_mib).GetByteSize(), 1048576u);
41 ASSERT_EQ((1_gib).GetByteSize(), 1073741824u);
42 }

References e3.

## ◆ TEST() [6/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanGetFloatValues |
| ) |  |

Definition at line 55 of file allocation_size_unittests.cc.

55 {
56 using namespace allocation_size_literals;
57 ASSERT_DOUBLE_EQ((1500_bytes).ConvertTo<KiloBytes>().GetSize(), 1.5);
58 }

## ◆ TEST() [7/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | CanPerformSimpleArithmetic |
| ) |  |

Definition at line 91 of file allocation_size_unittests.cc.

91 {
92 using namespace allocation_size_literals;
93 {
94 auto a = 100_bytes;
95 auto b = 200_bytes;
96 ASSERT_EQ((a + b).GetByteSize(), 300u);
97 }
98 {
99 auto a = 100_bytes;
100 a += 200_bytes;
101 ASSERT_EQ(a.GetByteSize(), 300u);
102 }
103 {
104 auto a = 100_bytes;
105 a -= 50_bytes;
106 ASSERT_EQ(a.GetByteSize(), 50u);
107 }
108 }

References impeller::saturated::b.

## ◆ TEST() [8/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | ConversionsAreNonTruncating |
| ) |  |

Definition at line 49 of file allocation_size_unittests.cc.

49 {
50 using namespace allocation_size_literals;
51 ASSERT_DOUBLE_EQ((1500_bytes).ConvertTo<KiloBytes>().GetSize(), 1.5);
52 ASSERT_EQ((1500_bytes).ConvertTo<KiloBytes>().GetByteSize(), 1500u);
53 }

## ◆ TEST() [9/574]

impeller::testing::TEST | ( | AllocationSizeTest | ,
|  | RelationalOperatorsAreFunctional |
| ) |  |

Definition at line 60 of file allocation_size_unittests.cc.

60 {
61 using namespace allocation_size_literals;
62
63 auto a = 1500_bytes;
64 auto b = 2500_bytes;
65 auto c = 0_bytes;
66
67 ASSERT_TRUE(a != b);
68 ASSERT_FALSE(a == b);
69 ASSERT_TRUE(b > a);
70 ASSERT_TRUE(b >= a);
71 ASSERT_TRUE(a < b);
72 ASSERT_TRUE(a <= b);
73 ASSERT_TRUE(a);
74 ASSERT_FALSE(c);
75 }
c
Point c
Definition: round_superellipse_param.cc:315

References impeller::saturated::b, and c.

## ◆ TEST() [10/574]

impeller::testing::TEST | ( | AllocatorTest | ,
|  | RangeTest |
| ) |  |

Definition at line 82 of file allocator_unittests.cc.

82 {
83 {
84 Range a = Range{0, 10};
85 Range b = Range{10, 20};
86 auto merged = a.Merge(b);
87
88 EXPECT_EQ(merged.offset, 0u);
89 EXPECT_EQ(merged.length, 30u);
90 }
91
92 {
93 Range a = Range{0, 10};
94 Range b = Range{100, 20};
95 auto merged = a.Merge(b);
96
97 EXPECT_EQ(merged.offset, 0u);
98 EXPECT_EQ(merged.length, 120u);
99 }
100
101 {
102 Range a = Range{0, 10};
103 Range b = Range{100, 20};
104 auto merged = b.Merge(a);
105
106 EXPECT_EQ(merged.offset, 0u);
107 EXPECT_EQ(merged.length, 120u);
108 }
109
110 {
111 Range a = Range{0, 10};
112 Range b = Range{100, 0};
113 auto merged = b.Merge(a);
114
115 EXPECT_EQ(merged.offset, 0u);
116 EXPECT_EQ(merged.length, 10u);
117 }
118
119 {
120 Range a = Range{0, 10};
121 Range b = Range{0, 10};
122 auto merged = b.Merge(a);
123
124 EXPECT_EQ(merged.offset, 0u);
125 EXPECT_EQ(merged.length, 10u);
126 }
127 }

References impeller::saturated::b, and impeller::Range::Merge().

## ◆ TEST() [11/574]

impeller::testing::TEST | ( | AllocatorTest | ,
|  | TextureDescriptorCompatibility |
| ) |  |

Definition at line 16 of file allocator_unittests.cc.

16 {
17 // Size.
18 {
19 TextureDescriptor desc_a = {.size = ISize(100, 100)};
20 TextureDescriptor desc_b = {.size = ISize(100, 100)};
21 TextureDescriptor desc_c = {.size = ISize(101, 100)};
22
23 ASSERT_EQ(desc_a, desc_b);
24 ASSERT_NE(desc_a, desc_c);
25 }
26 // Storage Mode.
27 {
28 TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
29 TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
30 TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};
31
32 ASSERT_EQ(desc_a, desc_b);
33 ASSERT_NE(desc_a, desc_c);
34 }
35 // Format.
36 {
37 TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
38 TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
39 TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};
40
41 ASSERT_EQ(desc_a, desc_b);
42 ASSERT_NE(desc_a, desc_c);
43 }
44 // Sample Count.
45 {
46 TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
47 TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
48 TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};
49
50 ASSERT_EQ(desc_a, desc_b);
51 ASSERT_NE(desc_a, desc_c);
52 }
53 // Sample Count.
54 {
55 TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
56 TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
57 TextureDescriptor desc_c = {.type = TextureType::kTexture2D};
58
59 ASSERT_EQ(desc_a, desc_b);
60 ASSERT_NE(desc_a, desc_c);
61 }
62 // Compression.
63 {
64 TextureDescriptor desc_a = {.compression_type = CompressionType::kLossless};
65 TextureDescriptor desc_b = {.compression_type = CompressionType::kLossless};
66 TextureDescriptor desc_c = {.compression_type = CompressionType::kLossy};
67
68 ASSERT_EQ(desc_a, desc_b);
69 ASSERT_NE(desc_a, desc_c);
70 }
71 // Mip Count.
72 {
73 TextureDescriptor desc_a = {.mip_count = 1};
74 TextureDescriptor desc_b = {.mip_count = 1};
75 TextureDescriptor desc_c = {.mip_count = 4};
76
77 ASSERT_EQ(desc_a, desc_b);
78 ASSERT_NE(desc_a, desc_c);
79 }
80 }
impeller::ISize
ISize64 ISize
Definition: size.h:162

References impeller::TextureDescriptor::compression_type, impeller::TextureDescriptor::format, impeller::kB10G10R10A10XR, impeller::kCount1, impeller::kCount4, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kLossless, impeller::kLossy, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::kTexture2DMultisample, impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::sample_count, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST() [12/574]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | ImageResourceKeepsVulkanDeviceAlive |
| ) |  |

Definition at line 77 of file allocator_vk_unittests.cc.

77 {
78 std::shared_ptr<Texture> texture;
79 std::weak_ptr<Allocator> weak_allocator;
80 {
81 auto const context = MockVulkanContextBuilder().Build();
82 weak_allocator = context->GetResourceAllocator();
83 auto allocator = context->GetResourceAllocator();
84
85 texture = allocator->CreateTexture(TextureDescriptor{
86 .storage_mode = StorageMode::kDevicePrivate,
87 .format = PixelFormat::kR8G8B8A8UNormInt,
88 .size = {1, 1},
89 });
90 context->Shutdown();
91 }
92
93 ASSERT_TRUE(weak_allocator.lock());
94 }

References impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST() [13/574]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | MemoryTypeSelectionSingleHeap |
| ) |  |

Definition at line 39 of file allocator_vk_unittests.cc.

39 {
40 vk::PhysicalDeviceMemoryProperties properties;
41 properties.memoryTypeCount = 1;
42 properties.memoryHeapCount = 1;
43 properties.memoryTypes[0].heapIndex = 0;
44 properties.memoryTypes[0].propertyFlags =
45 vk::MemoryPropertyFlagBits::eDeviceLocal;
46 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
47 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
48
49 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), 0);
50 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), -1);
51 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 0);
52 }

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [14/574]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | MemoryTypeSelectionTwoHeap |
| ) |  |

Definition at line 54 of file allocator_vk_unittests.cc.

54 {
55 vk::PhysicalDeviceMemoryProperties properties;
56 properties.memoryTypeCount = 2;
57 properties.memoryHeapCount = 2;
58 properties.memoryTypes[0].heapIndex = 0;
59 properties.memoryTypes[0].propertyFlags =
60 vk::MemoryPropertyFlagBits::eHostVisible;
61 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
62 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
63
64 properties.memoryTypes[1].heapIndex = 1;
65 properties.memoryTypes[1].propertyFlags =
66 vk::MemoryPropertyFlagBits::eDeviceLocal;
67 properties.memoryHeaps[1].size = 1024 * 1024 * 1024;
68 properties.memoryHeaps[1].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
69
70 // First fails because this only looks for eDeviceLocal.
71 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), -1);
72 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), 1);
73 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 1);
74 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(4, properties), -1);
75 }

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [15/574]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | ToVKImageUsageFlags |
| ) |  |

Definition at line 20 of file allocator_vk_unittests.cc.

20 {
21 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
22 PixelFormat::kR8G8B8A8UNormInt,
23 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
24 StorageMode::kDeviceTransient,
25 /*supports_memoryless_textures=*/true),
26 vk::ImageUsageFlagBits::eInputAttachment |
27 vk::ImageUsageFlagBits::eColorAttachment |
28 vk::ImageUsageFlagBits::eTransientAttachment);
29
30 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
31 PixelFormat::kD24UnormS8Uint,
32 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
33 StorageMode::kDeviceTransient,
34 /*supports_memoryless_textures=*/true),
35 vk::ImageUsageFlagBits::eDepthStencilAttachment |
36 vk::ImageUsageFlagBits::eTransientAttachment);
37 }
impeller::TextureUsageMask
Mask< TextureUsage > TextureUsageMask
Definition: formats.h:311

References impeller::kD24UnormS8Uint, impeller::kDeviceTransient, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, and impeller::AllocatorVK::ToVKImageUsageFlags().

## ◆ TEST() [16/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsAllQuadrantsFromFirst |
| ) |  |

Definition at line 262 of file arc_unittests.cc.

262 {
263 CheckFiveQuadrants(Degrees(90 * 0 + 60), Degrees(330));
264 }

## ◆ TEST() [17/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsAllQuadrantsFromFourth |
| ) |  |

Definition at line 274 of file arc_unittests.cc.

274 {
275 CheckFiveQuadrants(Degrees(90 * 3 + 60), Degrees(330));
276 }

## ◆ TEST() [18/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsAllQuadrantsFromSecond |
| ) |  |

Definition at line 266 of file arc_unittests.cc.

266 {
267 CheckFiveQuadrants(Degrees(90 * 1 + 60), Degrees(330));
268 }

## ◆ TEST() [19/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsAllQuadrantsFromThird |
| ) |  |

Definition at line 270 of file arc_unittests.cc.

270 {
271 CheckFiveQuadrants(Degrees(90 * 2 + 60), Degrees(330));
272 }

## ◆ TEST() [20/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsFullCircle |
| ) |  |

Definition at line 125 of file arc_unittests.cc.

125 {
126 // Anything with a sweep <=-360 or >=360 is a full circle regardless of
127 // starting angle
128 for (int start = -720; start < 720; start += 30) {
129 for (int sweep = 360; sweep < 1080; sweep += 45) {
130 TestFullCircleArc(Degrees(start), Degrees(sweep));
131 TestFullCircleArc(Degrees(start), Degrees(-sweep));
132 }
133 }
134 }
start
const size_t start
Definition: tessellator_libtess.cc:62

References start.

## ◆ TEST() [21/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsOnlyFirstQuadrant |
| ) |  |

Definition at line 210 of file arc_unittests.cc.

210 {
211 CheckOneQuadrant(Degrees(90 * 0 + 30), Degrees(30));
212 }

## ◆ TEST() [22/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsOnlyFourthQuadrant |
| ) |  |

Definition at line 222 of file arc_unittests.cc.

222 {
223 CheckOneQuadrant(Degrees(90 * 3 + 30), Degrees(30));
224 }

## ◆ TEST() [23/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsOnlySecondQuadrant |
| ) |  |

Definition at line 214 of file arc_unittests.cc.

214 {
215 CheckOneQuadrant(Degrees(90 * 1 + 30), Degrees(30));
216 }

## ◆ TEST() [24/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsOnlyThirdQuadrant |
| ) |  |

Definition at line 218 of file arc_unittests.cc.

218 {
219 CheckOneQuadrant(Degrees(90 * 2 + 30), Degrees(30));
220 }

## ◆ TEST() [25/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsVariousEndAnglesNearQuadrantAxis |
| ) |  |

Definition at line 172 of file arc_unittests.cc.

172 {
173 Tessellator tessellator;
174 const auto trigs = tessellator.GetTrigsForDeviceRadius(100);
175
176 for (int sweep_i = 5; sweep_i < 20000; sweep_i += 5) {
177 const Degrees sweep(sweep_i * 0.01f);
178 for (int quadrant = -360; quadrant <= 360; quadrant += 90) {
179 const Degrees start(quadrant + 80);
180 Arc arc(Rect::MakeLTRB(10, 10, 20, 20), start, sweep, false);
181 const auto& arc_iteration = arc.ComputeIterations(trigs.GetSteps());
182
183 TestArcIterator(arc_iteration, trigs, start, sweep,
184 "Various angles(" + std::to_string(start.degrees) +
185 " += " + std::to_string(sweep.degrees));
186 }
187 }
188 }

References impeller::Arc::ComputeIterations(), impeller::Degrees::degrees, impeller::Tessellator::Trigs::GetSteps(), impeller::Tessellator::GetTrigsForDeviceRadius(), impeller::TRect< Scalar >::MakeLTRB(), and start.

## ◆ TEST() [26/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsVariousStartAnglesNearQuadrantAxis |
| ) |  |

Definition at line 153 of file arc_unittests.cc.

153 {
154 Tessellator tessellator;
155 const auto trigs = tessellator.GetTrigsForDeviceRadius(100);
156 const Degrees sweep(45);
157
158 for (int start_i = -1000; start_i < 1000; start_i += 5) {
159 Scalar start_degrees = start_i * 0.01f;
160 for (int quadrant = -360; quadrant <= 360; quadrant += 90) {
161 const Degrees start(quadrant + start_degrees);
162 Arc arc(Rect::MakeLTRB(10, 10, 20, 20), start, sweep, false);
163 const auto& arc_iteration = arc.ComputeIterations(trigs.GetSteps());
164
165 TestArcIterator(arc_iteration, trigs, start, sweep,
166 "Various angles(" + std::to_string(start.degrees) +
167 " += " + std::to_string(sweep.degrees));
168 }
169 }
170 }

References impeller::Arc::ComputeIterations(), impeller::Degrees::degrees, impeller::Tessellator::Trigs::GetSteps(), impeller::Tessellator::GetTrigsForDeviceRadius(), impeller::TRect< Scalar >::MakeLTRB(), and start.

## ◆ TEST() [27/574]

impeller::testing::TEST | ( | ArcTest | ,
|  | ArcIterationsVariousTinyArcsNearQuadrantAxis |
| ) |  |

Definition at line 190 of file arc_unittests.cc.

190 {
191 Tessellator tessellator;
192 const auto trigs = tessellator.GetTrigsForDeviceRadius(100);
193 const Degrees sweep(0.1f);
194
195 for (int start_i = -1000; start_i < 1000; start_i += 5) {
196 Scalar start_degrees = start_i * 0.01f;
197 for (int quadrant = -360; quadrant <= 360; quadrant += 90) {
198 const Degrees start(quadrant + start_degrees);
199 Arc arc(Rect::MakeLTRB(10, 10, 20, 20), start, sweep, false);
200 const auto& arc_iteration = arc.ComputeIterations(trigs.GetSteps());
201 ASSERT_EQ(arc_iteration.quadrant_count, 0u);
202
203 TestArcIterator(arc_iteration, trigs, start, sweep,
204 "Various angles(" + std::to_string(start.degrees) +
205 " += " + std::to_string(sweep.degrees));
206 }
207 }
208 }

References impeller::Arc::ComputeIterations(), impeller::Degrees::degrees, impeller::Tessellator::Trigs::GetSteps(), impeller::Tessellator::GetTrigsForDeviceRadius(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Arc::Iteration::quadrant_count, and start.

## ◆ TEST() [28/574]

impeller::testing::TEST | ( | BaseTest | ,
|  | CanUseTypedMasks |
| ) |  |

Definition at line 259 of file base_unittests.cc.

259 {
260 {
261 MyMask mask;
262 ASSERT_EQ(static_cast<uint32_t>(mask), 0u);
263 ASSERT_FALSE(mask);
264 }
265
266 {
267 MyMask mask(MyMaskBits::kBar);
268 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
269 ASSERT_TRUE(mask);
270 }
271
272 {
273 MyMask mask2(MyMaskBits::kBar);
274 MyMask mask(mask2);
275 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
276 ASSERT_TRUE(mask);
277 }
278
279 {
280 MyMask mask2(MyMaskBits::kBar);
281 MyMask mask(std::move(mask2)); // NOLINT
282 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
283 ASSERT_TRUE(mask);
284 }
285
286 ASSERT_LT(MyMaskBits::kBar, MyMaskBits::kBaz);
287 ASSERT_LE(MyMaskBits::kBar, MyMaskBits::kBaz);
288 ASSERT_GT(MyMaskBits::kBaz, MyMaskBits::kBar);
289 ASSERT_GE(MyMaskBits::kBaz, MyMaskBits::kBar);
290 ASSERT_EQ(MyMaskBits::kBaz, MyMaskBits::kBaz);
291 ASSERT_NE(MyMaskBits::kBaz, MyMaskBits::kBang);
292
293 {
294 MyMask m1(MyMaskBits::kBar);
295 MyMask m2(MyMaskBits::kBaz);
296 ASSERT_EQ(static_cast<uint32_t>(m1 & m2), 0u);
297 ASSERT_FALSE(m1 & m2);
298 }
299
300 {
301 MyMask m1(MyMaskBits::kBar);
302 MyMask m2(MyMaskBits::kBaz);
303 ASSERT_EQ(static_cast<uint32_t>(m1 | m2), ((1u << 0u) | (1u << 1u)));
304 ASSERT_TRUE(m1 | m2);
305 }
306
307 {
308 MyMask m1(MyMaskBits::kBar);
309 MyMask m2(MyMaskBits::kBaz);
310 ASSERT_EQ(static_cast<uint32_t>(m1 ^ m2), ((1u << 0u) ^ (1u << 1u)));
311 ASSERT_TRUE(m1 ^ m2);
312 }
313
314 {
315 MyMask m1(MyMaskBits::kBar);
316 ASSERT_EQ(static_cast<uint32_t>(~m1), (~(1u << 0u)));
317 ASSERT_TRUE(m1);
318 }
319
320 {
321 MyMask m1 = MyMaskBits::kBar;
322 MyMask m2 = MyMaskBits::kBaz;
323 m2 = m1;
324 ASSERT_EQ(m2, MyMaskBits::kBar);
325 }
326
327 {
328 MyMask m = MyMaskBits::kBar | MyMaskBits::kBaz;
329 ASSERT_TRUE(m);
330 }
331
332 {
333 MyMask m = MyMaskBits::kBar & MyMaskBits::kBaz;
334 ASSERT_FALSE(m);
335 }
336
337 {
338 MyMask m = MyMaskBits::kBar ^ MyMaskBits::kBaz;
339 ASSERT_TRUE(m);
340 }
341
342 {
343 MyMask m = ~MyMaskBits::kBar;
344 ASSERT_TRUE(m);
345 }
346
347 {
348 MyMask m1 = MyMaskBits::kBar;
349 MyMask m2 = MyMaskBits::kBaz;
350 m2 |= m1;
351 ASSERT_EQ(m1, MyMaskBits::kBar);
352 MyMask pred = MyMaskBits::kBar | MyMaskBits::kBaz;
353 ASSERT_EQ(m2, pred);
354 }
355
356 {
357 MyMask m1 = MyMaskBits::kBar;
358 MyMask m2 = MyMaskBits::kBaz;
359 m2 &= m1;
360 ASSERT_EQ(m1, MyMaskBits::kBar);
361 MyMask pred = MyMaskBits::kBar & MyMaskBits::kBaz;
362 ASSERT_EQ(m2, pred);
363 }
364
365 {
366 MyMask m1 = MyMaskBits::kBar;
367 MyMask m2 = MyMaskBits::kBaz;
368 m2 ^= m1;
369 ASSERT_EQ(m1, MyMaskBits::kBar);
370 MyMask pred = MyMaskBits::kBar ^ MyMaskBits::kBaz;
371 ASSERT_EQ(m2, pred);
372 }
373
374 {
375 MyMask x = MyMaskBits::kBar;
376 MyMask m = x | MyMaskBits::kBaz;
377 ASSERT_TRUE(m);
378 }
379
380 {
381 MyMask x = MyMaskBits::kBar;
382 MyMask m = MyMaskBits::kBaz | x;
383 ASSERT_TRUE(m);
384 }
385
386 {
387 MyMask x = MyMaskBits::kBar;
388 MyMask m = x & MyMaskBits::kBaz;
389 ASSERT_FALSE(m);
390 }
391
392 {
393 MyMask x = MyMaskBits::kBar;
394 MyMask m = MyMaskBits::kBaz & x;
395 ASSERT_FALSE(m);
396 }
397
398 {
399 MyMask x = MyMaskBits::kBar;
400 MyMask m = x ^ MyMaskBits::kBaz;
401 ASSERT_TRUE(m);
402 }
403
404 {
405 MyMask x = MyMaskBits::kBar;
406 MyMask m = MyMaskBits::kBaz ^ x;
407 ASSERT_TRUE(m);
408 }
409
410 {
411 MyMask x = MyMaskBits::kBar;
412 MyMask m = ~x;
413 ASSERT_TRUE(m);
414 }
415
416 {
417 MyMaskBits x = MyMaskBits::kBar;
418 MyMask m = MyMaskBits::kBaz;
419 ASSERT_TRUE(x < m);
420 ASSERT_TRUE(x <= m);
421 }
422
423 {
424 MyMaskBits x = MyMaskBits::kBar;
425 MyMask m = MyMaskBits::kBaz;
426 ASSERT_FALSE(x == m);
427 }
428
429 {
430 MyMaskBits x = MyMaskBits::kBar;
431 MyMask m = MyMaskBits::kBaz;
432 ASSERT_TRUE(x != m);
433 }
434
435 {
436 MyMaskBits x = MyMaskBits::kBar;
437 MyMask m = MyMaskBits::kBaz;
438 ASSERT_FALSE(x > m);
439 ASSERT_FALSE(x >= m);
440 }
441 }
impeller::MyMask
Mask< MyMaskBits > MyMask
Definition: base_unittests.cc:20
impeller::MyMaskBits
MyMaskBits
Definition: base_unittests.cc:13

References impeller::kBang, impeller::kBar, impeller::kBaz, and x.

## ◆ TEST() [29/574]

impeller::testing::TEST | ( | BaseTest | ,
|  | NoExceptionPromiseEmpty |
| ) |  |

Definition at line 250 of file base_unittests.cc.

250 {
251 auto wrapper = std::make_shared<NoExceptionPromise<int>>();
252 std::future future = wrapper->get_future();
253
254 // Destroy the empty promise with the future still pending. Verify that the
255 // process does not abort while destructing the promise.
256 wrapper.reset();
257 }

## ◆ TEST() [30/574]

impeller::testing::TEST | ( | BaseTest | ,
|  | NoExceptionPromiseValue |
| ) |  |

Definition at line 243 of file base_unittests.cc.

243 {
244 NoExceptionPromise<int> wrapper;
245 std::future future = wrapper.get_future();
246 wrapper.set_value(123);
247 ASSERT_EQ(future.get(), 123);
248 }

References impeller::NoExceptionPromise< T >::get_future(), and impeller::NoExceptionPromise< T >::set_value().

## ◆ TEST() [31/574]

impeller::testing::TEST | ( | BlitCommandGLESTest | ,
|  | BlitCopyTextureToBufferCommandGLESBindsFramebuffer |
| ) |  |

Definition at line 39 of file blit_command_gles_unittests.cc.

39 {
40 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
41 auto& mock_gles_impl_ref = *mock_gles_impl;
42
43 EXPECT_CALL(mock_gles_impl_ref, GenFramebuffers(1, _))
44 .WillOnce(::testing::SetArgPointee<1>(3));
45 EXPECT_CALL(mock_gles_impl_ref, GenTextures(1, _))
46 .WillOnce(::testing::SetArgPointee<1>(1));
47 EXPECT_CALL(mock_gles_impl_ref, BindFramebuffer(GL_FRAMEBUFFER, 3)).Times(1);
48 EXPECT_CALL(mock_gles_impl_ref, CheckFramebufferStatus(GL_FRAMEBUFFER))
49 .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE));
50 EXPECT_CALL(mock_gles_impl_ref, ReadPixels(_, _, _, _, _, _, _)).Times(1);
51 EXPECT_CALL(mock_gles_impl_ref, BindFramebuffer(GL_FRAMEBUFFER, 0)).Times(1);
52
53 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
54 auto reactor = std::make_shared<TestReactorGLES>();
55 auto worker = std::make_shared<MockWorker>();
56 reactor->AddWorker(worker);
57
58 // Create source texture.
59 TextureDescriptor src_tex_desc;
60 src_tex_desc.format = PixelFormat::kR8G8B8A8UNormInt;
61 src_tex_desc.size = {10, 10};
62 src_tex_desc.usage =
63 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
64 auto source_texture = std::make_shared<TextureGLES>(reactor, src_tex_desc);
65 // Avoids the flip which would crash.
66 source_texture->SetCoordinateSystem(TextureCoordinateSystem::kUploadFromHost);
67
68 // Create destination buffer.
69 DeviceBufferDescriptor dest_buffer_desc;
70 dest_buffer_desc.size = 10 * 10 * 4;
71 dest_buffer_desc.storage_mode = StorageMode::kHostVisible;
72 auto allocation = std::make_shared<Allocation>();
73 ASSERT_TRUE(allocation->Truncate(Bytes(dest_buffer_desc.size)));
74 auto dest_buffer =
75 std::make_shared<DeviceBufferGLES>(dest_buffer_desc, reactor, allocation);
76
77 ASSERT_TRUE(reactor->React());
78
79 BlitCopyTextureToBufferCommandGLES command;
80 command.source = source_texture;
81 command.destination = dest_buffer;
82 command.source_region =
83 IRect::MakeSize(source_texture->GetTextureDescriptor().size);
84 command.label = "TestBlit";
85
86 EXPECT_TRUE(command.Encode(*reactor));
87
88 source_texture.reset();
89 dest_buffer.reset();
90
91 ASSERT_TRUE(reactor->React());
92 }

References impeller::BlitCopyTextureToBufferCommand::destination, impeller::BlitCopyTextureToBufferCommandGLES::Encode(), impeller::TextureDescriptor::format, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kUploadFromHost, impeller::BlitCommand::label, impeller::TRect< T >::MakeSize(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::BlitCopyTextureToBufferCommand::source, impeller::BlitCopyTextureToBufferCommand::source_region, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST() [32/574]

impeller::testing::TEST | ( | BufferBindingsGLESTest | ,
|  | BindArrayData |
| ) |  |

Definition at line 51 of file buffer_bindings_gles_unittests.cc.

51 {
52 BufferBindingsGLES bindings;
53 absl::flat_hash_map<std::string, GLint> uniform_bindings;
54 uniform_bindings["SHADERMETADATA.FOOBAR[0]"] = 1;
55 bindings.SetUniformBindings(std::move(uniform_bindings));
56 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
57
58 EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
59
60 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
61 std::vector<BufferResource> bound_buffers;
62 std::vector<TextureAndSampler> bound_textures;
63
64 ShaderMetadata shader_metadata = {
65 .name = "shader_metadata",
66 .members = {ShaderStructMemberMetadata{.type = ShaderType::kFloat,
67 .name = "foobar",
68 .offset = 0,
69 .size = sizeof(float),
70 .byte_length = sizeof(float) * 4,
71 .array_elements = 4}}};
72 std::shared_ptr<ReactorGLES> reactor;
73 std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
74 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float) * 4}));
75 DeviceBufferGLES device_buffer(
76 DeviceBufferDescriptor{.size = sizeof(float) * 4}, reactor,
77 backing_store);
78 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
79 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
80
81 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
82 bound_buffers, Range{0, 0},
83 Range{0, 1}));
84 }
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:154
impeller::BufferResource
Resource< BufferView > BufferResource
Definition: command.h:55
impeller::kFloat
@ kFloat
Definition: runtime_types.h:25

References impeller::BufferBindingsGLES::BindUniformData(), buffer_view, impeller::kFloat, impeller::ShaderMetadata::name, impeller::DeviceBufferDescriptor::size, and impeller::ShaderStructMemberMetadata::type.

## ◆ TEST() [33/574]

impeller::testing::TEST | ( | BufferBindingsGLESTest | ,
|  | BindUniformData |
| ) |  |

Definition at line 17 of file buffer_bindings_gles_unittests.cc.

17 {
18 BufferBindingsGLES bindings;
19 absl::flat_hash_map<std::string, GLint> uniform_bindings;
20 uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
21 bindings.SetUniformBindings(std::move(uniform_bindings));
22 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
23
24 EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
25
26 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
27 std::vector<BufferResource> bound_buffers;
28 std::vector<TextureAndSampler> bound_textures;
29
30 ShaderMetadata shader_metadata = {
31 .name = "shader_metadata",
32 .members = {ShaderStructMemberMetadata{.type = ShaderType::kFloat,
33 .name = "foobar",
34 .offset = 0,
35 .size = sizeof(float),
36 .byte_length = sizeof(float),
37 .array_elements = std::nullopt}}};
38 std::shared_ptr<ReactorGLES> reactor;
39 std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
40 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
41 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
42 reactor, backing_store);
43 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
44 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
45
46 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
47 bound_buffers, Range{0, 0},
48 Range{0, 1}));
49 }

References impeller::BufferBindingsGLES::BindUniformData(), buffer_view, impeller::kFloat, impeller::ShaderMetadata::name, impeller::DeviceBufferDescriptor::size, and impeller::ShaderStructMemberMetadata::type.

## ◆ TEST() [34/574]

impeller::testing::TEST | ( | BufferViewTest | ,
|  | Empty |
| ) |  |

Definition at line 11 of file buffer_view_unittests.cc.

11 {
12 BufferView buffer_view;
13 EXPECT_FALSE(buffer_view);
14 }

References buffer_view.

## ◆ TEST() [35/574]

impeller::testing::TEST | ( | BufferViewTest | ,
|  | TakeRaw |
| ) |  |

Definition at line 16 of file buffer_view_unittests.cc.

16 {
17 DeviceBuffer* buffer = reinterpret_cast<DeviceBuffer*>(0xcafebabe);
18 BufferView buffer_view(buffer, {0, 123});
19 EXPECT_TRUE(buffer_view);
20 std::shared_ptr<const DeviceBuffer> taken = buffer_view.TakeBuffer();
21 EXPECT_FALSE(taken);
22 EXPECT_EQ(buffer_view.GetBuffer(), buffer);
23 }

References buffer_view.

## ◆ TEST() [36/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultColorFormat |
| ) |  |

Definition at line 34 of file capabilities_unittests.cc.

34 {
35 auto defaults = CapabilitiesBuilder().Build();
36 EXPECT_EQ(defaults->GetDefaultColorFormat(), PixelFormat::kUnknown);
37 auto mutated = CapabilitiesBuilder()
38 .SetDefaultColorFormat(PixelFormat::kB10G10R10A10XR)
39 .Build();
40 EXPECT_EQ(mutated->GetDefaultColorFormat(), PixelFormat::kB10G10R10A10XR);
41 }

References impeller::CapabilitiesBuilder::Build(), impeller::kB10G10R10A10XR, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultColorFormat().

## ◆ TEST() [37/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultDepthStencilFormat |
| ) |  |

Definition at line 52 of file capabilities_unittests.cc.

52 {
53 auto defaults = CapabilitiesBuilder().Build();
54 EXPECT_EQ(defaults->GetDefaultDepthStencilFormat(), PixelFormat::kUnknown);
55 auto mutated = CapabilitiesBuilder()
56 .SetDefaultDepthStencilFormat(PixelFormat::kD32FloatS8UInt)
57 .Build();
58 EXPECT_EQ(mutated->GetDefaultDepthStencilFormat(),
59 PixelFormat::kD32FloatS8UInt);
60 }

References impeller::CapabilitiesBuilder::Build(), impeller::kD32FloatS8UInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultDepthStencilFormat().

## ◆ TEST() [38/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultGlyphAtlasFormat |
| ) |  |

Definition at line 62 of file capabilities_unittests.cc.

62 {
63 auto defaults = CapabilitiesBuilder().Build();
64 EXPECT_EQ(defaults->GetDefaultGlyphAtlasFormat(), PixelFormat::kUnknown);
65 auto mutated = CapabilitiesBuilder()
66 .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
67 .Build();
68 EXPECT_EQ(mutated->GetDefaultGlyphAtlasFormat(), PixelFormat::kA8UNormInt);
69 }

References impeller::CapabilitiesBuilder::Build(), impeller::kA8UNormInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultGlyphAtlasFormat().

## ◆ TEST() [39/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultStencilFormat |
| ) |  |

Definition at line 43 of file capabilities_unittests.cc.

43 {
44 auto defaults = CapabilitiesBuilder().Build();
45 EXPECT_EQ(defaults->GetDefaultStencilFormat(), PixelFormat::kUnknown);
46 auto mutated = CapabilitiesBuilder()
47 .SetDefaultStencilFormat(PixelFormat::kS8UInt)
48 .Build();
49 EXPECT_EQ(mutated->GetDefaultStencilFormat(), PixelFormat::kS8UInt);
50 }

References impeller::CapabilitiesBuilder::Build(), impeller::kS8UInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultStencilFormat().

## ◆ TEST() [40/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | MaxRenderPassAttachmentSize |
| ) |  |

Definition at line 71 of file capabilities_unittests.cc.

71 {
72 auto defaults = CapabilitiesBuilder().Build();
73 EXPECT_EQ(defaults->GetMaximumRenderPassAttachmentSize(), ISize(1, 1));
74 auto mutated = CapabilitiesBuilder()
75 .SetMaximumRenderPassAttachmentSize({100, 100})
76 .Build();
77 EXPECT_EQ(mutated->GetMaximumRenderPassAttachmentSize(), ISize(100, 100));
78 }

References impeller::CapabilitiesBuilder::Build(), and impeller::CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize().

## ◆ TEST() [41/574]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | MinUniformAlignment |
| ) |  |

Definition at line 80 of file capabilities_unittests.cc.

80 {
81 auto defaults = CapabilitiesBuilder().Build();
82 EXPECT_EQ(defaults->GetMinimumUniformAlignment(), 256u);
83 auto mutated = CapabilitiesBuilder().SetMinimumUniformAlignment(16).Build();
84 EXPECT_EQ(mutated->GetMinimumUniformAlignment(), 16u);
85 }

References impeller::CapabilitiesBuilder::Build(), and impeller::CapabilitiesBuilder::SetMinimumUniformAlignment().

## ◆ TEST() [42/574]

impeller::testing::TEST | ( | CapabilitiesVKTest | ,
|  | ContextFailsInitializationForNoCombinedDepthStencilFormat |
| ) |  |

Definition at line 215 of file context_vk_unittests.cc.

216 {
217 ScopedValidationDisable disable_validation;
218 const std::shared_ptr<ContextVK> context =
219 MockVulkanContextBuilder()
220 .SetPhysicalDeviceFormatPropertiesCallback(
221 [](VkPhysicalDevice physicalDevice, VkFormat format,
222 VkFormatProperties* pFormatProperties) {
223 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
224 pFormatProperties->optimalTilingFeatures =
225 static_cast<VkFormatFeatureFlags>(
226 vk::FormatFeatureFlagBits::eColorAttachment);
227 }
228 // Ignore combined depth-stencil formats.
229 })
230 .Build();
231 ASSERT_EQ(context, nullptr);
232 }

## ◆ TEST() [43/574]

impeller::testing::TEST | ( | CapabilitiesVKTest | ,
|  | ContextInitializesWithNoStencilFormat |
| ) |  |

Definition at line 184 of file context_vk_unittests.cc.

184 {
185 const std::shared_ptr<ContextVK> context =
186 MockVulkanContextBuilder()
187 .SetPhysicalDeviceFormatPropertiesCallback(
188 [](VkPhysicalDevice physicalDevice, VkFormat format,
189 VkFormatProperties* pFormatProperties) {
190 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
191 pFormatProperties->optimalTilingFeatures =
192 static_cast<VkFormatFeatureFlags>(
193 vk::FormatFeatureFlagBits::eColorAttachment);
194 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
195 pFormatProperties->optimalTilingFeatures =
196 static_cast<VkFormatFeatureFlags>(
197 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
198 }
199 // Ignore just the stencil format.
200 })
201 .Build();
202 ASSERT_NE(context, nullptr);
203 const CapabilitiesVK* capabilites_vk =
204 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
205 ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
206 PixelFormat::kD32FloatS8UInt);
207 ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
208 PixelFormat::kD32FloatS8UInt);
209 }

References impeller::CapabilitiesVK::GetDefaultDepthStencilFormat(), impeller::CapabilitiesVK::GetDefaultStencilFormat(), and impeller::kD32FloatS8UInt.

## ◆ TEST() [44/574]

impeller::testing::TEST | ( | CommandEncoderVKTest | ,
|  | CleanupAfterSubmit |
| ) |  |

Definition at line 37 of file command_encoder_vk_unittests.cc.

37 {
38 // This tests deleting the TrackedObjects where the thread is killed before
39 // the fence waiter has disposed of them, making sure the command buffer and
40 // its pools are deleted in that order.
41 std::shared_ptr<std::vector<std::string>> called_functions;
42 {
43 fml::AutoResetWaitableEvent wait_for_submit;
44 fml::AutoResetWaitableEvent wait_for_thread_join;
45 auto context = MockVulkanContextBuilder().Build();
46 std::thread thread([&] {
47 auto buffer = context->CreateCommandBuffer();
48 context->GetCommandQueue()->Submit(
49 {buffer}, [&](CommandBuffer::Status status) {
50 ASSERT_EQ(status, CommandBuffer::Status::kCompleted);
51 wait_for_thread_join.Wait();
52 wait_for_submit.Signal();
53 });
54 });
55 thread.join();
56 wait_for_thread_join.Signal();
57 wait_for_submit.Wait();
58 called_functions = GetMockVulkanFunctions(context->GetDevice());
59 context->Shutdown();
60 }
61
62 auto destroy_pool =
63 std::find(called_functions->begin(), called_functions->end(),
64 "vkDestroyCommandPool");
65 auto free_buffers =
66 std::find(called_functions->begin(), called_functions->end(),
67 "vkFreeCommandBuffers");
68 EXPECT_TRUE(destroy_pool != called_functions->end());
69 EXPECT_TRUE(free_buffers != called_functions->end());
70 EXPECT_TRUE(free_buffers < destroy_pool);
71 }

References impeller::CommandBuffer::kCompleted.

## ◆ TEST() [45/574]

impeller::testing::TEST | ( | CommandEncoderVKTest | ,
|  | DeleteEncoderAfterThreadDies |
| ) |  |

Definition at line 15 of file command_encoder_vk_unittests.cc.

15 {
16 // Tests that when a CommandEncoderVK is deleted that it will clean up its
17 // command buffers before it cleans up its command pool.
18 std::shared_ptr<std::vector<std::string>> called_functions;
19 {
20 auto context = MockVulkanContextBuilder().Build();
21 called_functions = GetMockVulkanFunctions(context->GetDevice());
22 std::thread thread([&] { context->CreateCommandBuffer(); });
23 thread.join();
24 context->Shutdown();
25 }
26 auto destroy_pool =
27 std::find(called_functions->begin(), called_functions->end(),
28 "vkDestroyCommandPool");
29 auto free_buffers =
30 std::find(called_functions->begin(), called_functions->end(),
31 "vkFreeCommandBuffers");
32 EXPECT_TRUE(destroy_pool != called_functions->end());
33 EXPECT_TRUE(free_buffers != called_functions->end());
34 EXPECT_TRUE(free_buffers < destroy_pool);
35 }

## ◆ TEST() [46/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | CommandBuffersAreRecycled |
| ) |  |

Definition at line 137 of file command_pool_vk_unittests.cc.

137 {
138 auto const context = MockVulkanContextBuilder().Build();
139
140 {
141 // Fetch a pool (which will be created).
142 auto const recycler = context->GetCommandPoolRecycler();
143 auto pool = recycler->Get();
144
145 auto buffer = pool->CreateCommandBuffer();
146 pool->CollectCommandBuffer(std::move(buffer));
147
148 // This normally is called at the end of a frame.
149 recycler->Dispose();
150 }
151
152 WaitForReclaim(context);
153
154 {
155 // Create a second pool and command buffer, which should reused the existing
156 // pool and cmd buffer.
157 auto const recycler = context->GetCommandPoolRecycler();
158 auto pool = recycler->Get();
159
160 auto buffer = pool->CreateCommandBuffer();
161 pool->CollectCommandBuffer(std::move(buffer));
162
163 // This normally is called at the end of a frame.
164 recycler->Dispose();
165 }
166
167 // Now check that we only ever created one pool and one command buffer.
168 auto const called = ReclaimAndGetMockVulkanFunctions(context);
169 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
170 1u);
171 EXPECT_EQ(
172 std::count(called->begin(), called->end(), "vkAllocateCommandBuffers"),
173 1u);
174
175 context->Shutdown();
176 }

## ◆ TEST() [47/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | ExtraCommandBufferAllocationsTriggerTrim |
| ) |  |

Definition at line 178 of file command_pool_vk_unittests.cc.

178 {
179 auto const context = MockVulkanContextBuilder().Build();
180
181 {
182 // Fetch a pool (which will be created).
183 auto const recycler = context->GetCommandPoolRecycler();
184 auto pool = recycler->Get();
185
186 // Allocate a large number of command buffers
187 for (auto i = 0; i < 64; i++) {
188 auto buffer = pool->CreateCommandBuffer();
189 pool->CollectCommandBuffer(std::move(buffer));
190 }
191
192 // This normally is called at the end of a frame.
193 recycler->Dispose();
194 }
195
196 // Command pool is reset but does not release resources.
197 auto called = ReclaimAndGetMockVulkanFunctions(context);
198 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetCommandPool"),
199 1u);
200
201 // Create the pool a second time, but dont use any command buffers.
202 {
203 // Fetch a pool (which will be created).
204 auto const recycler = context->GetCommandPoolRecycler();
205 auto pool = recycler->Get();
206
207 // This normally is called at the end of a frame.
208 recycler->Dispose();
209 }
210
211 // Verify that the cmd pool was trimmed.
212
213 // Now check that we only ever created one pool and one command buffer.
214 called = ReclaimAndGetMockVulkanFunctions(context);
215 EXPECT_EQ(std::count(called->begin(), called->end(),
216 "vkResetCommandPoolReleaseResources"),
217 1u);
218
219 context->Shutdown();
220 }

## ◆ TEST() [48/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | GetsACommandPoolPerThread |
| ) |  |

Definition at line 14 of file command_pool_vk_unittests.cc.

14 {
15 auto const context = MockVulkanContextBuilder().Build();
16
17 {
18 // Record the memory location of each pointer to a command pool.
19 //
20 // These pools have to be held at this context, otherwise they will be
21 // dropped and recycled and potentially reused by another thread, causing
22 // flaky tests.
23 std::shared_ptr<CommandPoolVK> pool1;
24 std::shared_ptr<CommandPoolVK> pool2;
25
26 // Create a command pool in two threads and record the memory location.
27 std::thread thread1(
28 [&]() { pool1 = context->GetCommandPoolRecycler()->Get(); });
29
30 std::thread thread2(
31 [&]() { pool2 = context->GetCommandPoolRecycler()->Get(); });
32
33 thread1.join();
34 thread2.join();
35
36 // The two command pools should be different.
37 EXPECT_NE(pool1, pool2);
38 }
39
40 context->Shutdown();
41 }

## ◆ TEST() [49/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | GetsTheSameCommandPoolOnSameThread |
| ) |  |

Definition at line 43 of file command_pool_vk_unittests.cc.

43 {
44 auto const context = MockVulkanContextBuilder().Build();
45
46 auto const pool1 = context->GetCommandPoolRecycler()->Get();
47 auto const pool2 = context->GetCommandPoolRecycler()->Get();
48
49 // The two command pools should be the same.
50 EXPECT_EQ(pool1.get(), pool2.get());
51
52 context->Shutdown();
53 }

## ◆ TEST() [50/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | ReclaimMakesCommandPoolAvailable |
| ) |  |

Definition at line 107 of file command_pool_vk_unittests.cc.

107 {
108 auto const context = MockVulkanContextBuilder().Build();
109
110 {
111 // Fetch a pool (which will be created).
112 auto const recycler = context->GetCommandPoolRecycler();
113 auto const pool = recycler->Get();
114
115 // This normally is called at the end of a frame.
116 recycler->Dispose();
117 }
118
119 WaitForReclaim(context);
120
121 // On another thread explicitly, request a new pool.
122 std::thread thread([&]() {
123 auto const pool = context->GetCommandPoolRecycler()->Get();
124 EXPECT_NE(pool.get(), nullptr);
125 });
126
127 thread.join();
128
129 // Now check that we only ever created one pool.
130 auto const called = ReclaimAndGetMockVulkanFunctions(context);
131 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
132 1u);
133
134 context->Shutdown();
135 }

## ◆ TEST() [51/574]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | RecyclerGlobalPoolMapSize |
| ) |  |

Definition at line 222 of file command_pool_vk_unittests.cc.

222 {
223 auto context = MockVulkanContextBuilder().Build();
224 auto const recycler = context->GetCommandPoolRecycler();
225
226 // The global pool list for this context should initially be empty.
227 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 0);
228
229 // Creating a pool for this thread should insert the pool into the global map.
230 auto pool = recycler->Get();
231 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 1);
232
233 // Disposing this thread's pool should remove it from the global map.
234 pool.reset();
235 recycler->Dispose();
236 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 0);
237
238 context->Shutdown();
239 }

References impeller::CommandPoolRecyclerVK::GetGlobalPoolCount().

## ◆ TEST() [52/574]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | TestsCriticalSectionAfterWait |
| ) |  |

Definition at line 197 of file base_unittests.cc.

197 {
198 std::vector<std::thread> threads;
199 const auto kThreadCount = 10u;
200
201 Mutex mtx;
202 ConditionVariable cv;
203 size_t sum = 0u;
204
205 std::condition_variable start_cv;
206 std::mutex start_mtx;
207 bool start = false;
208 auto start_predicate = [&start]() { return start; };
209 auto thread_main = [&]() {
210 {
211 std::unique_lock start_lock(start_mtx);
212 start_cv.wait(start_lock, start_predicate);
213 }
214
215 mtx.Lock();
216 cv.Wait(mtx, []() { return true; });
217 auto old_val = sum;
218 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
219 sum = old_val + 1u;
220 mtx.Unlock();
221 };
222 // Launch all threads. They will wait for the start CV to be signaled.
223 threads.reserve(kThreadCount);
224 for (size_t i = 0; i < kThreadCount; i++) {
225 threads.emplace_back(thread_main);
226 }
227 // Notify all threads that the test may start.
228 {
229 {
230 std::scoped_lock start_lock(start_mtx);
231 start = true;
232 }
233 start_cv.notify_all();
234 }
235 // Join all threads.
236 ASSERT_EQ(threads.size(), kThreadCount);
237 for (size_t i = 0; i < kThreadCount; i++) {
238 threads[i].join();
239 }
240 ASSERT_EQ(sum, kThreadCount);
241 }

References start, and impeller::ConditionVariable::Wait().

## ◆ TEST() [53/574]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | TestsCriticalSectionAfterWaitForUntil |
| ) |  |

Definition at line 151 of file base_unittests.cc.

151 {
152 std::vector<std::thread> threads;
153 const auto kThreadCount = 10u;
154
155 Mutex mtx;
156 ConditionVariable cv;
157 size_t sum = 0u;
158
159 std::condition_variable start_cv;
160 std::mutex start_mtx;
161 bool start = false;
162 auto start_predicate = [&start]() { return start; };
163 auto thread_main = [&]() {
164 {
165 std::unique_lock start_lock(start_mtx);
166 start_cv.wait(start_lock, start_predicate);
167 }
168
169 mtx.Lock();
170 cv.WaitFor(mtx, std::chrono::milliseconds{0u}, []() { return true; });
171 auto old_val = sum;
172 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
173 sum = old_val + 1u;
174 mtx.Unlock();
175 };
176 // Launch all threads. They will wait for the start CV to be signaled.
177 threads.reserve(kThreadCount);
178 for (size_t i = 0; i < kThreadCount; i++) {
179 threads.emplace_back(thread_main);
180 }
181 // Notify all threads that the test may start.
182 {
183 {
184 std::scoped_lock start_lock(start_mtx);
185 start = true;
186 }
187 start_cv.notify_all();
188 }
189 // Join all threads.
190 ASSERT_EQ(threads.size(), kThreadCount);
191 for (size_t i = 0; i < kThreadCount; i++) {
192 threads[i].join();
193 }
194 ASSERT_EQ(sum, kThreadCount);
195 }

References start, and impeller::ConditionVariable::WaitFor().

## ◆ TEST() [54/574]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitFor |
| ) |  |

Definition at line 113 of file base_unittests.cc.

113 {
114 CVTest test;
115 // test.rando_ivar = 12; // <--- Static analysis error
116 for (size_t i = 0; i < 2; ++i) {
117 test.mutex.Lock(); // <--- Static analysis error without this.
118 auto result = test.cv.WaitFor(
119 test.mutex, std::chrono::milliseconds{10},
120 [&]() IPLR_REQUIRES(test.mutex) {
121 test.rando_ivar = 12; // <-- Static analysics error without the
122 // IPLR_REQUIRES on the pred.
123 return false;
124 });
125 test.mutex.Unlock();
126 ASSERT_FALSE(result);
127 }
128 Lock lock(test.mutex); // <--- Static analysis error without this.
129 // The predicate never returns true. So return has to be due to a non-spurious
130 // wake.
131 ASSERT_EQ(test.rando_ivar, 12u);
132 }
IPLR_REQUIRES
#define IPLR_REQUIRES(...)
Definition: thread_safety.h:30

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::WaitFor().

## ◆ TEST() [55/574]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitForever |
| ) |  |

Definition at line 134 of file base_unittests.cc.

134 {
135 CVTest test;
136 // test.rando_ivar = 12; // <--- Static analysis error
137 for (size_t i = 0; i < 2; ++i) {
138 test.mutex.Lock(); // <--- Static analysis error without this.
139 test.cv.Wait(test.mutex, [&]() IPLR_REQUIRES(test.mutex) {
140 test.rando_ivar = 12; // <-- Static analysics error without
141 // the IPLR_REQUIRES on the pred.
142 return true;
143 });
144 test.mutex.Unlock();
145 }
146 Lock lock(test.mutex); // <--- Static analysis error without this.
147 // The wake only happens when the predicate returns true.
148 ASSERT_EQ(test.rando_ivar, 12u);
149 }

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::Wait().

## ◆ TEST() [56/574]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitUntil |
| ) |  |

Definition at line 90 of file base_unittests.cc.

90 {
91 CVTest test;
92 // test.rando_ivar = 12; // <--- Static analysis error
93 for (size_t i = 0; i < 2; ++i) {
94 test.mutex.Lock(); // <--- Static analysis error without this.
95 auto result = test.cv.WaitUntil(
96 test.mutex,
97 std::chrono::high_resolution_clock::now() +
98 std::chrono::milliseconds{10},
99 [&]() IPLR_REQUIRES(test.mutex) {
100 test.rando_ivar = 12; // <-- Static analysics error without the
101 // IPLR_REQUIRES on the pred.
102 return false;
103 });
104 test.mutex.Unlock();
105 ASSERT_FALSE(result);
106 }
107 Lock lock(test.mutex); // <--- Static analysis error without this.
108 // The predicate never returns true. So return has to be due to a non-spurious
109 // wake.
110 ASSERT_EQ(test.rando_ivar, 12u);
111 }

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::WaitUntil().

## ◆ TEST() [57/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | AHBSwapchainCapabilitiesCanBeMissing |
| ) |  |

Definition at line 357 of file context_vk_unittests.cc.

357 {
358 {
359 std::shared_ptr<ContextVK> context =
360 MockVulkanContextBuilder()
361 .SetSettingsCallback([](ContextVK::Settings& settings) {
362 settings.enable_surface_control = true;
363 })
364 .Build();
365
366 EXPECT_FALSE(context->GetShouldEnableSurfaceControlSwapchain());
367 }
368
369 ContextVK::EmbedderData data;
370 auto other_context = MockVulkanContextBuilder().Build();
371
372 data.instance = other_context->GetInstance();
373 data.device = other_context->GetDevice();
374 data.physical_device = other_context->GetPhysicalDevice();
375 data.queue = VkQueue{};
376 data.queue_family_index = 0;
377 data.instance_extensions = {"VK_KHR_surface", "VK_KHR_android_surface"};
378 data.device_extensions = {"VK_KHR_swapchain",
379 VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
380 VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
381 VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
382 VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME};
383
384 auto context = MockVulkanContextBuilder()
385 .SetSettingsCallback([](ContextVK::Settings& settings) {
386 settings.enable_surface_control = true;
387 })
388 .SetEmbedderData(data)
389 .Build();
390
391 EXPECT_TRUE(context->GetShouldEnableSurfaceControlSwapchain());
392
393 } // namespace impeller

References data, and impeller::ContextVK::Settings::enable_surface_control.

## ◆ TEST() [58/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | BatchSubmitCommandBuffersOnArm |
| ) |  |

Definition at line 306 of file context_vk_unittests.cc.

306 {
307 std::shared_ptr<ContextVK> context =
308 MockVulkanContextBuilder()
309 .SetPhysicalPropertiesCallback(
310 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
311 prop->vendorID = 0x13B5; // ARM
312 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
313 })
314 .Build();
315
316 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
317 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
318
319 // If command buffers are batch submitted, we should have created them but not
320 // created the fence to track them after enqueing.
321 auto functions = GetMockVulkanFunctions(context->GetDevice());
322 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
323 "vkAllocateCommandBuffers") != functions->end());
324 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
325 "vkCreateFence") == functions->end());
326
327 context->FlushCommandBuffers();
328
329 // After flushing, the fence should be created.
330 functions = GetMockVulkanFunctions(context->GetDevice());
331 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
332 "vkCreateFence") != functions->end());
333 }

## ◆ TEST() [59/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | BatchSubmitCommandBuffersOnNonArm |
| ) |  |

Definition at line 335 of file context_vk_unittests.cc.

335 {
336 std::shared_ptr<ContextVK> context =
337 MockVulkanContextBuilder()
338 .SetPhysicalPropertiesCallback(
339 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
340 prop->vendorID = 0x8686; // Made up ID
341 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
342 })
343 .Build();
344
345 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
346 EXPECT_TRUE(context->EnqueueCommandBuffer(context->CreateCommandBuffer()));
347
348 // If command buffers are batched and not submitted, we should have created
349 // them and a corresponding fence immediately.
350 auto functions = GetMockVulkanFunctions(context->GetDevice());
351 EXPECT_TRUE(std::find(functions->begin(), functions->end(),
352 "vkAllocateCommandBuffers") != functions->end());
353 EXPECT_FALSE(std::find(functions->begin(), functions->end(),
354 "vkCreateFence") != functions->end());
355 }

## ◆ TEST() [60/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | CanCreateContextInAbsenceOfValidationLayers |
| ) |  |

Definition at line 152 of file context_vk_unittests.cc.

152 {
153 // The mocked methods don't report the presence of a validation layer but we
154 // explicitly ask for validation. Context creation should continue anyway.
155 auto context = MockVulkanContextBuilder()
156 .SetSettingsCallback([](auto& settings) {
157 settings.enable_validation = true;
158 })
159 .Build();
160 ASSERT_NE(context, nullptr);
161 const CapabilitiesVK* capabilites_vk =
162 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
163 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
164 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [61/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | CanCreateContextWithValidationLayers |
| ) |  |

Definition at line 166 of file context_vk_unittests.cc.

166 {
167 auto context =
168 MockVulkanContextBuilder()
169 .SetSettingsCallback(
170 [](auto& settings) { settings.enable_validation = true; })
171 .SetInstanceExtensions(
172 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
173 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
174 .Build();
175 ASSERT_NE(context, nullptr);
176 const CapabilitiesVK* capabilites_vk =
177 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
178 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
179 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [62/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | CommonHardwareConcurrencyConfigurations |
| ) |  |

Definition at line 17 of file context_vk_unittests.cc.

17 {
18 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(100u), 4u);
19 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(9u), 4u);
20 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(8u), 4u);
21 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(7u), 3u);
22 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(6u), 3u);
23 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(5u), 2u);
24 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(4u), 2u);
25 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(3u), 1u);
26 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(2u), 1u);
27 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(1u), 1u);
28 }

References impeller::ContextVK::ChooseThreadCountForWorkers().

## ◆ TEST() [63/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletePipelineAfterContext |
| ) |  |

Definition at line 95 of file context_vk_unittests.cc.

95 {
96 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
97 std::shared_ptr<std::vector<std::string>> functions;
98 {
99 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
100 PipelineDescriptor pipeline_desc;
101 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
102 PipelineFuture<PipelineDescriptor> pipeline_future =
103 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
104 pipeline = pipeline_future.Get();
105 ASSERT_TRUE(pipeline);
106 functions = GetMockVulkanFunctions(context->GetDevice());
107 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
108 "vkCreateGraphicsPipelines") != functions->end());
109 }
110 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
111 "vkDestroyDevice") != functions->end());
112 }

References impeller::PipelineFuture< T >::Get(), and impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [64/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletePipelineLibraryAfterContext |
| ) |  |

Definition at line 136 of file context_vk_unittests.cc.

136 {
137 std::shared_ptr<PipelineLibrary> pipeline_library;
138 std::shared_ptr<std::vector<std::string>> functions;
139 {
140 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
141 PipelineDescriptor pipeline_desc;
142 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
143 pipeline_library = context->GetPipelineLibrary();
144 functions = GetMockVulkanFunctions(context->GetDevice());
145 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
146 "vkCreatePipelineCache") != functions->end());
147 }
148 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
149 "vkDestroyDevice") != functions->end());
150 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [65/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletesCommandPools |
| ) |  |

Definition at line 30 of file context_vk_unittests.cc.

30 {
31 std::weak_ptr<ContextVK> weak_context;
32 std::weak_ptr<CommandPoolVK> weak_pool;
33 {
34 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
35 auto const pool = context->GetCommandPoolRecycler()->Get();
36 weak_pool = pool;
37 weak_context = context;
38 ASSERT_TRUE(weak_pool.lock());
39 ASSERT_TRUE(weak_context.lock());
40 }
41 ASSERT_FALSE(weak_pool.lock());
42 ASSERT_FALSE(weak_context.lock());
43 }

## ◆ TEST() [66/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletesCommandPoolsOnAllThreads |
| ) |  |

Definition at line 45 of file context_vk_unittests.cc.

45 {
46 std::weak_ptr<ContextVK> weak_context;
47 std::weak_ptr<CommandPoolVK> weak_pool_main;
48
49 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
50 weak_pool_main = context->GetCommandPoolRecycler()->Get();
51 weak_context = context;
52 ASSERT_TRUE(weak_pool_main.lock());
53 ASSERT_TRUE(weak_context.lock());
54
55 // Start a second thread that obtains a command pool.
56 fml::AutoResetWaitableEvent latch1, latch2;
57 std::weak_ptr<CommandPoolVK> weak_pool_thread;
58 std::thread thread([&]() {
59 weak_pool_thread = context->GetCommandPoolRecycler()->Get();
60 latch1.Signal();
61 latch2.Wait();
62 });
63
64 // Delete the ContextVK on the main thread.
65 latch1.Wait();
66 context.reset();
67 ASSERT_FALSE(weak_pool_main.lock());
68 ASSERT_FALSE(weak_context.lock());
69
70 // Stop the second thread and check that its command pool has been deleted.
71 latch2.Signal();
72 thread.join();
73 ASSERT_FALSE(weak_pool_thread.lock());
74 }

## ◆ TEST() [67/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeleteShaderFunctionAfterContext |
| ) |  |

Definition at line 114 of file context_vk_unittests.cc.

114 {
115 std::shared_ptr<const ShaderFunction> shader_function;
116 std::shared_ptr<std::vector<std::string>> functions;
117 {
118 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
119 PipelineDescriptor pipeline_desc;
120 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
121 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
122 context->GetShaderLibrary()->RegisterFunction(
123 "foobar_fragment_main", ShaderStage::kFragment,
124 std::make_shared<fml::DataMapping>(data), [](bool) {});
125 shader_function = context->GetShaderLibrary()->GetFunction(
126 "foobar_fragment_main", ShaderStage::kFragment);
127 ASSERT_TRUE(shader_function);
128 functions = GetMockVulkanFunctions(context->GetDevice());
129 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
130 "vkCreateShaderModule") != functions->end());
131 }
132 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
133 "vkDestroyDevice") != functions->end());
134 }

References data, impeller::kFragment, and impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [68/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | EmbedderOverrides |
| ) |  |

Definition at line 283 of file context_vk_unittests.cc.

283 {
284 ContextVK::EmbedderData data;
285 auto other_context = MockVulkanContextBuilder().Build();
286
287 data.instance = other_context->GetInstance();
288 data.device = other_context->GetDevice();
289 data.physical_device = other_context->GetPhysicalDevice();
290 data.queue = VkQueue{};
291 data.queue_family_index = 0;
292 data.instance_extensions = {"VK_KHR_surface",
293 "VK_KHR_portability_enumeration"};
294 data.device_extensions = {"VK_KHR_swapchain"};
295
296 auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
297
298 EXPECT_TRUE(context->IsValid());
299 EXPECT_EQ(context->GetInstance(), other_context->GetInstance());
300 EXPECT_EQ(context->GetDevice(), other_context->GetDevice());
301 EXPECT_EQ(context->GetPhysicalDevice(), other_context->GetPhysicalDevice());
302 EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().index, 0u);
303 EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().family, 0u);
304 }

References data.

## ◆ TEST() [69/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | EmbedderOverridesUsesInstanceExtensions |
| ) |  |

Definition at line 264 of file context_vk_unittests.cc.

264 {
265 ContextVK::EmbedderData data;
266 auto other_context = MockVulkanContextBuilder().Build();
267
268 data.instance = other_context->GetInstance();
269 data.device = other_context->GetDevice();
270 data.physical_device = other_context->GetPhysicalDevice();
271 data.queue = VkQueue{};
272 data.queue_family_index = 0;
273 // Missing surface extension.
274 data.instance_extensions = {};
275 data.device_extensions = {"VK_KHR_swapchain"};
276
277 ScopedValidationDisable scoped;
278 auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
279
280 EXPECT_EQ(context, nullptr);
281 }

References data.

## ◆ TEST() [70/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | FatalMissingValidations |
| ) |  |

Definition at line 245 of file context_vk_unittests.cc.

245 {
246 EXPECT_DEATH(const std::shared_ptr<ContextVK> context =
247 MockVulkanContextBuilder()
248 .SetSettingsCallback([](ContextVK::Settings& settings) {
249 settings.enable_validation = true;
250 settings.fatal_missing_validations = true;
251 })
252 .Build(),
253 "");
254 }

References impeller::ContextVK::Settings::enable_validation, and impeller::ContextVK::Settings::fatal_missing_validations.

## ◆ TEST() [71/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | HasDefaultColorFormat |
| ) |  |

Definition at line 256 of file context_vk_unittests.cc.

256 {
257 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
258
259 const CapabilitiesVK* capabilites_vk =
260 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
261 ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
262 }

References impeller::CapabilitiesVK::GetDefaultColorFormat(), and impeller::kUnknown.

## ◆ TEST() [72/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | HashIsUniqueAcrossThreads |
| ) |  |

Definition at line 395 of file context_vk_unittests.cc.

395 {
396 uint64_t hash1, hash2;
397 std::thread thread1([&]() {
398 auto context = MockVulkanContextBuilder().Build();
399 hash1 = context->GetHash();
400 });
401 std::thread thread2([&]() {
402 auto context = MockVulkanContextBuilder().Build();
403 hash2 = context->GetHash();
404 });
405 thread1.join();
406 thread2.join();
407
408 EXPECT_NE(hash1, hash2);
409 }

## ◆ TEST() [73/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | ThreadLocalCleanupDeletesCommandPool |
| ) |  |

Definition at line 76 of file context_vk_unittests.cc.

76 {
77 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
78
79 fml::AutoResetWaitableEvent latch1, latch2;
80 std::weak_ptr<CommandPoolVK> weak_pool;
81 std::thread thread([&]() {
82 weak_pool = context->GetCommandPoolRecycler()->Get();
83 context->DisposeThreadLocalCachedResources();
84 latch1.Signal();
85 latch2.Wait();
86 });
87
88 latch1.Wait();
89 ASSERT_FALSE(weak_pool.lock());
90
91 latch2.Signal();
92 thread.join();
93 }

## ◆ TEST() [74/574]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | WarmUpFunctionCreatesRenderPass |
| ) |  |

Definition at line 234 of file context_vk_unittests.cc.

234 {
235 const std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
236
237 context->SetOffscreenFormat(PixelFormat::kR8G8B8A8UNormInt);
238 context->InitializeCommonlyUsedShadersIfNeeded();
239
240 auto functions = GetMockVulkanFunctions(context->GetDevice());
241 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
242 "vkCreateRenderPass") != functions->end());
243 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST() [75/574]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | DescriptorsAreRecycled |
| ) |  |

Definition at line 110 of file descriptor_pool_vk_unittests.cc.

110 {
111 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
112
113 {
114 DescriptorPoolVK pool = DescriptorPoolVK(context);
115 pool.AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
116 }
117
118 // Should reuse the same descriptor set allocated above.
119 std::shared_ptr<DescriptorPoolVK> pool =
120 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
121 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
122
123 std::shared_ptr<std::vector<std::string>> called =
124 GetMockVulkanFunctions(context->GetDevice());
125 EXPECT_EQ(
126 std::count(called->begin(), called->end(), "vkAllocateDescriptorSets"),
127 1);
128
129 // Should allocate a new descriptor set.
130 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
131 EXPECT_EQ(
132 std::count(called->begin(), called->end(), "vkAllocateDescriptorSets"),
133 2);
134 }

References impeller::DescriptorPoolVK::AllocateDescriptorSets().

## ◆ TEST() [76/574]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | GetDescriptorPoolRecyclerCreatesNewPools |
| ) |  |

Definition at line 13 of file descriptor_pool_vk_unittests.cc.

13 {
14 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
15
16 vk::UniqueDescriptorPool pool1 = context->GetDescriptorPoolRecycler()->Get();
17 vk::UniqueDescriptorPool pool2 = context->GetDescriptorPoolRecycler()->Get();
18
19 // The two descriptor pools should be different.
20 EXPECT_NE(pool1.get(), pool2.get());
21
22 context->Shutdown();
23 }

## ◆ TEST() [77/574]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | MultipleCommandBuffersShareDescriptorPool |
| ) |  |

Definition at line 88 of file descriptor_pool_vk_unittests.cc.

88 {
89 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
90
91 std::shared_ptr<CommandBuffer> cmd_buffer_1 = context->CreateCommandBuffer();
92 std::shared_ptr<CommandBuffer> cmd_buffer_2 = context->CreateCommandBuffer();
93
94 CommandBufferVK& vk_1 = CommandBufferVK::Cast(*cmd_buffer_1);
95 CommandBufferVK& vk_2 = CommandBufferVK::Cast(*cmd_buffer_2);
96
97 EXPECT_EQ(&vk_1.GetDescriptorPool(), &vk_2.GetDescriptorPool());
98
99 // Resetting resources creates a new pool.
100 context->DisposeThreadLocalCachedResources();
101
102 std::shared_ptr<CommandBuffer> cmd_buffer_3 = context->CreateCommandBuffer();
103 CommandBufferVK& vk_3 = CommandBufferVK::Cast(*cmd_buffer_3);
104
105 EXPECT_NE(&vk_1.GetDescriptorPool(), &vk_3.GetDescriptorPool());
106
107 context->Shutdown();
108 }

References impeller::BackendCast< CommandBufferVK, CommandBuffer >::Cast(), and impeller::CommandBufferVK::GetDescriptorPool().

## ◆ TEST() [78/574]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | ReclaimDropsDescriptorPoolIfSizeIsExceeded |
| ) |  |

Definition at line 46 of file descriptor_pool_vk_unittests.cc.

46 {
47 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
48
49 // Create 33 pools
50 {
51 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
52 for (size_t i = 0u; i < 33; i++) {
53 std::unique_ptr<DescriptorPoolVK> pool =
54 std::make_unique<DescriptorPoolVK>(context);
55 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
56 pools.push_back(std::move(pool));
57 }
58 }
59
60 std::shared_ptr<std::vector<std::string>> called =
61 GetMockVulkanFunctions(context->GetDevice());
62 EXPECT_EQ(
63 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
64 33u);
65
66 // Now create 33 more descriptor pools and observe that only one more is
67 // allocated.
68 {
69 std::vector<std::shared_ptr<DescriptorPoolVK>> pools;
70 for (size_t i = 0u; i < 33; i++) {
71 std::shared_ptr<DescriptorPoolVK> pool =
72 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
73 pool->AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
74 pools.push_back(std::move(pool));
75 }
76 }
77
78 std::shared_ptr<std::vector<std::string>> called_twice =
79 GetMockVulkanFunctions(context->GetDevice());
80 // 32 of the descriptor pools were recycled, so only one more is created.
81 EXPECT_EQ(
82 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
83 34u);
84
85 context->Shutdown();
86 }

## ◆ TEST() [79/574]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | ReclaimMakesDescriptorPoolAvailable |
| ) |  |

Definition at line 25 of file descriptor_pool_vk_unittests.cc.

25 {
26 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
27
28 {
29 // Fetch a pool (which will be created).
30 DescriptorPoolVK pool = DescriptorPoolVK(context);
31 pool.AllocateDescriptorSets({}, /*pipeline_key=*/0, *context);
32 }
33
34 std::shared_ptr<DescriptorPoolVK> pool =
35 context->GetDescriptorPoolRecycler()->GetDescriptorPool();
36
37 // Now check that we only ever created one pool.
38 std::shared_ptr<std::vector<std::string>> called =
39 GetMockVulkanFunctions(context->GetDevice());
40 EXPECT_EQ(
41 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
42
43 context->Shutdown();
44 }

References impeller::DescriptorPoolVK::AllocateDescriptorSets().

## ◆ TEST() [80/574]

impeller::testing::TEST | ( | DeviceBufferGLESTest | ,
|  | BindUniformData |
| ) |  |

Definition at line 25 of file device_buffer_gles_unittests.cc.

25 {
26 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
27
28 EXPECT_CALL(*mock_gles_impl, GenBuffers(1, _)).Times(1);
29
30 std::shared_ptr<MockGLES> mock_gled =
31 MockGLES::Init(std::move(mock_gles_impl));
32 ProcTableGLES::Resolver resolver = kMockResolverGLES;
33 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
34 auto worker = std::make_shared<TestWorker>();
35 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
36 reactor->AddWorker(worker);
37
38 std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
39 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
40 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
41 reactor, backing_store);
42 EXPECT_FALSE(device_buffer.GetHandle().has_value());
43 EXPECT_TRUE(device_buffer.BindAndUploadDataIfNecessary(
44 DeviceBufferGLES::BindingType::kUniformBuffer));
45 EXPECT_TRUE(device_buffer.GetHandle().has_value());
46 }

References impeller::DeviceBufferGLES::kUniformBuffer, and impeller::DeviceBufferDescriptor::size.

## ◆ TEST() [81/574]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsRespectsSkipCounts |
| ) |  |

Definition at line 89 of file draw_order_resolver_unittests.cc.

89 {
90 DrawOrderResolver resolver;
91
92 // These items will be skipped.
93 resolver.AddElement(0, false);
94 resolver.AddElement(1, true);
95 resolver.AddElement(2, false);
96 // These ones will be included in the final draw list.
97 resolver.AddElement(3, false);
98 resolver.AddElement(4, true);
99 resolver.AddElement(5, true);
100
101 // Form the draw list, skipping elements 0, 1, and 2.
102 // This emulates what happens when entitypass applies the clear color
103 // optimization.
104 auto sorted_elements = resolver.GetSortedDraws(1, 2);
105
106 EXPECT_EQ(sorted_elements.size(), 3u);
107 // First, opaque items are drawn in reverse order.
108 EXPECT_EQ(sorted_elements[0], 5u);
109 EXPECT_EQ(sorted_elements[1], 4u);
110 // Then, translucent items are drawn.
111 EXPECT_EQ(sorted_elements[2], 3u);
112 }

References impeller::DrawOrderResolver::AddElement(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [82/574]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithClips |
| ) |  |

Definition at line 33 of file draw_order_resolver_unittests.cc.

33 {
34 DrawOrderResolver resolver;
35
36 // Items before clip.
37 resolver.AddElement(0, false);
38 resolver.AddElement(1, true);
39 resolver.AddElement(2, false);
40 resolver.AddElement(3, true);
41
42 // Clip.
43 resolver.PushClip(4);
44 {
45 // Clipped items.
46 resolver.AddElement(5, false);
47 resolver.AddElement(6, false);
48 // Clipped translucent items.
49 resolver.AddElement(7, true);
50 resolver.AddElement(8, true);
51 }
52 resolver.PopClip();
53
54 // Items after clip.
55 resolver.AddElement(9, true);
56 resolver.AddElement(10, false);
57 resolver.AddElement(11, true);
58 resolver.AddElement(12, false);
59
60 auto sorted_elements = resolver.GetSortedDraws(0, 0);
61
62 EXPECT_EQ(sorted_elements.size(), 13u);
63 // First, all the non-clipped opaque items are drawn in reverse order.
64 EXPECT_EQ(sorted_elements[0], 11u);
65 EXPECT_EQ(sorted_elements[1], 9u);
66 EXPECT_EQ(sorted_elements[2], 3u);
67 EXPECT_EQ(sorted_elements[3], 1u);
68 // Then, non-clipped translucent items that came before the clip are drawn in
69 // their original order.
70 EXPECT_EQ(sorted_elements[4], 0u);
71 EXPECT_EQ(sorted_elements[5], 2u);
72
73 // Then, the clip and its sorted child items are drawn.
74 EXPECT_EQ(sorted_elements[6], 4u);
75 {
76 // Opaque clipped items are drawn in reverse order.
77 EXPECT_EQ(sorted_elements[7], 8u);
78 EXPECT_EQ(sorted_elements[8], 7u);
79 // Translucent clipped items are drawn.
80 EXPECT_EQ(sorted_elements[9], 5u);
81 EXPECT_EQ(sorted_elements[10], 6u);
82 }
83 // Finally, the non-clipped translucent items which came after the clip are
84 // drawn in their original order.
85 EXPECT_EQ(sorted_elements[11], 10u);
86 EXPECT_EQ(sorted_elements[12], 12u);
87 }

References impeller::DrawOrderResolver::AddElement(), impeller::DrawOrderResolver::GetSortedDraws(), impeller::DrawOrderResolver::PopClip(), and impeller::DrawOrderResolver::PushClip().

## ◆ TEST() [83/574]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithFlush |
| ) |  |

Definition at line 114 of file draw_order_resolver_unittests.cc.

114 {
115 DrawOrderResolver resolver;
116
117 resolver.AddElement(0, false);
118 resolver.AddElement(1, true);
119 resolver.AddElement(2, false);
120 resolver.AddElement(3, true);
121
122 resolver.Flush();
123
124 resolver.AddElement(4, false);
125 resolver.AddElement(5, true);
126 resolver.AddElement(6, false);
127 resolver.AddElement(7, true);
128
129 resolver.Flush();
130
131 resolver.AddElement(8, false);
132 resolver.AddElement(9, true);
133 resolver.AddElement(10, false);
134 resolver.AddElement(11, true);
135
136 auto sorted_elements = resolver.GetSortedDraws(1, 1);
137
138 EXPECT_EQ(sorted_elements.size(), 10u);
139
140 // Skipped draws apply to the first flush.
141 EXPECT_EQ(sorted_elements[0], 3u);
142 EXPECT_EQ(sorted_elements[1], 2u);
143
144 EXPECT_EQ(sorted_elements[2], 7u);
145 EXPECT_EQ(sorted_elements[3], 5u);
146 EXPECT_EQ(sorted_elements[4], 4u);
147 EXPECT_EQ(sorted_elements[5], 6u);
148
149 EXPECT_EQ(sorted_elements[6], 11u);
150 EXPECT_EQ(sorted_elements[7], 9u);
151 EXPECT_EQ(sorted_elements[8], 8u);
152 EXPECT_EQ(sorted_elements[9], 10u);
153 }

References impeller::DrawOrderResolver::AddElement(), impeller::DrawOrderResolver::Flush(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [84/574]

impeller::testing::TEST | ( | DrawOrderResolverTest | ,
|  | GetSortedDrawsReturnsCorrectOrderWithNoClips |
| ) |  |

Definition at line 12 of file draw_order_resolver_unittests.cc.

12 {
13 DrawOrderResolver resolver;
14
15 // Opaque items.
16 resolver.AddElement(0, true);
17 resolver.AddElement(1, true);
18 // Translucent items.
19 resolver.AddElement(2, false);
20 resolver.AddElement(3, false);
21
22 auto sorted_elements = resolver.GetSortedDraws(0, 0);
23
24 EXPECT_EQ(sorted_elements.size(), 4u);
25 // First, the opaque items are drawn in reverse order.
26 EXPECT_EQ(sorted_elements[0], 1u);
27 EXPECT_EQ(sorted_elements[1], 0u);
28 // Then the translucent items are drawn.
29 EXPECT_EQ(sorted_elements[2], 2u);
30 EXPECT_EQ(sorted_elements[3], 3u);
31 }

References impeller::DrawOrderResolver::AddElement(), and impeller::DrawOrderResolver::GetSortedDraws().

## ◆ TEST() [85/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanBatchSubmitCommandBuffers |
| ) |  |

Definition at line 90 of file driver_info_vk_unittests.cc.

90 {
91 // Old Adreno no batch submit!
92 EXPECT_FALSE(CanBatchSubmitTest("Adreno (TM) 540", true));
93
94 EXPECT_TRUE(CanBatchSubmitTest("Mali-G51", false));
95 EXPECT_TRUE(CanBatchSubmitTest("Adreno (TM) 750", true));
96 }
impeller::testing::CanBatchSubmitTest
bool CanBatchSubmitTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:71

References CanBatchSubmitTest().

## ◆ TEST() [86/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanGenerateMipMaps |
| ) |  |

Definition at line 146 of file driver_info_vk_unittests.cc.

146 {
147 // Adreno no mips
148 EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 540", true));
149 EXPECT_FALSE(CanUseMipgeneration("Adreno (TM) 750", true));
150
151 // Mali A-OK
152 EXPECT_TRUE(CanUseMipgeneration("Mali-G51", false));
153 }
impeller::testing::CanUseMipgeneration
bool CanUseMipgeneration(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:127

References CanUseMipgeneration().

## ◆ TEST() [87/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanIdentifyBadMaleoonDriver |
| ) |  |

Definition at line 40 of file driver_info_vk_unittests.cc.

40 {
41 auto const context =
42 MockVulkanContextBuilder()
43 .SetPhysicalPropertiesCallback(
44 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
45 prop->vendorID = 0x19E5; // Huawei
46 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
47 })
48 .Build();
49
50 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
51 }

## ◆ TEST() [88/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanUseFramebufferFetch |
| ) |  |

Definition at line 216 of file driver_info_vk_unittests.cc.

216 {
217 // Adreno no primitive restart on models as or older than 630.
218 EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 540", true));
219 EXPECT_FALSE(CanUseFramebufferFetch("Adreno (TM) 630", true));
220
221 EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 640", true));
222 EXPECT_TRUE(CanUseFramebufferFetch("Adreno (TM) 750", true));
223 EXPECT_TRUE(CanUseFramebufferFetch("Mali-G51", false));
224 }
impeller::testing::CanUseFramebufferFetch
bool CanUseFramebufferFetch(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:197

References CanUseFramebufferFetch().

## ◆ TEST() [89/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | CanUsePrimitiveRestart |
| ) |  |

Definition at line 118 of file driver_info_vk_unittests.cc.

118 {
119 // Adreno no primitive restart
120 EXPECT_FALSE(CanUsePrimitiveRestartSubmitTest("Adreno (TM) 540", true));
121 EXPECT_FALSE(CanUsePrimitiveRestartSubmitTest("Adreno (TM) 750", true));
122
123 // Mali A-OK
124 EXPECT_TRUE(CanUsePrimitiveRestartSubmitTest("Mali-G51", false));
125 }
impeller::testing::CanUsePrimitiveRestartSubmitTest
bool CanUsePrimitiveRestartSubmitTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:98

References CanUsePrimitiveRestartSubmitTest().

## ◆ TEST() [90/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DisabledDevices |
| ) |  |

Definition at line 166 of file driver_info_vk_unittests.cc.

166 {
167 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 504"));
168 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 505"));
169 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 506"));
170 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 508"));
171 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 509"));
172 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 512"));
173 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 530"));
174 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 610"));
175 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 620"));
176 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 630"));
177 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 640"));
178 EXPECT_TRUE(IsBadVersionTest("Adreno (TM) 650"));
179 }
impeller::testing::IsBadVersionTest
bool IsBadVersionTest(std::string_view driver_name, bool qc=true)
Definition: driver_info_vk_unittests.cc:53

References IsBadVersionTest().

## ◆ TEST() [91/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DisableOldXclipseDriver |
| ) |  |

Definition at line 226 of file driver_info_vk_unittests.cc.

226 {
227 auto context =
228 MockVulkanContextBuilder()
229 .SetPhysicalPropertiesCallback(
230 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
231 prop->vendorID = 0x144D; // Samsung
232 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
233 // Version 1.1.0
234 prop->apiVersion = (1 << 22) | (1 << 12);
235 })
236 .Build();
237
238 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
239
240 context =
241 MockVulkanContextBuilder()
242 .SetPhysicalPropertiesCallback(
243 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
244 prop->vendorID = 0x144D; // Samsung
245 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
246 // Version 1.3.0
247 prop->apiVersion = (1 << 22) | (3 << 12);
248 })
249 .Build();
250
251 EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver());
252 }

## ◆ TEST() [92/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DriverParsingAdreno |
| ) |  |

Definition at line 161 of file driver_info_vk_unittests.cc.

161 {
162 EXPECT_EQ(GetAdrenoVersion("Adreno (TM) 540"), AdrenoGPU::kAdreno540);
163 EXPECT_EQ(GetAdrenoVersion("Foo Bar"), AdrenoGPU::kUnknown);
164 }
impeller::GetAdrenoVersion
AdrenoGPU GetAdrenoVersion(std::string_view version)
Definition: driver_info_vk.cc:134

References impeller::GetAdrenoVersion(), impeller::kAdreno540, and impeller::kUnknown.

## ◆ TEST() [93/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | DriverParsingMali |
| ) |  |

Definition at line 155 of file driver_info_vk_unittests.cc.

155 {
156 EXPECT_EQ(GetMaliVersion("Mali-G51-MORE STUFF"), MaliGPU::kG51);
157 EXPECT_EQ(GetMaliVersion("Mali-G51"), MaliGPU::kG51);
158 EXPECT_EQ(GetMaliVersion("Mali-111111"), MaliGPU::kUnknown);
159 }
impeller::GetMaliVersion
MaliGPU GetMaliVersion(std::string_view version)
Definition: driver_info_vk.cc:158

References impeller::GetMaliVersion(), impeller::kG51, and impeller::kUnknown.

## ◆ TEST() [94/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | EnabledDevicesAdreno |
| ) |  |

Definition at line 186 of file driver_info_vk_unittests.cc.

186 {
187 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 702"));
188 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 710"));
189 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 720"));
190 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 725"));
191 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 730"));
192 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 732"));
193 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 740"));
194 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 750"));
195 }

References IsBadVersionTest().

## ◆ TEST() [95/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | EnabledDevicesMali |
| ) |  |

Definition at line 181 of file driver_info_vk_unittests.cc.

181 {
182 EXPECT_FALSE(IsBadVersionTest("Mali-G52", /*qc=*/false));
183 EXPECT_FALSE(IsBadVersionTest("Mali-G54-MORE STUFF", /*qc=*/false));
184 }

References IsBadVersionTest().

## ◆ TEST() [96/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | NewPowerVREnabled |
| ) |  |

Definition at line 271 of file driver_info_vk_unittests.cc.

271 {
272 std::shared_ptr<ContextVK> context =
273 MockVulkanContextBuilder()
274 .SetPhysicalPropertiesCallback(
275 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
276 prop->vendorID = 0x1010;
277 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
278 std::string name = "PowerVR DXT 123";
279 name.copy(prop->deviceName, name.size());
280 })
281 .Build();
282
283 EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver());
284 EXPECT_EQ(context->GetDriverInfo()->GetPowerVRGPUInfo(),
285 std::optional<PowerVRGPU>(PowerVRGPU::kDXT));
286 EXPECT_TRUE(GetWorkaroundsFromDriverInfo(*context->GetDriverInfo())
287 .input_attachment_self_dependency_broken);
288 }

References impeller::GetWorkaroundsFromDriverInfo(), impeller::WorkaroundsVK::input_attachment_self_dependency_broken, and impeller::kDXT.

## ◆ TEST() [97/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | OldPowerVRDisabled |
| ) |  |

Definition at line 254 of file driver_info_vk_unittests.cc.

254 {
255 std::shared_ptr<ContextVK> context =
256 MockVulkanContextBuilder()
257 .SetPhysicalPropertiesCallback(
258 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
259 prop->vendorID = 0x1010;
260 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
261 std::string name = "PowerVR Rogue GE8320";
262 name.copy(prop->deviceName, name.size());
263 })
264 .Build();
265
266 EXPECT_TRUE(context->GetDriverInfo()->IsKnownBadDriver());
267 EXPECT_EQ(context->GetDriverInfo()->GetPowerVRGPUInfo(),
268 std::optional<PowerVRGPU>(PowerVRGPU::kUnknown));
269 }

References impeller::kUnknown.

## ◆ TEST() [98/574]

impeller::testing::TEST | ( | DriverInfoVKTest | ,
|  | PowerVRBSeries |
| ) |  |

Definition at line 290 of file driver_info_vk_unittests.cc.

290 {
291 std::shared_ptr<ContextVK> context =
292 MockVulkanContextBuilder()
293 .SetPhysicalPropertiesCallback(
294 [](VkPhysicalDevice device, VkPhysicalDeviceProperties* prop) {
295 prop->vendorID = 0x1010;
296 prop->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
297 std::string name = "PowerVR BXM-8-256";
298 name.copy(prop->deviceName, name.size());
299 })
300 .Build();
301
302 EXPECT_FALSE(context->GetDriverInfo()->IsKnownBadDriver());
303 EXPECT_EQ(context->GetDriverInfo()->GetPowerVRGPUInfo(),
304 std::optional<PowerVRGPU>(PowerVRGPU::kBXM));
305 }

References impeller::kBXM.

## ◆ TEST() [99/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | AlphaCoverageStrokePaths |
| ) |  |

Definition at line 543 of file geometry_unittests.cc.

543 {
544 auto matrix = Matrix::MakeScale(Vector2{3.0, 3.0});
545 EXPECT_EQ(Geometry::MakeStrokePath({}, {.width = 0.5f})
546 ->ComputeAlphaCoverage(matrix),
547 1.0f);
548 EXPECT_NEAR(Geometry::MakeStrokePath({}, {.width = 0.1f})
549 ->ComputeAlphaCoverage(matrix),
550 0.6, 0.05);
551 EXPECT_NEAR(Geometry::MakeStrokePath({}, {.width = 0.05})
552 ->ComputeAlphaCoverage(matrix),
553 0.3, 0.05);
554 EXPECT_NEAR(Geometry::MakeStrokePath({}, {.width = 0.01})
555 ->ComputeAlphaCoverage(matrix),
556 0.1, 0.1);
557 EXPECT_NEAR(Geometry::MakeStrokePath({}, {.width = 0.0000005f})
558 ->ComputeAlphaCoverage(matrix),
559 1e-05, 0.001);
560 EXPECT_EQ(Geometry::MakeStrokePath({}, {.width = 0.0f})
561 ->ComputeAlphaCoverage(matrix),
562 1.0f);
563 EXPECT_EQ(Geometry::MakeStrokePath({}, {.width = 40.0f})
564 ->ComputeAlphaCoverage(matrix),
565 1.0f);
566 }
impeller::Vector2
Point Vector2
Definition: point.h:429

References impeller::Matrix::MakeScale(), and impeller::Geometry::MakeStrokePath().

## ◆ TEST() [100/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillArcGeometryCoverage |
| ) |  |

Definition at line 104 of file geometry_unittests.cc.

104 {
105 Rect oval_bounds = Rect::MakeLTRB(100, 100, 200, 200);
106 Matrix transform45 = Matrix::MakeTranslation(oval_bounds.GetCenter()) *
107 Matrix::MakeRotationZ(Degrees(45)) *
108 Matrix::MakeTranslation(-oval_bounds.GetCenter());
109
110 { // Sweeps <=-360 or >=360
111 for (int start = -720; start <= 720; start += 10) {
112 for (int sweep = 360; sweep <= 720; sweep += 30) {
113 std::string label =
114 "start: " + std::to_string(start) + " + " + std::to_string(sweep);
115 auto geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
116 Degrees(sweep), false);
117 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
118 << "start: " << start << ", sweep: " << sweep;
119 geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
120 Degrees(-sweep), false);
121 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
122 << "start: " << start << ", sweep: " << -sweep;
123 geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
124 Degrees(-sweep), true);
125 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
126 << "start: " << start << ", sweep: " << -sweep << ", with center";
127 }
128 }
129 }
130 { // Sweep from late in one quadrant to earlier in same quadrant
131 for (int start = 60; start < 360; start += 90) {
132 auto geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
133 Degrees(330), false);
134 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
135 << "start: " << start << " without center";
136 geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
137 Degrees(330), true);
138 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
139 << "start: " << start << " with center";
140 }
141 }
142 { // Sweep from early in one quadrant backwards to later in same quadrant
143 for (int start = 30; start < 360; start += 90) {
144 auto geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
145 Degrees(-330), false);
146 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
147 << "start: " << start << " without center";
148 geometry = Geometry::MakeFilledArc(oval_bounds, Degrees(start),
149 Degrees(-330), true);
150 EXPECT_EQ(geometry->GetCoverage({}), oval_bounds)
151 << "start: " << start << " with center";
152 }
153 }
154 { // Sweep past each quadrant axis individually, no center
155 for (int start = -360; start <= 720; start += 360) {
156 { // Quadrant 0
157 auto geometry = Geometry::MakeFilledArc(
158 oval_bounds, Degrees(start - 45), Degrees(90), false);
159 Rect expected_bounds = Rect::MakeLTRB(150 + 50 * kSqrt2Over2, //
160 150 - 50 * kSqrt2Over2, //
161 200, //
162 150 + 50 * kSqrt2Over2);
163 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
164 expected_bounds)
165 << "start: " << start - 45;
166 }
167 { // Quadrant 1
168 auto geometry = Geometry::MakeFilledArc(
169 oval_bounds, Degrees(start + 45), Degrees(90), false);
170 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2, //
171 150 + 50 * kSqrt2Over2, //
172 150 + 50 * kSqrt2Over2, //
173 200);
174 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
175 expected_bounds)
176 << "start: " << start + 45;
177 }
178 { // Quadrant 2
179 auto geometry = Geometry::MakeFilledArc(
180 oval_bounds, Degrees(start + 135), Degrees(90), false);
181 Rect expected_bounds = Rect::MakeLTRB(100, //
182 150 - 50 * kSqrt2Over2, //
183 150 - 50 * kSqrt2Over2, //
184 150 + 50 * kSqrt2Over2);
185 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
186 expected_bounds)
187 << "start: " << start + 135;
188 }
189 { // Quadrant 3
190 auto geometry = Geometry::MakeFilledArc(
191 oval_bounds, Degrees(start + 225), Degrees(90), false);
192 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2, //
193 100, //
194 150 + 50 * kSqrt2Over2, //
195 150 - 50 * kSqrt2Over2);
196 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
197 expected_bounds)
198 << "start: " << start + 225;
199 }
200 }
201 }
202 { // Sweep past each quadrant axis individually, including the center
203 for (int start = -360; start <= 720; start += 360) {
204 { // Quadrant 0
205 auto geometry = Geometry::MakeFilledArc(
206 oval_bounds, Degrees(start - 45), Degrees(90), true);
207 Rect expected_bounds = Rect::MakeLTRB(150, //
208 150 - 50 * kSqrt2Over2, //
209 200, //
210 150 + 50 * kSqrt2Over2);
211 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
212 expected_bounds)
213 << "start: " << start - 45;
214 }
215 { // Quadrant 1
216 auto geometry = Geometry::MakeFilledArc(
217 oval_bounds, Degrees(start + 45), Degrees(90), true);
218 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2, //
219 150, //
220 150 + 50 * kSqrt2Over2, //
221 200);
222 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
223 expected_bounds)
224 << "start: " << start + 45;
225 }
226 { // Quadrant 2
227 auto geometry = Geometry::MakeFilledArc(
228 oval_bounds, Degrees(start + 135), Degrees(90), true);
229 Rect expected_bounds = Rect::MakeLTRB(100, //
230 150 - 50 * kSqrt2Over2, //
231 150, //
232 150 + 50 * kSqrt2Over2);
233 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
234 expected_bounds)
235 << "start: " << start + 135;
236 }
237 { // Quadrant 3
238 auto geometry = Geometry::MakeFilledArc(
239 oval_bounds, Degrees(start + 225), Degrees(90), true);
240 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2, //
241 100, //
242 150 + 50 * kSqrt2Over2, //
243 150);
244 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
245 expected_bounds)
246 << "start: " << start + 225;
247 }
248 }
249 }
250 { // 45 degree tilted full circle
251 auto geometry =
252 Geometry::MakeFilledArc(oval_bounds, Degrees(0), Degrees(360), false);
253 ASSERT_TRUE(oval_bounds.TransformBounds(transform45).Contains(oval_bounds));
254
255 EXPECT_TRUE(geometry->GetCoverage(transform45)
256 .value_or(Rect())
257 .Contains(oval_bounds));
258 }
259 { // 45 degree tilted mostly full circle
260 auto geometry =
261 Geometry::MakeFilledArc(oval_bounds, Degrees(3), Degrees(359), false);
262 ASSERT_TRUE(oval_bounds.TransformBounds(transform45).Contains(oval_bounds));
263
264 EXPECT_TRUE(geometry->GetCoverage(transform45)
265 .value_or(Rect())
266 .Contains(oval_bounds));
267 }
268 }
EXPECT_RECT_NEAR
#define EXPECT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:203
impeller::kSqrt2Over2
constexpr float kSqrt2Over2
Definition: constants.h:51
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:788

References impeller::TRect< T >::Contains(), EXPECT_RECT_NEAR, impeller::TRect< T >::GetCenter(), impeller::kSqrt2Over2, impeller::Geometry::MakeFilledArc(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), start, and impeller::TRect< T >::TransformBounds().

## ◆ TEST() [101/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillPathGeometryCoversArea |
| ) |  |

Definition at line 81 of file geometry_unittests.cc.

81 {
82 auto path = flutter::DlPathBuilder{}
83 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
84 .TakePath();
85 auto geometry = Geometry::MakeFillPath(
86 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
87 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
88 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
89 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
90 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
91 }

References impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [102/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillPathGeometryCoversAreaNoInnerRect |
| ) |  |

Definition at line 93 of file geometry_unittests.cc.

93 {
94 auto path = flutter::DlPathBuilder{}
95 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
96 .TakePath();
97 auto geometry = Geometry::MakeFillPath(path);
98 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
99 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
100 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
101 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
102 }

References impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [103/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillRoundRectGeometryCoversArea |
| ) |  |

Definition at line 471 of file geometry_unittests.cc.

471 {
472 Rect bounds = Rect::MakeLTRB(100, 100, 200, 200);
473 RoundRect round_rect =
474 RoundRect::MakeRectRadii(bounds, RoundingRadii{
475 .top_left = Size(1, 11),
476 .top_right = Size(2, 12),
477 .bottom_left = Size(3, 13),
478 .bottom_right = Size(4, 14),
479 });
480 FillRoundRectGeometry geom(round_rect);
481
482 // Tall middle rect should barely be covered.
483 EXPECT_TRUE(geom.CoversArea({}, Rect::MakeLTRB(103, 100, 196, 200)));
484 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(102, 100, 196, 200)));
485 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(103, 99, 196, 200)));
486 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(103, 100, 197, 200)));
487 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(103, 100, 196, 201)));
488
489 // Wide middle rect should barely be covered.
490 EXPECT_TRUE(geom.CoversArea({}, Rect::MakeLTRB(100, 112, 200, 186)));
491 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(99, 112, 200, 186)));
492 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(100, 111, 200, 186)));
493 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(100, 112, 201, 186)));
494 EXPECT_FALSE(geom.CoversArea({}, Rect::MakeLTRB(100, 112, 200, 187)));
495 }
impeller::Size
TSize< Scalar > Size
Definition: size.h:159

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::RoundingRadii::top_left.

## ◆ TEST() [104/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | GeometryResultHasReasonableDefaults |
| ) |  |

Definition at line 536 of file geometry_unittests.cc.

536 {
537 GeometryResult result;
538 EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
539 EXPECT_EQ(result.transform, Matrix());
540 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
541 }

References impeller::GeometryResult::kNormal, impeller::kTriangleStrip, impeller::GeometryResult::mode, impeller::GeometryResult::transform, and impeller::GeometryResult::type.

## ◆ TEST() [105/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | LineGeometryCoverage |
| ) |  |

Definition at line 497 of file geometry_unittests.cc.

497 {
498 {
499 auto geometry = Geometry::MakeLine( //
500 {10, 10}, {20, 10}, {.width = 2, .cap = Cap::kButt});
501 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
502 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
503 }
504
505 {
506 auto geometry = Geometry::MakeLine( //
507 {10, 10}, {20, 10}, {.width = 2, .cap = Cap::kSquare});
508 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
509 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
510 }
511
512 {
513 auto geometry = Geometry::MakeLine( //
514 {10, 10}, {10, 20}, {.width = 2, .cap = Cap::kButt});
515 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
516 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
517 }
518
519 {
520 auto geometry = Geometry::MakeLine( //
521 {10, 10}, {10, 20}, {.width = 2, .cap = Cap::kSquare});
522 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
523 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
524 }
525 }

References impeller::kButt, impeller::kSquare, impeller::Geometry::MakeLine(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [106/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | RectGeometryCoversArea |
| ) |  |

Definition at line 73 of file geometry_unittests.cc.

73 {
74 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
75 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
76 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
77 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
78 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
79 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::Geometry::MakeRect().

## ◆ TEST() [107/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | RotatedFilledCircleGeometryCoverage |
| ) |  |

Definition at line 1315 of file geometry_unittests.cc.

1315 {
1316 Point center = Point(50, 50);
1317 auto geometry = Geometry::MakeCircle(center, 50);
1318 Rect circle_bounds = Rect::MakeLTRB(0, 0, 100, 100);
1319 ASSERT_EQ(geometry->GetCoverage({}).value_or(Rect()), circle_bounds);
1320
1321 Matrix transform45 = Matrix::MakeTranslation(center) *
1322 Matrix::MakeRotationZ(Degrees(45)) *
1323 Matrix::MakeTranslation(-center);
1324
1325 EXPECT_TRUE(geometry->GetCoverage(transform45).has_value());
1326 Rect bounds = geometry->GetCoverage(transform45).value_or(Rect());
1327 EXPECT_TRUE(bounds.Contains(circle_bounds))
1328 << "geometry bounds: " << bounds << std::endl
1329 << " circle bounds: " << circle_bounds;
1330 }

References impeller::TRect< T >::Contains(), impeller::Geometry::MakeCircle(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [108/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | RotatedStrokedCircleGeometryCoverage |
| ) |  |

Definition at line 1332 of file geometry_unittests.cc.

1332 {
1333 Point center = Point(50, 50);
1334 auto geometry = Geometry::MakeStrokedCircle(center, 50, 10);
1335 Rect circle_bounds = Rect::MakeLTRB(0, 0, 100, 100).Expand(5);
1336 ASSERT_EQ(geometry->GetCoverage({}).value_or(Rect()), circle_bounds);
1337
1338 Matrix transform45 = Matrix::MakeTranslation(center) *
1339 Matrix::MakeRotationZ(Degrees(45)) *
1340 Matrix::MakeTranslation(-center);
1341
1342 EXPECT_TRUE(geometry->GetCoverage(transform45).has_value());
1343 Rect bounds = geometry->GetCoverage(transform45).value_or(Rect());
1344 EXPECT_TRUE(bounds.Contains(circle_bounds))
1345 << "geometry bounds: " << bounds << std::endl
1346 << " circle bounds: " << circle_bounds;
1347 }
impeller::TRect::Expand
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:618

References impeller::TRect< T >::Contains(), impeller::TRect< T >::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokedCircle(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [109/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | RoundRectGeometryCoversArea |
| ) |  |

Definition at line 527 of file geometry_unittests.cc.

527 {
528 auto geometry =
529 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
530 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
531 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
532 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
533 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
534 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::Geometry::MakeRoundRect().

## ◆ TEST() [110/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | SimpleTwoLineStrokeVerticesButtCap |
| ) |  |

Definition at line 568 of file geometry_unittests.cc.

568 {
569 flutter::DlPathBuilder path_builder;
570 path_builder.MoveTo({20, 20});
571 path_builder.LineTo({30, 20});
572 path_builder.MoveTo({120, 20});
573 path_builder.LineTo({130, 20});
574 flutter::DlPath path = path_builder.TakePath();
575
576 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
577 path,
578 {
579 .width = 10.0f,
580 .cap = Cap::kButt,
581 .join = Join::kBevel,
582 .miter_limit = 4.0f,
583 },
584 1.0f);
585
586 std::vector<Point> expected = {
587 // The points for the first segment (20, 20) -> (30, 20)
588 Point(20, 25),
589 Point(20, 15),
590 Point(30, 25),
591 Point(30, 15),
592
593 // The glue points that allow us to "pick up the pen" between segments
594 Point(30, 20),
595 Point(30, 20),
596 Point(120, 20),
597 Point(120, 20),
598
599 // The points for the second segment (120, 20) -> (130, 20)
600 Point(120, 25),
601 Point(120, 15),
602 Point(130, 25),
603 Point(130, 15),
604 };
605
606 EXPECT_EQ(points, expected);
607 }
points
std::vector< Point > points
Definition: tessellator_libtess.cc:76

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, and points.

## ◆ TEST() [111/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | SimpleTwoLineStrokeVerticesRoundCap |
| ) |  |

Definition at line 609 of file geometry_unittests.cc.

609 {
610 flutter::DlPathBuilder path_builder;
611 path_builder.MoveTo({20, 20});
612 path_builder.LineTo({30, 20});
613 path_builder.MoveTo({120, 20});
614 path_builder.LineTo({130, 20});
615 flutter::DlPath path = path_builder.TakePath();
616
617 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
618 path,
619 {
620 .width = 10.0f,
621 .cap = Cap::kRound,
622 .join = Join::kBevel,
623 .miter_limit = 4.0f,
624 },
625 1.0f);
626
627 size_t count = points.size();
628 ASSERT_TRUE((count & 0x1) == 0x0); // Should always be even
629
630 // For a scale factor of 1.0 and a stroke width of 10.0 we currently
631 // generate 40 total points for the 2 line segments based on the number
632 // of quadrant circle divisions for a radius of 5.0
633 //
634 // If the number of points changes because of a change in the way we
635 // compute circle divisions, we need to recompute the circular offsets
636 ASSERT_EQ(points.size(), 40u);
637
638 // Compute the indicated circular end cap offset based on the current
639 // step out of 4 divisions [1, 2, 3] (not 0 or 4) based on whether this
640 // is the left or right side of the path and whether this is a backwards
641 // (starting) cap or a forwards (ending) cap.
642 auto offset = [](int step, bool left, bool backwards) -> Point {
643 Radians angle(kPiOver2 * (step / 4.0f));
644 Point along = Point(5.0f, 0.0f) * std::cos(angle.radians);
645 Point across = Point(0.0f, 5.0f) * std::sin(angle.radians);
646 Point center = backwards ? -along : along;
647 return left ? center + across : center - across;
648 };
649
650 // The points for the first segment (20, 20) -> (30, 20)
651 EXPECT_EQ(points[0], Point(15, 20));
652 EXPECT_EQ(points[1], Point(20, 20) + offset(1, true, true));
653 EXPECT_EQ(points[2], Point(20, 20) + offset(1, false, true));
654 EXPECT_EQ(points[3], Point(20, 20) + offset(2, true, true));
655 EXPECT_EQ(points[4], Point(20, 20) + offset(2, false, true));
656 EXPECT_EQ(points[5], Point(20, 20) + offset(3, true, true));
657 EXPECT_EQ(points[6], Point(20, 20) + offset(3, false, true));
658 EXPECT_EQ(points[7], Point(20, 25));
659 EXPECT_EQ(points[8], Point(20, 15));
660 EXPECT_EQ(points[9], Point(30, 25));
661 EXPECT_EQ(points[10], Point(30, 15));
662 EXPECT_EQ(points[11], Point(30, 20) + offset(3, true, false));
663 EXPECT_EQ(points[12], Point(30, 20) + offset(3, false, false));
664 EXPECT_EQ(points[13], Point(30, 20) + offset(2, true, false));
665 EXPECT_EQ(points[14], Point(30, 20) + offset(2, false, false));
666 EXPECT_EQ(points[15], Point(30, 20) + offset(1, true, false));
667 EXPECT_EQ(points[16], Point(30, 20) + offset(1, false, false));
668 EXPECT_EQ(points[17], Point(35, 20));
669
670 // The glue points that allow us to "pick up the pen" between segments
671 EXPECT_EQ(points[18], Point(30, 20));
672 EXPECT_EQ(points[19], Point(30, 20));
673 EXPECT_EQ(points[20], Point(120, 20));
674 EXPECT_EQ(points[21], Point(120, 20));
675
676 // The points for the second segment (120, 20) -> (130, 20)
677 EXPECT_EQ(points[22], Point(115, 20));
678 EXPECT_EQ(points[23], Point(120, 20) + offset(1, true, true));
679 EXPECT_EQ(points[24], Point(120, 20) + offset(1, false, true));
680 EXPECT_EQ(points[25], Point(120, 20) + offset(2, true, true));
681 EXPECT_EQ(points[26], Point(120, 20) + offset(2, false, true));
682 EXPECT_EQ(points[27], Point(120, 20) + offset(3, true, true));
683 EXPECT_EQ(points[28], Point(120, 20) + offset(3, false, true));
684 EXPECT_EQ(points[29], Point(120, 25));
685 EXPECT_EQ(points[30], Point(120, 15));
686 EXPECT_EQ(points[31], Point(130, 25));
687 EXPECT_EQ(points[32], Point(130, 15));
688 EXPECT_EQ(points[33], Point(130, 20) + offset(3, true, false));
689 EXPECT_EQ(points[34], Point(130, 20) + offset(3, false, false));
690 EXPECT_EQ(points[35], Point(130, 20) + offset(2, true, false));
691 EXPECT_EQ(points[36], Point(130, 20) + offset(2, false, false));
692 EXPECT_EQ(points[37], Point(130, 20) + offset(1, true, false));
693 EXPECT_EQ(points[38], Point(130, 20) + offset(1, false, false));
694 EXPECT_EQ(points[39], Point(135, 20));
695 }
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kPiOver2, impeller::kRound, points, and impeller::Radians::radians.

## ◆ TEST() [112/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | SimpleTwoLineStrokeVerticesSquareCap |
| ) |  |

Definition at line 697 of file geometry_unittests.cc.

697 {
698 flutter::DlPathBuilder path_builder;
699 path_builder.MoveTo({20, 20});
700 path_builder.LineTo({30, 20});
701 path_builder.MoveTo({120, 20});
702 path_builder.LineTo({130, 20});
703 flutter::DlPath path = path_builder.TakePath();
704
705 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
706 path,
707 {
708 .width = 10.0f,
709 .cap = Cap::kSquare,
710 .join = Join::kBevel,
711 .miter_limit = 4.0f,
712 },
713 1.0f);
714
715 // clang-format off
716 std::vector<Point> expected = {
717 // The points for the first segment (20, 20) -> (30, 20)
718 Point(15, 25),
719 Point(15, 15),
720 Point(20, 25),
721 Point(20, 15),
722 Point(30, 25),
723 Point(30, 15),
724 Point(35, 25),
725 Point(35, 15),
726
727 // The glue points that allow us to "pick up the pen" between segments
728 Point(30, 20),
729 Point(30, 20),
730 Point(120, 20),
731 Point(120, 20),
732
733 // The points for the second segment (120, 20) -> (130, 20)
734 Point(115, 25),
735 Point(115, 15),
736 Point(120, 25),
737 Point(120, 15),
738 Point(130, 25),
739 Point(130, 15),
740 Point(135, 25),
741 Point(135, 15),
742 };
743 // clang-format on
744
745 EXPECT_EQ(points, expected);
746 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kSquare, and points.

## ◆ TEST() [113/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | StrokeArcGeometryCoverage |
| ) |  |

Definition at line 270 of file geometry_unittests.cc.

270 {
271 Rect oval_bounds = Rect::MakeLTRB(100, 100, 200, 200);
272 Rect expanded_bounds = Rect::MakeLTRB(95, 95, 205, 205);
273 Rect squared_bounds = Rect::MakeLTRB(100 - 5 * kSqrt2, 100 - 5 * kSqrt2,
274 200 + 5 * kSqrt2, 200 + 5 * kSqrt2);
275 Matrix transform45 = Matrix::MakeTranslation(oval_bounds.GetCenter()) *
276 Matrix::MakeRotationZ(Degrees(45)) *
277 Matrix::MakeTranslation(-oval_bounds.GetCenter());
278
279 StrokeParameters butt_params = {
280 .width = 10.0f,
281 .cap = Cap::kButt,
282 };
283 StrokeParameters square_params = {
284 .width = 10.0f,
285 .cap = Cap::kSquare,
286 };
287
288 { // Sweeps <=-360 or >=360
289 for (int start = -720; start <= 720; start += 10) {
290 for (int sweep = 360; sweep <= 720; sweep += 30) {
291 std::string label =
292 "start: " + std::to_string(start) + " + " + std::to_string(sweep);
293 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
294 Degrees(sweep), butt_params);
295 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
296 << "start: " << start << ", sweep: " << sweep;
297 geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
298 Degrees(-sweep), butt_params);
299 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
300 << "start: " << start << ", sweep: " << -sweep;
301 geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
302 Degrees(-sweep), square_params);
303 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
304 << "start: " << start << ", sweep: " << -sweep << ", square caps";
305 }
306 }
307 }
308 { // Sweep from late in one quadrant to earlier in same quadrant
309 for (int start = 60; start < 360; start += 90) {
310 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
311 Degrees(330), butt_params);
312 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
313 << "start: " << start << ", butt caps";
314 geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
315 Degrees(330), square_params);
316 EXPECT_EQ(geometry->GetCoverage({}), squared_bounds)
317 << "start: " << start << ", square caps";
318 }
319 }
320 { // Sweep from early in one quadrant backwards to later in same quadrant
321 for (int start = 30; start < 360; start += 90) {
322 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
323 Degrees(-330), butt_params);
324 EXPECT_EQ(geometry->GetCoverage({}), expanded_bounds)
325 << "start: " << start << " without center";
326 geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
327 Degrees(-330), square_params);
328 EXPECT_EQ(geometry->GetCoverage({}), squared_bounds)
329 << "start: " << start << " with center";
330 }
331 }
332 { // Sweep past each quadrant axis individually with butt caps
333 for (int start = -360; start <= 720; start += 360) {
334 { // Quadrant 0
335 auto geometry = Geometry::MakeStrokedArc(
336 oval_bounds, Degrees(start - 45), Degrees(90), butt_params);
337 Rect expected_bounds = Rect::MakeLTRB(150 + 50 * kSqrt2Over2 - 5, //
338 150 - 50 * kSqrt2Over2 - 5, //
339 205, //
340 150 + 50 * kSqrt2Over2 + 5);
341 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
342 expected_bounds)
343 << "start: " << start - 45;
344 }
345 { // Quadrant 1
346 auto geometry = Geometry::MakeStrokedArc(
347 oval_bounds, Degrees(start + 45), Degrees(90), butt_params);
348 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2 - 5, //
349 150 + 50 * kSqrt2Over2 - 5, //
350 150 + 50 * kSqrt2Over2 + 5, //
351 205);
352 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
353 expected_bounds)
354 << "start: " << start + 45;
355 }
356 { // Quadrant 2
357 auto geometry = Geometry::MakeStrokedArc(
358 oval_bounds, Degrees(start + 135), Degrees(90), butt_params);
359 Rect expected_bounds = Rect::MakeLTRB(95, //
360 150 - 50 * kSqrt2Over2 - 5, //
361 150 - 50 * kSqrt2Over2 + 5, //
362 150 + 50 * kSqrt2Over2 + 5);
363 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
364 expected_bounds)
365 << "start: " << start + 135;
366 }
367 { // Quadrant 3
368 auto geometry = Geometry::MakeStrokedArc(
369 oval_bounds, Degrees(start + 225), Degrees(90), butt_params);
370 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2 - 5, //
371 95, //
372 150 + 50 * kSqrt2Over2 + 5, //
373 150 - 50 * kSqrt2Over2 + 5);
374 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
375 expected_bounds)
376 << "start: " << start + 225;
377 }
378 }
379 }
380 { // Sweep past each quadrant axis individually with square caps
381 Scalar pad = 5 * kSqrt2;
382 for (int start = -360; start <= 720; start += 360) {
383 { // Quadrant 0
384 auto geometry = Geometry::MakeStrokedArc(
385 oval_bounds, Degrees(start - 45), Degrees(90), square_params);
386 Rect expected_bounds = Rect::MakeLTRB(150 + 50 * kSqrt2Over2 - pad, //
387 150 - 50 * kSqrt2Over2 - pad, //
388 200 + pad, //
389 150 + 50 * kSqrt2Over2 + pad);
390 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
391 expected_bounds)
392 << "start: " << start - 45;
393 }
394 { // Quadrant 1
395 auto geometry = Geometry::MakeStrokedArc(
396 oval_bounds, Degrees(start + 45), Degrees(90), square_params);
397 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2 - pad, //
398 150 + 50 * kSqrt2Over2 - pad, //
399 150 + 50 * kSqrt2Over2 + pad, //
400 200 + pad);
401 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
402 expected_bounds)
403 << "start: " << start + 45;
404 }
405 { // Quadrant 2
406 auto geometry = Geometry::MakeStrokedArc(
407 oval_bounds, Degrees(start + 135), Degrees(90), square_params);
408 Rect expected_bounds = Rect::MakeLTRB(100 - pad, //
409 150 - 50 * kSqrt2Over2 - pad, //
410 150 - 50 * kSqrt2Over2 + pad, //
411 150 + 50 * kSqrt2Over2 + pad);
412 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
413 expected_bounds)
414 << "start: " << start + 135;
415 }
416 { // Quadrant 3
417 auto geometry = Geometry::MakeStrokedArc(
418 oval_bounds, Degrees(start + 225), Degrees(90), square_params);
419 Rect expected_bounds = Rect::MakeLTRB(150 - 50 * kSqrt2Over2 - pad, //
420 100 - pad, //
421 150 + 50 * kSqrt2Over2 + pad, //
422 150 - 50 * kSqrt2Over2 + pad);
423 EXPECT_RECT_NEAR(geometry->GetCoverage({}).value_or(Rect()),
424 expected_bounds)
425 << "start: " << start + 225;
426 }
427 }
428 }
429 { // 45 degree tilted full circle, butt caps
430 auto geometry = Geometry::MakeStrokedArc( //
431 oval_bounds, Degrees(0), Degrees(360), butt_params);
432 ASSERT_TRUE(
433 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
434
435 EXPECT_TRUE(geometry->GetCoverage(transform45)
436 .value_or(Rect())
437 .Contains(expanded_bounds));
438 }
439 { // 45 degree tilted full circle, square caps
440 auto geometry = Geometry::MakeStrokedArc( //
441 oval_bounds, Degrees(0), Degrees(360), square_params);
442 ASSERT_TRUE(
443 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
444
445 EXPECT_TRUE(geometry->GetCoverage(transform45)
446 .value_or(Rect())
447 .Contains(squared_bounds));
448 }
449 { // 45 degree tilted mostly full circle, butt caps
450 auto geometry = Geometry::MakeStrokedArc( //
451 oval_bounds, Degrees(3), Degrees(359), butt_params);
452 ASSERT_TRUE(
453 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
454
455 EXPECT_TRUE(geometry->GetCoverage(transform45)
456 .value_or(Rect())
457 .Contains(expanded_bounds));
458 }
459 { // 45 degree tilted mostly full circle, square caps
460 auto geometry = Geometry::MakeStrokedArc( //
461 oval_bounds, Degrees(3), Degrees(359), square_params);
462 ASSERT_TRUE(
463 oval_bounds.TransformBounds(transform45).Contains(expanded_bounds));
464
465 EXPECT_TRUE(geometry->GetCoverage(transform45)
466 .value_or(Rect())
467 .Contains(squared_bounds));
468 }
469 }
impeller::kSqrt2
constexpr float kSqrt2
Definition: constants.h:47

References impeller::TRect< T >::Contains(), EXPECT_RECT_NEAR, impeller::TRect< T >::GetCenter(), impeller::kButt, impeller::kSqrt2, impeller::kSqrt2Over2, impeller::kSquare, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokedArc(), impeller::Matrix::MakeTranslation(), start, impeller::TRect< T >::TransformBounds(), and impeller::StrokeParameters::width.

## ◆ TEST() [114/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TightConic180DegreeJoins |
| ) |  |

Definition at line 1180 of file geometry_unittests.cc.

1180 {
1181 // First, create a mild conic that helps us verify how many points
1182 // should normally be on a quad with 2 legs of length 90.
1183 flutter::DlPathBuilder path_builder_refrence;
1184 path_builder_refrence.MoveTo(Point(10, 10));
1185 path_builder_refrence.ConicCurveTo(Point(100, 10), Point(100, 100), 0.9f);
1186 flutter::DlPath path_reference = path_builder_refrence.TakePath();
1187
1188 auto points_bevel_reference =
1189 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1190 path_reference,
1191 {
1192 .width = 20.0f,
1193 .cap = Cap::kButt,
1194 .join = Join::kBevel,
1195 .miter_limit = 4.0f,
1196 },
1197 1.0f);
1198 // Generates no joins because the curve is smooth
1199 EXPECT_EQ(points_bevel_reference.size(), 78u);
1200
1201 // Now create a path that doubles back on itself with a conic.
1202 flutter::DlPathBuilder path_builder;
1203 path_builder.MoveTo(Point(10, 10));
1204 path_builder.QuadraticCurveTo(Point(100, 10), Point(10, 10));
1205 flutter::DlPath path = path_builder.TakePath();
1206
1207 auto points_bevel =
1208 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1209 path,
1210 {
1211 .width = 20.0f,
1212 .cap = Cap::kButt,
1213 .join = Join::kBevel,
1214 .miter_limit = 4.0f,
1215 },
1216 1.0f);
1217 // Generates round join because it is in the middle of a curved segment
1218 EXPECT_GT(points_bevel.size(), points_bevel_reference.size());
1219
1220 auto points_miter =
1221 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1222 path,
1223 {
1224 .width = 20.0f,
1225 .cap = Cap::kButt,
1226 .join = Join::kMiter,
1227 .miter_limit = 400.0f,
1228 },
1229 1.0f);
1230 // Generates round join because it is in the middle of a curved segment
1231 EXPECT_GT(points_miter.size(), points_bevel_reference.size());
1232
1233 auto points_round =
1234 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1235 path,
1236 {
1237 .width = 20.0f,
1238 .cap = Cap::kButt,
1239 .join = Join::kRound,
1240 .miter_limit = 4.0f,
1241 },
1242 1.0f);
1243 // Generates round join because it is in the middle of a curved segment
1244 EXPECT_GT(points_round.size(), points_bevel_reference.size());
1245 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, impeller::kMiter, and impeller::kRound.

## ◆ TEST() [115/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TightCubic180DegreeJoins |
| ) |  |

Definition at line 1247 of file geometry_unittests.cc.

1247 {
1248 // First, create a mild cubic that helps us verify how many points
1249 // should normally be on a quad with 3 legs of length ~50.
1250 flutter::DlPathBuilder path_builder_reference;
1251 path_builder_reference.MoveTo(Point(10, 10));
1252 path_builder_reference.CubicCurveTo(Point(60, 10), Point(100, 40),
1253 Point(100, 90));
1254 flutter::DlPath path_reference = path_builder_reference.TakePath();
1255
1256 auto points_reference =
1257 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1258 path_reference,
1259 {
1260 .width = 20.0f,
1261 .cap = Cap::kButt,
1262 .join = Join::kBevel,
1263 .miter_limit = 4.0f,
1264 },
1265 1.0f);
1266 // Generates no joins because the curve is smooth
1267 EXPECT_EQ(points_reference.size(), 76u);
1268
1269 // Now create a path that doubles back on itself with a cubic.
1270 flutter::DlPathBuilder path_builder;
1271 path_builder.MoveTo(Point(10, 10));
1272 path_builder.CubicCurveTo(Point(60, 10), Point(100, 40), Point(60, 10));
1273 flutter::DlPath path = path_builder.TakePath();
1274
1275 auto points_bevel =
1276 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1277 path,
1278 {
1279 .width = 20.0f,
1280 .cap = Cap::kButt,
1281 .join = Join::kBevel,
1282 .miter_limit = 4.0f,
1283 },
1284 1.0f);
1285 // Generates round join because it is in the middle of a curved segment
1286 EXPECT_GT(points_bevel.size(), points_reference.size());
1287
1288 auto points_miter =
1289 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1290 path,
1291 {
1292 .width = 20.0f,
1293 .cap = Cap::kButt,
1294 .join = Join::kMiter,
1295 .miter_limit = 400.0f,
1296 },
1297 1.0f);
1298 // Generates round join because it is in the middle of a curved segment
1299 EXPECT_GT(points_miter.size(), points_reference.size());
1300
1301 auto points_round =
1302 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1303 path,
1304 {
1305 .width = 20.0f,
1306 .cap = Cap::kButt,
1307 .join = Join::kRound,
1308 .miter_limit = 4.0f,
1309 },
1310 1.0f);
1311 // Generates round join because it is in the middle of a curved segment
1312 EXPECT_GT(points_round.size(), points_reference.size());
1313 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, impeller::kMiter, and impeller::kRound.

## ◆ TEST() [116/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TightQuadratic180DegreeJoins |
| ) |  |

Definition at line 1113 of file geometry_unittests.cc.

1113 {
1114 // First, create a mild quadratic that helps us verify how many points
1115 // should normally be on a quad with 2 legs of length 90.
1116 flutter::DlPathBuilder path_builder_refrence;
1117 path_builder_refrence.MoveTo(Point(10, 10));
1118 path_builder_refrence.QuadraticCurveTo(Point(100, 10), Point(100, 100));
1119 flutter::DlPath path_reference = path_builder_refrence.TakePath();
1120
1121 auto points_bevel_reference =
1122 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1123 path_reference,
1124 {
1125 .width = 20.0f,
1126 .cap = Cap::kButt,
1127 .join = Join::kBevel,
1128 .miter_limit = 4.0f,
1129 },
1130 1.0f);
1131 // Generates no joins because the curve is smooth
1132 EXPECT_EQ(points_bevel_reference.size(), 74u);
1133
1134 // Now create a path that doubles back on itself with a quadratic.
1135 flutter::DlPathBuilder path_builder;
1136 path_builder.MoveTo(Point(10, 10));
1137 path_builder.QuadraticCurveTo(Point(100, 10), Point(10, 10));
1138 flutter::DlPath path = path_builder.TakePath();
1139
1140 auto points_bevel =
1141 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1142 path,
1143 {
1144 .width = 20.0f,
1145 .cap = Cap::kButt,
1146 .join = Join::kBevel,
1147 .miter_limit = 4.0f,
1148 },
1149 1.0f);
1150 // Generates round join because it is in the middle of a curved segment
1151 EXPECT_GT(points_bevel.size(), points_bevel_reference.size());
1152
1153 auto points_miter =
1154 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1155 path,
1156 {
1157 .width = 20.0f,
1158 .cap = Cap::kButt,
1159 .join = Join::kMiter,
1160 .miter_limit = 400.0f,
1161 },
1162 1.0f);
1163 // Generates round join because it is in the middle of a curved segment
1164 EXPECT_GT(points_miter.size(), points_bevel_reference.size());
1165
1166 auto points_round =
1167 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1168 path,
1169 {
1170 .width = 20.0f,
1171 .cap = Cap::kButt,
1172 .join = Join::kRound,
1173 .miter_limit = 4.0f,
1174 },
1175 1.0f);
1176 // Generates round join because it is in the middle of a curved segment
1177 EXPECT_GT(points_round.size(), points_bevel_reference.size());
1178 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, impeller::kMiter, and impeller::kRound.

## ◆ TEST() [117/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TinyConicGeneratesCaps |
| ) |  |

Definition at line 927 of file geometry_unittests.cc.

927 {
928 flutter::DlPathBuilder path_builder;
929 path_builder.MoveTo({20, 20});
930 path_builder.ConicCurveTo({20.125, 20}, {20.250, 20}, 0.6);
931 flutter::DlPath path = path_builder.TakePath();
932
933 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
934 path,
935 {
936 .width = 4.0f,
937 .cap = Cap::kSquare,
938 .join = Join::kBevel,
939 .miter_limit = 4.0f,
940 },
941 1.0f);
942
943 std::vector<Point> expected = {
944 // The points for the opening square cap
945 Point(18, 22),
946 Point(18, 18),
947
948 // The points for the start of the curve
949 Point(20, 22),
950 Point(20, 18),
951
952 // The points for the end of the curve
953 Point(20.25, 22),
954 Point(20.25, 18),
955
956 // The points for the closing square cap
957 Point(22.25, 22),
958 Point(22.25, 18),
959 };
960
961 EXPECT_EQ(points, expected);
962 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kSquare, and points.

## ◆ TEST() [118/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TinyCubicGeneratesCaps |
| ) |  |

Definition at line 964 of file geometry_unittests.cc.

964 {
965 flutter::DlPathBuilder path_builder;
966 path_builder.MoveTo({20, 20});
967 path_builder.CubicCurveTo({20.0625, 20}, {20.125, 20}, {20.250, 20});
968 flutter::DlPath path = path_builder.TakePath();
969
970 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
971 path,
972 {
973 .width = 4.0f,
974 .cap = Cap::kSquare,
975 .join = Join::kBevel,
976 .miter_limit = 4.0f,
977 },
978 1.0f);
979
980 std::vector<Point> expected = {
981 // The points for the opening square cap
982 Point(18, 22),
983 Point(18, 18),
984
985 // The points for the start of the curve
986 Point(20, 22),
987 Point(20, 18),
988
989 // The points for the end of the curve
990 Point(20.25, 22),
991 Point(20.25, 18),
992
993 // The points for the closing square cap
994 Point(22.25, 22),
995 Point(22.25, 18),
996 };
997
998 EXPECT_EQ(points, expected);
999 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kSquare, and points.

## ◆ TEST() [119/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TinyQuadGeneratesCaps |
| ) |  |

Definition at line 890 of file geometry_unittests.cc.

890 {
891 flutter::DlPathBuilder path_builder;
892 path_builder.MoveTo({20, 20});
893 path_builder.QuadraticCurveTo({20.125, 20}, {20.250, 20});
894 flutter::DlPath path = path_builder.TakePath();
895
896 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
897 path,
898 {
899 .width = 4.0f,
900 .cap = Cap::kSquare,
901 .join = Join::kBevel,
902 .miter_limit = 4.0f,
903 },
904 1.0f);
905
906 std::vector<Point> expected = {
907 // The points for the opening square cap
908 Point(18, 22),
909 Point(18, 18),
910
911 // The points for the start of the curve
912 Point(20, 22),
913 Point(20, 18),
914
915 // The points for the end of the curve
916 Point(20.25, 22),
917 Point(20.25, 18),
918
919 // The points for the closing square cap
920 Point(22.25, 22),
921 Point(22.25, 18),
922 };
923
924 EXPECT_EQ(points, expected);
925 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kSquare, and points.

## ◆ TEST() [120/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegments180DegreeJoins |
| ) |  |

Definition at line 1065 of file geometry_unittests.cc.

1065 {
1066 // First, create a path that doubles back on itself.
1067 flutter::DlPathBuilder path_builder;
1068 path_builder.MoveTo(Point(10, 10));
1069 path_builder.LineTo(Point(100, 10));
1070 path_builder.LineTo(Point(10, 10));
1071 flutter::DlPath path = path_builder.TakePath();
1072
1073 auto points_bevel =
1074 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1075 path,
1076 {
1077 .width = 20.0f,
1078 .cap = Cap::kButt,
1079 .join = Join::kBevel,
1080 .miter_limit = 4.0f,
1081 },
1082 1.0f);
1083 // Generates no join - because it is a bevel join
1084 EXPECT_EQ(points_bevel.size(), 8u);
1085
1086 auto points_miter =
1087 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1088 path,
1089 {
1090 .width = 20.0f,
1091 .cap = Cap::kButt,
1092 .join = Join::kMiter,
1093 .miter_limit = 400.0f,
1094 },
1095 1.0f);
1096 // Generates no join - even with a very large miter limit
1097 EXPECT_EQ(points_miter.size(), 8u);
1098
1099 auto points_round =
1100 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1101 path,
1102 {
1103 .width = 20.0f,
1104 .cap = Cap::kButt,
1105 .join = Join::kRound,
1106 .miter_limit = 4.0f,
1107 },
1108 1.0f);
1109 // Generates lots of join points - to round off the 180 degree bend
1110 EXPECT_EQ(points_round.size(), 19u);
1111 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, impeller::kMiter, and impeller::kRound.

## ◆ TEST() [121/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegmentsLeftTurnStrokeVerticesBevelJoin |
| ) |  |

Definition at line 782 of file geometry_unittests.cc.

782 {
783 flutter::DlPathBuilder path_builder;
784 path_builder.MoveTo({20, 20});
785 path_builder.LineTo({30, 20});
786 path_builder.LineTo({30, 10});
787 flutter::DlPath path = path_builder.TakePath();
788
789 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
790 path,
791 {
792 .width = 10.0f,
793 .cap = Cap::kButt,
794 .join = Join::kBevel,
795 .miter_limit = 4.0f,
796 },
797 1.0f);
798
799 std::vector<Point> expected = {
800 // The points for the first segment (20, 20) -> (30, 20)
801 Point(20, 25),
802 Point(20, 15),
803 Point(30, 25),
804 Point(30, 15),
805
806 // The points for the second segment (120, 20) -> (130, 20)
807 Point(35, 20),
808 Point(25, 20),
809 Point(35, 10),
810 Point(25, 10),
811 };
812
813 EXPECT_EQ(points, expected);
814 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, and points.

## ◆ TEST() [122/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegmentsLeftTurnStrokeVerticesMiterJoin |
| ) |  |

Definition at line 853 of file geometry_unittests.cc.

853 {
854 flutter::DlPathBuilder path_builder;
855 path_builder.MoveTo({20, 20});
856 path_builder.LineTo({30, 20});
857 path_builder.LineTo({30, 10});
858 flutter::DlPath path = path_builder.TakePath();
859
860 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
861 path,
862 {
863 .width = 10.0f,
864 .cap = Cap::kButt,
865 .join = Join::kMiter,
866 .miter_limit = 4.0f,
867 },
868 1.0f);
869
870 std::vector<Point> expected = {
871 // The points for the first segment (20, 20) -> (30, 20)
872 Point(20, 25),
873 Point(20, 15),
874 Point(30, 25),
875 Point(30, 15),
876
877 // And one point makes a Miter
878 Point(35, 25),
879
880 // The points for the second segment (120, 20) -> (130, 20)
881 Point(35, 20),
882 Point(25, 20),
883 Point(35, 10),
884 Point(25, 10),
885 };
886
887 EXPECT_EQ(points, expected);
888 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kButt, impeller::kMiter, and points.

## ◆ TEST() [123/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegmentsMiterLimit |
| ) |  |

Definition at line 1001 of file geometry_unittests.cc.

1001 {
1002 // degrees is the angle that the line deviates from "straight ahead"
1003 for (int degrees = 10; degrees < 180; degrees += 10) {
1004 // Start with a width of 2 since line widths of 1 usually decide
1005 // that they don't need join geometry at a scale of 1.0
1006 for (int width = 2; width <= 10; width++) {
1007 Degrees d(degrees);
1008 Radians r(d);
1009 Point pixel_delta = Point(std::cos(r.radians), std::sin(r.radians));
1010
1011 if (pixel_delta.GetDistance(Point(1, 0)) * width < 1.0f) {
1012 // Some combinations of angle and width result in a join that is
1013 // less than a pixel in size. We don't care about compliance on
1014 // such a small join delta (and, in fact, the implementation may
1015 // decide to elide those small joins).
1016 continue;
1017 }
1018
1019 // Miter limits are based on angle between the vectors/segments
1020 Degrees between(180 - degrees);
1021 Radians r_between(between);
1022 Scalar limit = 1.0f / std::sin(r_between.radians / 2.0f);
1023
1024 flutter::DlPathBuilder path_builder;
1025 path_builder.MoveTo(Point(20, 20));
1026 path_builder.LineTo(Point(30, 20));
1027 path_builder.LineTo(Point(30, 20) + pixel_delta * 10.0f);
1028 flutter::DlPath path = path_builder.TakePath();
1029
1030 // Miter limit too small (99% of required) to allow a miter
1031 auto points1 =
1032 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1033 path,
1034 {
1035 .width = static_cast<Scalar>(width),
1036 .cap = Cap::kButt,
1037 .join = Join::kMiter,
1038 .miter_limit = limit * 0.99f,
1039 },
1040 1.0f);
1041 EXPECT_EQ(points1.size(), 8u)
1042 << "degrees: " << degrees << ", width: " << width << ", "
1043 << points1[4];
1044
1045 // Miter limit large enough (101% of required) to allow a miter
1046 auto points2 =
1047 ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
1048 path,
1049 {
1050 .width = static_cast<Scalar>(width),
1051 .cap = Cap::kButt,
1052 .join = Join::kMiter,
1053 .miter_limit = limit * 1.01f,
1054 },
1055 1.0f);
1056 EXPECT_EQ(points2.size(), 9u)
1057 << "degrees: " << degrees << ", width: " << width;
1058 EXPECT_LE(points2[4].GetDistance({30, 20}), width * limit * 1.05f)
1059 << "degrees: " << degrees << ", width: " << width << ", "
1060 << points2[4];
1061 }
1062 }
1063 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::TPoint< T >::GetDistance(), impeller::kButt, impeller::kMiter, and impeller::Radians::radians.

## ◆ TEST() [124/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegmentsRightTurnStrokeVerticesBevelJoin |
| ) |  |

Definition at line 748 of file geometry_unittests.cc.

748 {
749 flutter::DlPathBuilder path_builder;
750 path_builder.MoveTo({20, 20});
751 path_builder.LineTo({30, 20});
752 path_builder.LineTo({30, 30});
753 flutter::DlPath path = path_builder.TakePath();
754
755 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
756 path,
757 {
758 .width = 10.0f,
759 .cap = Cap::kButt,
760 .join = Join::kBevel,
761 .miter_limit = 4.0f,
762 },
763 1.0f);
764
765 std::vector<Point> expected = {
766 // The points for the first segment (20, 20) -> (30, 20)
767 Point(20, 25),
768 Point(20, 15),
769 Point(30, 25),
770 Point(30, 15),
771
772 // The points for the second segment (120, 20) -> (130, 20)
773 Point(25, 20),
774 Point(35, 20),
775 Point(25, 30),
776 Point(35, 30),
777 };
778
779 EXPECT_EQ(points, expected);
780 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kBevel, impeller::kButt, and points.

## ◆ TEST() [125/574]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | TwoLineSegmentsRightTurnStrokeVerticesMiterJoin |
| ) |  |

Definition at line 816 of file geometry_unittests.cc.

816 {
817 flutter::DlPathBuilder path_builder;
818 path_builder.MoveTo({20, 20});
819 path_builder.LineTo({30, 20});
820 path_builder.LineTo({30, 30});
821 flutter::DlPath path = path_builder.TakePath();
822
823 auto points = ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(
824 path,
825 {
826 .width = 10.0f,
827 .cap = Cap::kButt,
828 .join = Join::kMiter,
829 .miter_limit = 4.0f,
830 },
831 1.0f);
832
833 std::vector<Point> expected = {
834 // The points for the first segment (20, 20) -> (30, 20)
835 Point(20, 25),
836 Point(20, 15),
837 Point(30, 25),
838 Point(30, 15),
839
840 // And one point makes a Miter
841 Point(35, 15),
842
843 // The points for the second segment (120, 20) -> (130, 20)
844 Point(25, 20),
845 Point(35, 20),
846 Point(25, 30),
847 Point(35, 30),
848 };
849
850 EXPECT_EQ(points, expected);
851 }

References impeller::ImpellerEntityUnitTestAccessor::GenerateSolidStrokeVertices(), impeller::kButt, impeller::kMiter, and points.

## ◆ TEST() [126/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendAndRestoreClipCoverage |
| ) |  |

Definition at line 58 of file clip_stack_unittests.cc.

58 {
59 EntityPassClipStack recorder =
60 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
61
62 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
63
64 // Push a clip.
65 EntityPassClipStack::ClipStateResult result =
66 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
67 /*is_axis_aligned_rect=*/true),
68 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
69 EXPECT_TRUE(result.should_render);
70 EXPECT_TRUE(result.clip_did_change);
71
72 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
73 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
74 Rect::MakeLTRB(50, 50, 55.5, 55.5));
75 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
76 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
77
78 // Restore the clip.
79 recorder.RecordRestore({0, 0}, 0);
80
81 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
82 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
83 Rect::MakeSize(Size::MakeWH(100, 100)));
84 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
85 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
86 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordClip(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [127/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendAndRestoreClipCoverageNonAA |
| ) |  |

Definition at line 88 of file clip_stack_unittests.cc.

88 {
89 EntityPassClipStack recorder =
90 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
91
92 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
93
94 // Push a clip.
95 EntityPassClipStack::ClipStateResult result =
96 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.4, 55.4),
97 /*is_axis_aligned_rect=*/true),
98 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
99 EXPECT_FALSE(result.should_render);
100 EXPECT_TRUE(result.clip_did_change);
101
102 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
103 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
104 Rect::MakeLTRB(50, 50, 55, 55));
105 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
106 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
107
108 // Restore the clip.
109 recorder.RecordRestore({0, 0}, 0);
110
111 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
112 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
113 Rect::MakeSize(Size::MakeWH(100, 100)));
114 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
115 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
116 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordClip(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [128/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendDecreasingSizeClipCoverage |
| ) |  |

Definition at line 171 of file clip_stack_unittests.cc.

171 {
172 EntityPassClipStack recorder =
173 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
174
175 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
176
177 // Push Clips that shrink in size. All should be applied.
178 Entity entity;
179
180 for (auto i = 1; i < 20; i++) {
181 EntityPassClipStack::ClipStateResult result = recorder.RecordClip(
182 ClipContents(Rect::MakeLTRB(i, i, 99.6 - i, 99.6 - i),
183 /*is_axis_aligned_rect=*/true),
184 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
185
186 EXPECT_TRUE(result.should_render);
187 EXPECT_TRUE(result.clip_did_change);
188 EXPECT_EQ(recorder.CurrentClipCoverage(),
189 Rect::MakeLTRB(i, i, 99.6 - i, 99.6 - i));
190 }
191 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [129/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendIncreasingSizeClipCoverage |
| ) |  |

Definition at line 193 of file clip_stack_unittests.cc.

193 {
194 EntityPassClipStack recorder =
195 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
196
197 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
198
199 // Push Clips that grow in size. All should be skipped.
200
201 for (auto i = 1; i < 20; i++) {
202 EntityPassClipStack::ClipStateResult result = recorder.RecordClip(
203 ClipContents(Rect::MakeLTRB(0 - i, 0 - i, 100 + i, 100 + i),
204 /*is_axis_aligned_rect=*/true),
205 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
206
207 EXPECT_FALSE(result.should_render);
208 EXPECT_FALSE(result.clip_did_change);
209 EXPECT_EQ(recorder.CurrentClipCoverage(), Rect::MakeLTRB(0, 0, 100, 100));
210 }
211 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::CurrentClipCoverage(), impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [130/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendLargerClipCoverage |
| ) |  |

Definition at line 120 of file clip_stack_unittests.cc.

120 {
121 EntityPassClipStack recorder =
122 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
123
124 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
125
126 // Push a clip.
127 EntityPassClipStack::ClipStateResult result =
128 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
129 /*is_axis_aligned_rect=*/true),
130 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
131
132 EXPECT_TRUE(result.should_render);
133 EXPECT_TRUE(result.clip_did_change);
134
135 // Push a clip with larger coverage than the previous state.
136 result = recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100.5, 100.5),
137 /*is_axis_aligned_rect=*/true),
138 Matrix(), {0, 0}, 1, 100, /*is_aa=*/true);
139
140 EXPECT_FALSE(result.should_render);
141 EXPECT_FALSE(result.clip_did_change);
142 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [131/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendLargerClipCoverageWithDifferenceOrNonSquare |
| ) |  |

Definition at line 146 of file clip_stack_unittests.cc.

147 {
148 EntityPassClipStack recorder =
149 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
150
151 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
152
153 // Push a clip.
154 EntityPassClipStack::ClipStateResult result =
155 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55, 55),
156 /*is_axis_aligned_rect=*/true),
157 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
158
159 EXPECT_FALSE(result.should_render);
160 EXPECT_TRUE(result.clip_did_change);
161
162 // Push a clip with larger coverage than the previous state.
163 result = recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100, 100),
164 /*is_axis_aligned_rect=*/false),
165 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
166
167 EXPECT_TRUE(result.should_render);
168 EXPECT_TRUE(result.clip_did_change);
169 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [132/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | CanPopEntitiesSafely |
| ) |  |

Definition at line 48 of file clip_stack_unittests.cc.

48 {
49 EntityPassClipStack recorder =
50 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
51
52 EXPECT_TRUE(recorder.GetReplayEntities().empty());
53
54 recorder.RecordRestore({0, 0}, 0);
55 EXPECT_TRUE(recorder.GetReplayEntities().empty());
56 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordRestore().

## ◆ TEST() [133/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | CanPushAndPopEntities |
| ) |  |

Definition at line 14 of file clip_stack_unittests.cc.

14 {
15 EntityPassClipStack recorder =
16 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
17
18 EXPECT_TRUE(recorder.GetReplayEntities().empty());
19
20 recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 100, 100),
21 /*is_axis_aligned_rect=*/false),
22 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
23
24 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
25
26 recorder.RecordClip(ClipContents(Rect::MakeLTRB(0, 0, 50.5, 50.5),
27 /*is_axis_aligned_rect=*/true),
28 Matrix(), {0, 0}, 2, 100, /*is_aa=*/true);
29
30 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
31 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
32 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
33
34 // NOLINTBEGIN(bugprone-unchecked-optional-access)
35 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
36 Rect::MakeLTRB(0, 0, 100, 100));
37 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
38 Rect::MakeLTRB(0, 0, 50.5, 50.5));
39 // NOLINTEND(bugprone-unchecked-optional-access)
40
41 recorder.RecordRestore({0, 0}, 1);
42 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
43
44 recorder.RecordRestore({0, 0}, 0);
45 EXPECT_TRUE(recorder.GetReplayEntities().empty());
46 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::RecordRestore().

## ◆ TEST() [134/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | ClipAndRestoreWithSubpasses |
| ) |  |

Definition at line 232 of file clip_stack_unittests.cc.

232 {
233 EntityPassClipStack recorder =
234 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
235
236 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
237
238 // Push a clip.
239 {
240 EntityPassClipStack::ClipStateResult result =
241 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.5, 55.5),
242 /*is_axis_aligned_rect=*/true),
243 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
244
245 EXPECT_TRUE(result.should_render);
246 EXPECT_TRUE(result.clip_did_change);
247 }
248
249 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
250 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
251 Rect::MakeLTRB(50, 50, 55.5, 55.5));
252 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
253 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
254
255 // Begin a subpass.
256 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
257 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
258 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
259 Rect::MakeLTRB(50, 50, 55, 55));
260
261 {
262 EntityPassClipStack::ClipStateResult result =
263 recorder.RecordClip(ClipContents(Rect::MakeLTRB(54, 54, 54.5, 54.5),
264 /*is_axis_aligned_rect=*/true),
265 Matrix(), {0, 0}, 0, 100, /*is_aa=*/true);
266
267 EXPECT_TRUE(result.should_render);
268 EXPECT_TRUE(result.clip_did_change);
269 }
270
271 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
272 Rect::MakeLTRB(54, 54, 54.5, 54.5));
273
274 // End subpass.
275 recorder.PopSubpass();
276
277 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
278 Rect::MakeLTRB(50, 50, 55.5, 55.5));
279 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [135/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | ClipAndRestoreWithSubpassesNonAA |
| ) |  |

Definition at line 281 of file clip_stack_unittests.cc.

281 {
282 EntityPassClipStack recorder =
283 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
284
285 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
286
287 // Push a clip.
288 {
289 EntityPassClipStack::ClipStateResult result =
290 recorder.RecordClip(ClipContents(Rect::MakeLTRB(50, 50, 55.4, 55.4),
291 /*is_axis_aligned_rect=*/true),
292 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
293
294 EXPECT_FALSE(result.should_render);
295 EXPECT_TRUE(result.clip_did_change);
296 }
297
298 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
299 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
300 Rect::MakeLTRB(50, 50, 55.0, 55.0));
301 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
302 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
303
304 // Begin a subpass.
305 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
306 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
307 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
308 Rect::MakeLTRB(50, 50, 55, 55));
309
310 {
311 EntityPassClipStack::ClipStateResult result =
312 recorder.RecordClip(ClipContents(Rect::MakeLTRB(54, 54, 55.4, 55.4),
313 /*is_axis_aligned_rect=*/true),
314 Matrix(), {0, 0}, 0, 100, /*is_aa=*/false);
315
316 EXPECT_FALSE(result.should_render);
317 EXPECT_TRUE(result.clip_did_change);
318 }
319
320 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
321 Rect::MakeLTRB(54, 54, 55.0, 55.0));
322
323 // End subpass.
324 recorder.PopSubpass();
325
326 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
327 Rect::MakeLTRB(50, 50, 55, 55));
328 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::EntityPassClipStack::RecordClip(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [136/574]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | UnbalancedRestore |
| ) |  |

Definition at line 213 of file clip_stack_unittests.cc.

213 {
214 EntityPassClipStack recorder =
215 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
216
217 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
218
219 // Restore the clip.
220 EntityPassClipStack::ClipStateResult result =
221 recorder.RecordRestore(Point(0, 0), 0);
222 EXPECT_FALSE(result.should_render);
223 EXPECT_FALSE(result.clip_did_change);
224
225 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
226 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
227 Rect::MakeSize(Size::MakeWH(100, 100)));
228 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
229 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
230 }

References impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::RecordRestore(), and impeller::EntityPassClipStack::ClipStateResult::should_render.

## ◆ TEST() [137/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | AddFenceDoesNothingIfTerminating |
| ) |  |

Definition at line 86 of file fence_waiter_vk_unittests.cc.

86 {
87 auto signal = fml::ManualResetWaitableEvent();
88
89 {
90 auto const context = MockVulkanContextBuilder().Build();
91 auto const device = context->GetDevice();
92 auto const waiter = context->GetFenceWaiter();
93 waiter->Terminate();
94
95 auto fence = device.createFenceUnique({}).value;
96 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
97 }
98
99 // Ensure the fence did _not_ signal.
100 EXPECT_TRUE(signal.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(100)));
101 }
value
int32_t value
Definition: dl_golden_unittests.cc:459

References value.

## ◆ TEST() [138/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesFenceCallback |
| ) |  |

Definition at line 28 of file fence_waiter_vk_unittests.cc.

28 {
29 auto const context = MockVulkanContextBuilder().Build();
30 auto const device = context->GetDevice();
31 auto const waiter = context->GetFenceWaiter();
32
33 auto signal = fml::ManualResetWaitableEvent();
34 auto fence = device.createFenceUnique({}).value;
35 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
36
37 signal.Wait();
38 }

References value.

## ◆ TEST() [139/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesFenceCallbackX2 |
| ) |  |

Definition at line 40 of file fence_waiter_vk_unittests.cc.

40 {
41 auto const context = MockVulkanContextBuilder().Build();
42 auto const device = context->GetDevice();
43 auto const waiter = context->GetFenceWaiter();
44
45 auto signal = fml::ManualResetWaitableEvent();
46 auto fence = device.createFenceUnique({}).value;
47 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
48
49 auto signal2 = fml::ManualResetWaitableEvent();
50 auto fence2 = device.createFenceUnique({}).value;
51 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
52
53 signal.Wait();
54 signal2.Wait();
55 }

References value.

## ◆ TEST() [140/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesNewFenceThenOldFence |
| ) |  |

Definition at line 57 of file fence_waiter_vk_unittests.cc.

57 {
58 auto const context = MockVulkanContextBuilder().Build();
59 auto const device = context->GetDevice();
60 auto const waiter = context->GetFenceWaiter();
61
62 auto signal = fml::ManualResetWaitableEvent();
63 auto fence = device.createFenceUnique({}).value;
64 MockFence::SetStatus(fence, vk::Result::eNotReady);
65 auto raw_fence = MockFence::GetRawPointer(fence);
66 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
67
68 // The easiest way to verify that the callback was _not_ called is to wait
69 // for a timeout, but that could introduce flakiness. Instead, we'll add a
70 // second fence that will signal immediately, and wait for that one instead.
71 {
72 auto signal2 = fml::ManualResetWaitableEvent();
73 auto fence2 = device.createFenceUnique({}).value;
74 MockFence::SetStatus(fence2, vk::Result::eSuccess);
75 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
76 signal2.Wait();
77 }
78
79 // Now, we'll signal the first fence, and wait for the callback to be called.
80 raw_fence->SetStatus(vk::Result::eSuccess);
81
82 // Now, we'll signal the first fence, and wait for the callback to be called.
83 signal.Wait();
84 }

References value.

## ◆ TEST() [141/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | IgnoresNullCallback |
| ) |  |

Definition at line 19 of file fence_waiter_vk_unittests.cc.

19 {
20 auto const context = MockVulkanContextBuilder().Build();
21 auto const device = context->GetDevice();
22 auto const waiter = context->GetFenceWaiter();
23
24 auto fence = device.createFenceUnique({}).value;
25 EXPECT_FALSE(waiter->AddFence(std::move(fence), nullptr));
26 }

References value.

## ◆ TEST() [142/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | IgnoresNullFence |
| ) |  |

Definition at line 13 of file fence_waiter_vk_unittests.cc.

13 {
14 auto const context = MockVulkanContextBuilder().Build();
15 auto const waiter = context->GetFenceWaiter();
16 EXPECT_FALSE(waiter->AddFence(vk::UniqueFence(), []() {}));
17 }

## ◆ TEST() [143/574]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | InProgressFencesStillWaitIfTerminated |
| ) |  |

Definition at line 103 of file fence_waiter_vk_unittests.cc.

103 {
104 MockFence* raw_fence = nullptr;
105 auto signal = fml::ManualResetWaitableEvent();
106
107 auto const context = MockVulkanContextBuilder().Build();
108 auto const device = context->GetDevice();
109 auto const waiter = context->GetFenceWaiter();
110
111 // Add a fence that isn't signalled yet.
112 auto fence = device.createFenceUnique({}).value;
113
114 // Even if the fence is eSuccess, it's not guaranteed to be called in time.
115 MockFence::SetStatus(fence, vk::Result::eNotReady);
116 raw_fence = MockFence::GetRawPointer(fence);
117 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
118
119 // Signal the fence after a delay.
120 std::thread thread([&]() {
121 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
122 raw_fence->SetStatus(vk::Result::eSuccess);
123 });
124
125 // Terminate the waiter. This will block until all pending fences are
126 // signalled.
127 waiter->Terminate();
128
129 // This will hang if the fence was not signalled.
130 signal.Wait();
131
132 thread.join();
133 }

References value.

## ◆ TEST() [144/574]

impeller::testing::TEST | ( | FilterInputTest | ,
|  | CanSetLocalTransformForTexture |
| ) |  |

Definition at line 15 of file filter_input_unittests.cc.

15 {
16 std::shared_ptr<Texture> texture = nullptr;
17 auto input =
18 FilterInput::Make(texture, Matrix::MakeTranslation({1.0, 0.0, 0.0}));
19 Entity e;
20 e.SetTransform(Matrix::MakeTranslation({0.0, 2.0, 0.0}));
21
22 ASSERT_MATRIX_NEAR(input->GetLocalTransform(e),
23 Matrix::MakeTranslation({1.0, 0.0, 0.0}));
24 ASSERT_MATRIX_NEAR(input->GetTransform(e),
25 Matrix::MakeTranslation({1.0, 2.0, 0.0}));
26 }
ASSERT_MATRIX_NEAR
#define ASSERT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:189

References ASSERT_MATRIX_NEAR, impeller::FilterInput::Make(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST() [145/574]

impeller::testing::TEST | ( | FormatsVKTest | ,
|  | DescriptorMapping |
| ) |  |

Definition at line 11 of file formats_vk_unittests.cc.

11 {
12 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kSampledImage),
13 vk::DescriptorType::eCombinedImageSampler);
14 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kUniformBuffer),
15 vk::DescriptorType::eUniformBuffer);
16 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kStorageBuffer),
17 vk::DescriptorType::eStorageBuffer);
18 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kImage),
19 vk::DescriptorType::eSampledImage);
20 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kSampler),
21 vk::DescriptorType::eSampler);
22 EXPECT_EQ(ToVKDescriptorType(DescriptorType::kInputAttachment),
23 vk::DescriptorType::eInputAttachment);
24 }
impeller::ToVKDescriptorType
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
Definition: formats_vk.h:294
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:26

References impeller::kImage, impeller::kInputAttachment, impeller::kSampledImage, impeller::kSampler, impeller::kStorageBuffer, impeller::kUniformBuffer, and impeller::ToVKDescriptorType().

## ◆ TEST() [146/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateSigmaForBlurRadius |
| ) |  |

Definition at line 470 of file gaussian_blur_filter_contents_unittests.cc.

470 {
471 Scalar sigma = 1.0;
472 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
473 GaussianBlurFilterContents::ScaleSigma(sigma));
474 fml::StatusOr<Scalar> derived_sigma =
475 CalculateSigmaForBlurRadius(radius, Matrix());
476 ASSERT_TRUE(derived_sigma.ok());
477 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
478 }

References impeller::GaussianBlurFilterContents::CalculateBlurRadius(), and impeller::GaussianBlurFilterContents::ScaleSigma().

## ◆ TEST() [147/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateSigmaValues |
| ) |  |

Definition at line 232 of file gaussian_blur_filter_contents_unittests.cc.

232 {
233 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
234 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
235 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
236 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
237 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
238 // Hang on to 1/8 as long as possible.
239 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
240 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
241 // Downsample clamped to 1/16th.
242 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
243 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [148/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | ChopHugeBlurs |
| ) |  |

Definition at line 633 of file gaussian_blur_filter_contents_unittests.cc.

633 {
634 Scalar sigma = 30.5f;
635 int32_t blur_radius = static_cast<int32_t>(
636 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
637 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
638 .blur_sigma = sigma,
639 .blur_radius = blur_radius,
640 .step_size = 1};
641 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
642 GaussianBlurPipeline::FragmentShader::KernelSamples frag_kernel_samples =
643 LerpHackKernelSamples(kernel_samples);
644 EXPECT_TRUE(frag_kernel_samples.sample_count <= kGaussianBlurMaxKernelSize);
645 }
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:85
impeller::kGaussianBlurMaxKernelSize
static constexpr int32_t kGaussianBlurMaxKernelSize
Definition: gaussian_blur_filter_contents.h:17
impeller::GenerateBlurInfo
KernelSamples GenerateBlurInfo(BlurParameters parameters)
Definition: gaussian_blur_filter_contents.cc:1049
impeller::LerpHackKernelSamples
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
Definition: gaussian_blur_filter_contents.cc:1096

References blur_radius, impeller::BlurParameters::blur_uv_offset, impeller::GaussianBlurFilterContents::CalculateBlurRadius(), impeller::GenerateBlurInfo(), impeller::kGaussianBlurMaxKernelSize, and impeller::LerpHackKernelSamples().

## ◆ TEST() [149/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | Coefficients |
| ) |  |

Definition at line 480 of file gaussian_blur_filter_contents_unittests.cc.

480 {
481 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
482 .blur_sigma = 1,
483 .blur_radius = 5,
484 .step_size = 1};
485 KernelSamples samples = GenerateBlurInfo(parameters);
486 EXPECT_EQ(samples.sample_count, 11);
487
488 // Coefficients should add up to 1.
489 Scalar tally = 0;
490 for (int i = 0; i < samples.sample_count; ++i) {
491 tally += samples.samples[i].coefficient;
492 }
493 EXPECT_FLOAT_EQ(tally, 1.0f);
494
495 // Verify the shape of the curve.
496 for (int i = 0; i < 4; ++i) {
497 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
498 samples.samples[10 - i].coefficient);
499 EXPECT_TRUE(samples.samples[i + 1].coefficient >
500 samples.samples[i].coefficient);
501 }
502 }

References impeller::BlurParameters::blur_uv_offset, impeller::KernelSample::coefficient, impeller::GenerateBlurInfo(), impeller::KernelSamples::sample_count, and impeller::KernelSamples::samples.

## ◆ TEST() [150/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageEmpty |
| ) |  |

Definition at line 122 of file gaussian_blur_filter_contents_unittests.cc.

122 {
123 GaussianBlurFilterContents contents(
124 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
125 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
126 /*mask_geometry=*/nullptr);
127 FilterInput::Vector inputs = {};
128 Entity entity;
129 std::optional<Rect> coverage =
130 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
131 ASSERT_FALSE(coverage.has_value());
132 }

References impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, and impeller::FilterContents::kNormal.

## ◆ TEST() [151/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageSimple |
| ) |  |

Definition at line 134 of file gaussian_blur_filter_contents_unittests.cc.

134 {
135 GaussianBlurFilterContents contents(
136 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
137 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
138 /*mask_geometry=*/nullptr);
139 FilterInput::Vector inputs = {
140 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
141 Entity entity;
142 std::optional<Rect> coverage =
143 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
144
145 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
146 }

References impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [152/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithSigma |
| ) |  |

Definition at line 148 of file gaussian_blur_filter_contents_unittests.cc.

148 {
149 fml::StatusOr<Scalar> sigma_radius_1 =
150 CalculateSigmaForBlurRadius(1.0, Matrix());
151 ASSERT_TRUE(sigma_radius_1.ok());
152 GaussianBlurFilterContents contents(
153 /*sigma_x=*/sigma_radius_1.value(),
154 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
155 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
156 /*mask_geometry=*/nullptr);
157 FilterInput::Vector inputs = {
158 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
159 Entity entity;
160 std::optional<Rect> coverage =
161 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
162
163 EXPECT_TRUE(coverage.has_value());
164 if (coverage.has_value()) {
165 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
166 }
167 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [153/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | Create |
| ) |  |

Definition at line 113 of file gaussian_blur_filter_contents_unittests.cc.

113 {
114 GaussianBlurFilterContents contents(
115 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
116 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
117 /*mask_geometry=*/nullptr);
118 EXPECT_EQ(contents.GetSigmaX(), 0.0);
119 EXPECT_EQ(contents.GetSigmaY(), 0.0);
120 }

References impeller::GaussianBlurFilterContents::GetSigmaX(), impeller::GaussianBlurFilterContents::GetSigmaY(), impeller::Entity::kDecal, and impeller::FilterContents::kNormal.

## ◆ TEST() [154/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | FilterSourceCoverage |
| ) |  |

Definition at line 214 of file gaussian_blur_filter_contents_unittests.cc.

214 {
215 fml::StatusOr<Scalar> sigma_radius_1 =
216 CalculateSigmaForBlurRadius(1.0, Matrix());
217 ASSERT_TRUE(sigma_radius_1.ok());
218 auto contents = std::make_unique<GaussianBlurFilterContents>(
219 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
220 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
221 /*mask_geometry=*/nullptr);
222 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
223 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
224 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
225 EXPECT_TRUE(coverage.has_value());
226 if (coverage.has_value()) {
227 EXPECT_RECT_NEAR(coverage.value(),
228 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
229 }
230 }

References EXPECT_RECT_NEAR, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeScale().

## ◆ TEST() [155/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | LerpHackKernelSamplesComplex |
| ) |  |

Definition at line 579 of file gaussian_blur_filter_contents_unittests.cc.

579 {
580 Scalar sigma = 10.0f;
581 int32_t blur_radius = static_cast<int32_t>(
582 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
583 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
584 .blur_sigma = sigma,
585 .blur_radius = blur_radius,
586 .step_size = 1};
587 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
588 EXPECT_EQ(kernel_samples.sample_count, 33);
589 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
590 LerpHackKernelSamples(kernel_samples);
591 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
592 float data[33];
593 srand(0);
594 for (int i = 0; i < 33; i++) {
595 data[i] = 255.0 * static_cast<double>(IMPELLER_RAND()) / RAND_MAX;
596 }
597
598 auto sampler = [data](Point point) -> Scalar {
599 FML_CHECK(point.y == 0.0f);
600 FML_CHECK(point.x >= -16);
601 FML_CHECK(point.x <= 16);
602 Scalar fint_part;
603 Scalar fract = fabsf(modf(point.x, &fint_part));
604 if (fract == 0) {
605 int32_t int_part = static_cast<int32_t>(fint_part) + 16;
606 return data[int_part];
607 } else {
608 int32_t left = static_cast<int32_t>(floor(point.x)) + 16;
609 int32_t right = static_cast<int32_t>(ceil(point.x)) + 16;
610 if (point.x < 0) {
611 return fract * data[left] + (1.0 - fract) * data[right];
612 } else {
613 return (1.0 - fract) * data[left] + fract * data[right];
614 }
615 }
616 };
617
618 Scalar output = 0.0;
619 for (int i = 0; i < kernel_samples.sample_count; ++i) {
620 auto sample = kernel_samples.samples[i];
621 output += sample.coefficient * sampler(sample.uv_offset);
622 }
623
624 Scalar fast_output = 0.0;
625 for (int i = 0; i < fast_kernel_samples.sample_count; i++) {
626 fast_output += GetCoefficient(fast_kernel_samples.sample_data[i]) *
627 sampler(GetUVOffset(fast_kernel_samples.sample_data[i]));
628 }
629
630 EXPECT_NEAR(output, fast_output, 0.1);
631 }
IMPELLER_RAND
#define IMPELLER_RAND
Definition: gaussian_blur_filter_contents_unittests.cc:19

References blur_radius, impeller::BlurParameters::blur_uv_offset, impeller::GaussianBlurFilterContents::CalculateBlurRadius(), impeller::KernelSample::coefficient, data, impeller::GenerateBlurInfo(), IMPELLER_RAND, impeller::LerpHackKernelSamples(), impeller::KernelSamples::sample_count, and impeller::KernelSamples::samples.

## ◆ TEST() [156/574]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | LerpHackKernelSamplesSimple |
| ) |  |

Definition at line 504 of file gaussian_blur_filter_contents_unittests.cc.

504 {
505 KernelSamples kernel_samples = {
506 .sample_count = 5,
507 .samples =
508 {
509 {
510 .uv_offset = Vector2(-2, 0),
511 .coefficient = 0.1f,
512 },
513 {
514 .uv_offset = Vector2(-1, 0),
515 .coefficient = 0.2f,
516 },
517 {
518 .uv_offset = Vector2(0, 0),
519 .coefficient = 0.4f,
520 },
521 {
522 .uv_offset = Vector2(1, 0),
523 .coefficient = 0.2f,
524 },
525 {
526 .uv_offset = Vector2(2, 0),
527 .coefficient = 0.1f,
528 },
529 },
530 };
531
532 GaussianBlurPipeline::FragmentShader::KernelSamples blur_info =
533 LerpHackKernelSamples(kernel_samples);
534 EXPECT_EQ(blur_info.sample_count, 3);
535
536 KernelSample* samples = kernel_samples.samples;
537
538 //////////////////////////////////////////////////////////////////////////////
539 // Check output kernel.
540
541 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[0]),
542 Point(-1.3333333, 0));
543 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[0]), 0.3);
544
545 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[1]), Point(0, 0));
546 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[1]), 0.4);
547
548 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[2]), Point(1.333333, 0));
549 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[2]), 0.3);
550
551 //////////////////////////////////////////////////////////////////////////////
552 // Check output of fast kernel versus original kernel.
553
554 Scalar data[5] = {0.25, 0.5, 0.5, 1.0, 0.2};
555 Scalar original_output =
556 samples[0].coefficient * data[0] + samples[1].coefficient * data[1] +
557 samples[2].coefficient * data[2] + samples[3].coefficient * data[3] +
558 samples[4].coefficient * data[4];
559
560 auto lerp = [](const Point& point, Scalar left, Scalar right) {
561 Scalar int_part;
562 Scalar fract = fabsf(modf(point.x, &int_part));
563 if (point.x < 0) {
564 return left * fract + right * (1.0 - fract);
565 } else {
566 return left * (1.0 - fract) + right * fract;
567 }
568 };
569 Scalar fast_output =
570 /*1st*/ lerp(GetUVOffset(blur_info.sample_data[0]), data[0], data[1]) *
571 GetCoefficient(blur_info.sample_data[0]) +
572 /*2nd*/ data[2] * GetCoefficient(blur_info.sample_data[1]) +
573 /*3rd*/ lerp(GetUVOffset(blur_info.sample_data[2]), data[3], data[4]) *
574 GetCoefficient(blur_info.sample_data[2]);
575
576 EXPECT_NEAR(original_output, fast_output, 0.01);
577 }
EXPECT_POINT_NEAR
#define EXPECT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:205

References impeller::KernelSample::coefficient, data, EXPECT_POINT_NEAR, impeller::LerpHackKernelSamples(), impeller::KernelSamples::sample_count, impeller::KernelSamples::samples, and impeller::TPoint< T >::x.

## ◆ TEST() [157/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | BlendModeToString |
| ) |  |

Definition at line 1709 of file geometry_unittests.cc.

1709 {
1710 using BlendT = std::underlying_type_t<BlendMode>;
1711 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLastMode); i++) {
1712 auto mode = static_cast<BlendMode>(i);
1713 auto result = BlendModeToString(mode);
1714 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1715 }
1716 }
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1704
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::BlendMode
BlendMode
Definition: color.h:58

References _BLEND_MODE_NAME_CHECK, impeller::BlendModeToString(), IMPELLER_FOR_EACH_BLEND_MODE, and impeller::kLastMode.

## ◆ TEST() [158/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanConvertBetweenDegressAndRadians |
| ) |  |

Definition at line 1718 of file geometry_unittests.cc.

1718 {
1719 {
1720 auto deg = Degrees{90.0};
1721 Radians rad = deg;
1722 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1723 }
1724 }

References impeller::kPiOver2, and impeller::Radians::radians.

## ◆ TEST() [159/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanConvertTTypesExplicitly |
| ) |  |

Definition at line 593 of file geometry_unittests.cc.

593 {
594 {
595 Point p1(1.0, 2.0);
596 IPoint p2 = static_cast<IPoint>(p1);
597 ASSERT_EQ(p2.x, 1u);
598 ASSERT_EQ(p2.y, 2u);
599 }
600
601 {
602 Size s1(1.0, 2.0);
603 ISize s2 = static_cast<ISize>(s1);
604 ASSERT_EQ(s2.width, 1u);
605 ASSERT_EQ(s2.height, 2u);
606 }
607
608 {
609 Size s1(1.0, 2.0);
610 Point p1 = static_cast<Point>(s1);
611 ASSERT_EQ(p1.x, 1u);
612 ASSERT_EQ(p1.y, 2u);
613 }
614 }
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:426
p2
Point p2
Definition: round_superellipse_param.cc:317
p1
Point p1
Definition: round_superellipse_param.cc:313

References impeller::TSize< T >::height, p1, p2, and impeller::TSize< T >::width.

## ◆ TEST() [160/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanGenerateMipCounts |
| ) |  |

Definition at line 580 of file geometry_unittests.cc.

580 {
581 EXPECT_EQ((Size{128, 128}.MipCount()), 7u);
582 EXPECT_EQ((Size{128, 256}.MipCount()), 7u);
583 EXPECT_EQ((Size{128, 130}.MipCount()), 7u);
584 EXPECT_EQ((Size{128, 257}.MipCount()), 7u);
585 EXPECT_EQ((Size{257, 128}.MipCount()), 7u);
586 EXPECT_EQ((Size{128, 0}.MipCount()), 1u);
587 EXPECT_EQ((Size{128, -25}.MipCount()), 1u);
588 EXPECT_EQ((Size{-128, 25}.MipCount()), 1u);
589 EXPECT_EQ((Size{1, 1}.MipCount()), 1u);
590 EXPECT_EQ((Size{0, 0}.MipCount()), 1u);
591 }
impeller::TSize::MipCount
constexpr size_t MipCount() const
Return the mip count of the texture.
Definition: size.h:137

References impeller::TSize< T >::MipCount().

## ◆ TEST() [161/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicPointOps |
| ) |  |

Definition at line 616 of file geometry_unittests.cc.

616 {
617 {
618 IPoint p1(1, 2);
619 IPoint p2 = p1 + IPoint(1, 2);
620 ASSERT_EQ(p2.x, 2u);
621 ASSERT_EQ(p2.y, 4u);
622 }
623
624 {
625 IPoint p1(3, 6);
626 IPoint p2 = p1 - IPoint(1, 2);
627 ASSERT_EQ(p2.x, 2u);
628 ASSERT_EQ(p2.y, 4u);
629 }
630
631 {
632 IPoint p1(1, 2);
633 IPoint p2 = p1 * IPoint(2, 3);
634 ASSERT_EQ(p2.x, 2u);
635 ASSERT_EQ(p2.y, 6u);
636 }
637
638 {
639 IPoint p1(2, 6);
640 IPoint p2 = p1 / IPoint(2, 3);
641 ASSERT_EQ(p2.x, 1u);
642 ASSERT_EQ(p2.y, 2u);
643 }
644 }

References p1, and p2.

## ◆ TEST() [162/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicPointOpsWithArithmeticTypes |
| ) |  |

Definition at line 646 of file geometry_unittests.cc.

646 {
647 // LHS
648 {
649 IPoint p1(1, 2);
650 IPoint p2 = p1 * 2.0f;
651 ASSERT_EQ(p2.x, 2u);
652 ASSERT_EQ(p2.y, 4u);
653 }
654
655 {
656 IPoint p1(2, 6);
657 IPoint p2 = p1 / 2.0f;
658 ASSERT_EQ(p2.x, 1u);
659 ASSERT_EQ(p2.y, 3u);
660 }
661
662 // RHS
663 {
664 IPoint p1(1, 2);
665 IPoint p2 = 2.0f * p1;
666 ASSERT_EQ(p2.x, 2u);
667 ASSERT_EQ(p2.y, 4u);
668 }
669
670 {
671 IPoint p1(2, 6);
672 IPoint p2 = 12.0f / p1;
673 ASSERT_EQ(p2.x, 6u);
674 ASSERT_EQ(p2.y, 2u);
675 }
676 }

References p1, and p2.

## ◆ TEST() [163/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicVector3Ops |
| ) |  |

Definition at line 1276 of file geometry_unittests.cc.

1276 {
1277 {
1278 Vector3 p1(1, 2, 3);
1279 Vector3 p2 = p1 + Vector3(1, 2, 3);
1280 ASSERT_EQ(p2.x, 2u);
1281 ASSERT_EQ(p2.y, 4u);
1282 ASSERT_EQ(p2.z, 6u);
1283 }
1284
1285 {
1286 Vector3 p1(3, 6, 9);
1287 Vector3 p2 = p1 - Vector3(1, 2, 3);
1288 ASSERT_EQ(p2.x, 2u);
1289 ASSERT_EQ(p2.y, 4u);
1290 ASSERT_EQ(p2.z, 6u);
1291 }
1292
1293 {
1294 Vector3 p1(1, 2, 3);
1295 Vector3 p2 = p1 * Vector3(2, 3, 4);
1296 ASSERT_EQ(p2.x, 2u);
1297 ASSERT_EQ(p2.y, 6u);
1298 ASSERT_EQ(p2.z, 12u);
1299 }
1300
1301 {
1302 Vector3 p1(2, 6, 12);
1303 Vector3 p2 = p1 / Vector3(2, 3, 4);
1304 ASSERT_EQ(p2.x, 1u);
1305 ASSERT_EQ(p2.y, 2u);
1306 ASSERT_EQ(p2.z, 3u);
1307 }
1308 }

References p1, and p2.

## ◆ TEST() [164/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicVector3OpsWithArithmeticTypes |
| ) |  |

Definition at line 1310 of file geometry_unittests.cc.

1310 {
1311 // LHS
1312 {
1313 Vector3 p1(1, 2, 3);
1314 Vector3 p2 = p1 + 2.0f;
1315 ASSERT_EQ(p2.x, 3);
1316 ASSERT_EQ(p2.y, 4);
1317 ASSERT_EQ(p2.z, 5);
1318 }
1319
1320 {
1321 Vector3 p1(1, 2, 3);
1322 Vector3 p2 = p1 - 2.0f;
1323 ASSERT_EQ(p2.x, -1);
1324 ASSERT_EQ(p2.y, 0);
1325 ASSERT_EQ(p2.z, 1);
1326 }
1327
1328 {
1329 Vector3 p1(1, 2, 3);
1330 Vector3 p2 = p1 * 2.0f;
1331 ASSERT_EQ(p2.x, 2);
1332 ASSERT_EQ(p2.y, 4);
1333 ASSERT_EQ(p2.z, 6);
1334 }
1335
1336 {
1337 Vector3 p1(2, 6, 12);
1338 Vector3 p2 = p1 / 2.0f;
1339 ASSERT_EQ(p2.x, 1);
1340 ASSERT_EQ(p2.y, 3);
1341 ASSERT_EQ(p2.z, 6);
1342 }
1343
1344 // RHS
1345 {
1346 Vector3 p1(1, 2, 3);
1347 Vector3 p2 = 2.0f + p1;
1348 ASSERT_EQ(p2.x, 3);
1349 ASSERT_EQ(p2.y, 4);
1350 ASSERT_EQ(p2.z, 5);
1351 }
1352
1353 {
1354 Vector3 p1(1, 2, 3);
1355 Vector3 p2 = 2.0f - p1;
1356 ASSERT_EQ(p2.x, 1);
1357 ASSERT_EQ(p2.y, 0);
1358 ASSERT_EQ(p2.z, -1);
1359 }
1360
1361 {
1362 Vector3 p1(1, 2, 3);
1363 Vector3 p2 = 2.0f * p1;
1364 ASSERT_EQ(p2.x, 2);
1365 ASSERT_EQ(p2.y, 4);
1366 ASSERT_EQ(p2.z, 6);
1367 }
1368
1369 {
1370 Vector3 p1(2, 6, 12);
1371 Vector3 p2 = 12.0f / p1;
1372 ASSERT_EQ(p2.x, 6);
1373 ASSERT_EQ(p2.y, 2);
1374 ASSERT_EQ(p2.z, 1);
1375 }
1376 }

References p1, and p2.

## ◆ TEST() [165/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanUsePointAssignmentOperators |
| ) |  |

Definition at line 798 of file geometry_unittests.cc.

798 {
799 // Point on RHS
800 {
801 IPoint p(1, 2);
802 p += IPoint(1, 2);
803 ASSERT_EQ(p.x, 2u);
804 ASSERT_EQ(p.y, 4u);
805 }
806
807 {
808 IPoint p(3, 6);
809 p -= IPoint(1, 2);
810 ASSERT_EQ(p.x, 2u);
811 ASSERT_EQ(p.y, 4u);
812 }
813
814 {
815 IPoint p(1, 2);
816 p *= IPoint(2, 3);
817 ASSERT_EQ(p.x, 2u);
818 ASSERT_EQ(p.y, 6u);
819 }
820
821 {
822 IPoint p(2, 6);
823 p /= IPoint(2, 3);
824 ASSERT_EQ(p.x, 1u);
825 ASSERT_EQ(p.y, 2u);
826 }
827
828 // Size on RHS
829 {
830 IPoint p(1, 2);
831 p += ISize(1, 2);
832 ASSERT_EQ(p.x, 2u);
833 ASSERT_EQ(p.y, 4u);
834 }
835
836 {
837 IPoint p(3, 6);
838 p -= ISize(1, 2);
839 ASSERT_EQ(p.x, 2u);
840 ASSERT_EQ(p.y, 4u);
841 }
842
843 {
844 IPoint p(1, 2);
845 p *= ISize(2, 3);
846 ASSERT_EQ(p.x, 2u);
847 ASSERT_EQ(p.y, 6u);
848 }
849
850 {
851 IPoint p(2, 6);
852 p /= ISize(2, 3);
853 ASSERT_EQ(p.x, 1u);
854 ASSERT_EQ(p.y, 2u);
855 }
856
857 // Arithmetic type on RHS
858 {
859 IPoint p(1, 2);
860 p *= 3;
861 ASSERT_EQ(p.x, 3u);
862 ASSERT_EQ(p.y, 6u);
863 }
864
865 {
866 IPoint p(3, 6);
867 p /= 3;
868 ASSERT_EQ(p.x, 1u);
869 ASSERT_EQ(p.y, 2u);
870 }
871 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [166/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanUseVector3AssignmentOperators |
| ) |  |

Definition at line 1226 of file geometry_unittests.cc.

1226 {
1227 {
1228 Vector3 p(1, 2, 4);
1229 p += Vector3(1, 2, 4);
1230 ASSERT_EQ(p.x, 2u);
1231 ASSERT_EQ(p.y, 4u);
1232 ASSERT_EQ(p.z, 8u);
1233 }
1234
1235 {
1236 Vector3 p(3, 6, 8);
1237 p -= Vector3(1, 2, 3);
1238 ASSERT_EQ(p.x, 2u);
1239 ASSERT_EQ(p.y, 4u);
1240 ASSERT_EQ(p.z, 5u);
1241 }
1242
1243 {
1244 Vector3 p(1, 2, 3);
1245 p *= Vector3(2, 3, 4);
1246 ASSERT_EQ(p.x, 2u);
1247 ASSERT_EQ(p.y, 6u);
1248 ASSERT_EQ(p.z, 12u);
1249 }
1250
1251 {
1252 Vector3 p(1, 2, 3);
1253 p *= 2;
1254 ASSERT_EQ(p.x, 2u);
1255 ASSERT_EQ(p.y, 4u);
1256 ASSERT_EQ(p.z, 6u);
1257 }
1258
1259 {
1260 Vector3 p(2, 6, 12);
1261 p /= Vector3(2, 3, 4);
1262 ASSERT_EQ(p.x, 1u);
1263 ASSERT_EQ(p.y, 2u);
1264 ASSERT_EQ(p.z, 3u);
1265 }
1266
1267 {
1268 Vector3 p(2, 6, 12);
1269 p /= 2;
1270 ASSERT_EQ(p.x, 1u);
1271 ASSERT_EQ(p.y, 3u);
1272 ASSERT_EQ(p.z, 6u);
1273 }
1274 }

References impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [167/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorApplyColorMatrix |
| ) |  |

Definition at line 1483 of file geometry_unittests.cc.

1483 {
1484 {
1485 ColorMatrix color_matrix = {
1486 1, 1, 1, 1, 1, //
1487 1, 1, 1, 1, 1, //
1488 1, 1, 1, 1, 1, //
1489 1, 1, 1, 1, 1, //
1490 };
1491 auto result = Color::White().ApplyColorMatrix(color_matrix);
1492 auto expected = Color(1, 1, 1, 1);
1493 ASSERT_COLOR_NEAR(result, expected);
1494 }
1495
1496 {
1497 ColorMatrix color_matrix = {
1498 0.1, 0, 0, 0, 0.01, //
1499 0, 0.2, 0, 0, 0.02, //
1500 0, 0, 0.3, 0, 0.03, //
1501 0, 0, 0, 0.4, 0.04, //
1502 };
1503 auto result = Color::White().ApplyColorMatrix(color_matrix);
1504 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1505 ASSERT_COLOR_NEAR(result, expected);
1506 }
1507 }
ASSERT_COLOR_NEAR
#define ASSERT_COLOR_NEAR(a, b)
Definition: geometry_asserts.h:192

References impeller::Color::ApplyColorMatrix(), ASSERT_COLOR_NEAR, and impeller::Color::White().

## ◆ TEST() [168/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorBlendReturnsExpectedResults |
| ) |  |

Definition at line 1692 of file geometry_unittests.cc.

1692 {
1693 Color dst = ColorBlendTestData::kDestinationColor;
1694 for (size_t source_i = 0;
1695 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1696 source_i++) {
1697 Color src = ColorBlendTestData::kSourceColors[source_i];
1698
1699 Color expected;
1700 IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK)
1701 }
1702 }
_BLEND_MODE_RESULT_CHECK
#define _BLEND_MODE_RESULT_CHECK(blend_mode)
Definition: geometry_unittests.cc:1686

References _BLEND_MODE_RESULT_CHECK, IMPELLER_FOR_EACH_BLEND_MODE, impeller::testing::ColorBlendTestData::kDestinationColor, and impeller::testing::ColorBlendTestData::kSourceColors.

## ◆ TEST() [169/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorClamp01 |
| ) |  |

Definition at line 1443 of file geometry_unittests.cc.

1443 {
1444 {
1445 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1446 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1447 ASSERT_COLOR_NEAR(result, expected);
1448 }
1449
1450 {
1451 Color result = Color(-1, -1, -1, -1).Clamp01();
1452 Color expected = Color(0, 0, 0, 0);
1453 ASSERT_COLOR_NEAR(result, expected);
1454 }
1455
1456 {
1457 Color result = Color(2, 2, 2, 2).Clamp01();
1458 Color expected = Color(1, 1, 1, 1);
1459 ASSERT_COLOR_NEAR(result, expected);
1460 }
1461 }

References ASSERT_COLOR_NEAR, and impeller::Color::Clamp01().

## ◆ TEST() [170/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorLerp |
| ) |  |

Definition at line 1421 of file geometry_unittests.cc.

1421 {
1422 {
1423 Color a(0.0, 0.0, 0.0, 0.0);
1424 Color b(1.0, 1.0, 1.0, 1.0);
1425
1426 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1427 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1428 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1429 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1430 }
1431
1432 {
1433 Color a(0.2, 0.4, 1.0, 0.5);
1434 Color b(0.4, 1.0, 0.2, 0.3);
1435
1436 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1437 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1438 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1439 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1440 }
1441 }

References ASSERT_COLOR_NEAR, impeller::saturated::b, and impeller::Color::Lerp().

## ◆ TEST() [171/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorLinearToSRGB |
| ) |  |

Definition at line 1509 of file geometry_unittests.cc.

1509 {
1510 {
1511 auto result = Color::White().LinearToSRGB();
1512 auto expected = Color(1, 1, 1, 1);
1513 ASSERT_COLOR_NEAR(result, expected);
1514 }
1515
1516 {
1517 auto result = Color::BlackTransparent().LinearToSRGB();
1518 auto expected = Color(0, 0, 0, 0);
1519 ASSERT_COLOR_NEAR(result, expected);
1520 }
1521
1522 {
1523 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1524 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1525 ASSERT_COLOR_NEAR(result, expected);
1526 }
1527 }

References ASSERT_COLOR_NEAR, impeller::Color::BlackTransparent(), impeller::Color::LinearToSRGB(), and impeller::Color::White().

## ◆ TEST() [172/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorMakeRGBA8 |
| ) |  |

Definition at line 1463 of file geometry_unittests.cc.

1463 {
1464 {
1465 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1466 Color b = Color::BlackTransparent();
1467 ASSERT_COLOR_NEAR(a, b);
1468 }
1469
1470 {
1471 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1472 Color b = Color::White();
1473 ASSERT_COLOR_NEAR(a, b);
1474 }
1475
1476 {
1477 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1478 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1479 ASSERT_COLOR_NEAR(a, b);
1480 }
1481 }

References ASSERT_COLOR_NEAR, impeller::saturated::b, impeller::Color::BlackTransparent(), impeller::Color::MakeRGBA8(), and impeller::Color::White().

## ◆ TEST() [173/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorPremultiply |
| ) |  |

Definition at line 1378 of file geometry_unittests.cc.

1378 {
1379 {
1380 Color a(1.0, 0.5, 0.2, 0.5);
1381 Color premultiplied = a.Premultiply();
1382 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1383 ASSERT_COLOR_NEAR(premultiplied, expected);
1384 }
1385
1386 {
1387 Color a(0.5, 0.25, 0.1, 0.5);
1388 Color unpremultiplied = a.Unpremultiply();
1389 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1390 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1391 }
1392
1393 {
1394 Color a(0.5, 0.25, 0.1, 0.0);
1395 Color unpremultiplied = a.Unpremultiply();
1396 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1397 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1398 }
1399 }

References ASSERT_COLOR_NEAR, impeller::Color::Premultiply(), and impeller::Color::Unpremultiply().

## ◆ TEST() [174/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorPrinting |
| ) |  |

Definition at line 1801 of file geometry_unittests.cc.

1801 {
1802 {
1803 std::stringstream stream;
1804 Color m;
1805 stream << m;
1806 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
1807 }
1808
1809 {
1810 std::stringstream stream;
1811 Color m(1, 2, 3, 4);
1812 stream << m;
1813 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1814 }
1815 }

## ◆ TEST() [175/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorR8G8B8A8 |
| ) |  |

Definition at line 1401 of file geometry_unittests.cc.

1401 {
1402 {
1403 Color a(1.0, 0.5, 0.2, 0.5);
1404 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1405 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1406 }
1407
1408 {
1409 Color a(0.0, 0.0, 0.0, 0.0);
1410 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1411 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1412 }
1413
1414 {
1415 Color a(1.0, 1.0, 1.0, 1.0);
1416 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1417 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1418 }
1419 }
ASSERT_ARRAY_4_NEAR
#define ASSERT_ARRAY_4_NEAR(a, b)
Definition: geometry_asserts.h:197

References ASSERT_ARRAY_4_NEAR, and impeller::Color::ToR8G8B8A8().

## ◆ TEST() [176/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorSRGBToLinear |
| ) |  |

Definition at line 1529 of file geometry_unittests.cc.

1529 {
1530 {
1531 auto result = Color::White().SRGBToLinear();
1532 auto expected = Color(1, 1, 1, 1);
1533 ASSERT_COLOR_NEAR(result, expected);
1534 }
1535
1536 {
1537 auto result = Color::BlackTransparent().SRGBToLinear();
1538 auto expected = Color(0, 0, 0, 0);
1539 ASSERT_COLOR_NEAR(result, expected);
1540 }
1541
1542 {
1543 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1544 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1545 ASSERT_COLOR_NEAR(result, expected);
1546 }
1547 }

References ASSERT_COLOR_NEAR, impeller::Color::BlackTransparent(), impeller::Color::SRGBToLinear(), and impeller::Color::White().

## ◆ TEST() [177/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | DeterminantTest |
| ) |  |

Definition at line 121 of file geometry_unittests.cc.

121 {
122 auto matrix = Matrix{3, 4, 14, 155, 2, 1, 3, 4, 2, 3, 2, 1, 1, 2, 4, 2};
123 ASSERT_EQ(matrix.GetDeterminant(), -1889);
124 }

## ◆ TEST() [178/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Gradient |
| ) |  |

Definition at line 1823 of file geometry_unittests.cc.

1823 {
1824 {
1825 // Simple 2 color gradient produces color buffer containing exactly those
1826 // values.
1827 std::vector<Color> colors = {Color::Red(), Color::Blue()};
1828 std::vector<Scalar> stops = {0.0, 1.0};
1829
1830 auto gradient = CreateGradientBuffer(colors, stops);
1831
1832 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1833 ASSERT_EQ(gradient.texture_size, 2u);
1834 }
1835
1836 {
1837 // Gradient with duplicate stops does not create an empty texture.
1838 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
1839 Color::Blue()};
1840 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
1841
1842 auto gradient = CreateGradientBuffer(colors, stops);
1843 ASSERT_EQ(gradient.texture_size, 5u);
1844 }
1845
1846 {
1847 // Simple N color gradient produces color buffer containing exactly those
1848 // values.
1849 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
1850 Color::White()};
1851 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
1852
1853 auto gradient = CreateGradientBuffer(colors, stops);
1854
1855 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1856 ASSERT_EQ(gradient.texture_size, 4u);
1857 }
1858
1859 {
1860 // Gradient with color stops will lerp and scale buffer.
1861 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
1862 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
1863
1864 auto gradient = CreateGradientBuffer(colors, stops);
1865
1866 std::vector<Color> lerped_colors = {
1867 Color::Red(),
1868 Color::Blue(),
1869 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
1870 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
1871 Color::Green(),
1872 };
1873 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
1874 ASSERT_EQ(gradient.texture_size, 5u);
1875 }
1876
1877 {
1878 // Gradient size is capped at 1024.
1879 std::vector<Color> colors = {};
1880 std::vector<Scalar> stops = {};
1881 for (auto i = 0u; i < 1025; i++) {
1882 colors.push_back(Color::Blue());
1883 stops.push_back(i / 1025.0);
1884 }
1885
1886 auto gradient = CreateGradientBuffer(colors, stops);
1887
1888 ASSERT_EQ(gradient.texture_size, 1024u);
1889 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
1890 }
1891 }
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:198
impeller::CreateGradientBuffer
GradientData CreateGradientBuffer(const std::vector< Color > &colors, const std::vector< Scalar > &stops)
Populate a vector with the interpolated color bytes for the linear gradient described by colors and s...
Definition: gradient.cc:20

References ASSERT_COLOR_BUFFER_NEAR, impeller::Color::Black(), impeller::Color::Blue(), impeller::CreateGradientBuffer(), impeller::Color::Green(), impeller::Color::Lerp(), impeller::Color::Red(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST() [179/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | HalfConversions |
| ) |  |

Definition at line 1893 of file geometry_unittests.cc.

1893 {
1894 #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1895 defined(FML_OS_IOS_SIMULATOR)
1896 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1897 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1898 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1899 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1900
1901 // 65504 is the largest possible half.
1902 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1903 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1904
1905 // Colors
1906 ASSERT_EQ(HalfVector4(Color::Red()),
1907 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1908 ASSERT_EQ(HalfVector4(Color::Green()),
1909 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1910 ASSERT_EQ(HalfVector4(Color::Blue()),
1911 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1912 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1913 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1914
1915 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1916 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1917 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1918
1919 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1920 ASSERT_EQ(Half(0.5), Half(0.5f16));
1921 ASSERT_EQ(Half(5), Half(5.0f16));
1922 #else
1923 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1924 "only used on Apple platforms.";
1925 #endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1926 }
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:32

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Color::Green(), impeller::Color::Red(), and impeller::ScalarToHalf().

## ◆ TEST() [180/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | InvertMatrix |
| ) |  |

Definition at line 126 of file geometry_unittests.cc.

126 {
127 auto inverted = Matrix{10, -9, -12, 8, //
128 7, -12, 11, 22, //
129 -10, 10, 3, 6, //
130 -2, 22, 2, 1}
131 .Invert();
132
133 auto result = Matrix{
134 438.0 / 85123.0, 1751.0 / 85123.0, -7783.0 / 85123.0, 4672.0 / 85123.0,
135 393.0 / 85123.0, -178.0 / 85123.0, -570.0 / 85123.0, 4192 / 85123.0,
136 -5230.0 / 85123.0, 2802.0 / 85123.0, -3461.0 / 85123.0, 962.0 / 85123.0,
137 2690.0 / 85123.0, 1814.0 / 85123.0, 3896.0 / 85123.0, 319.0 / 85123.0};
138
139 ASSERT_MATRIX_NEAR(inverted, result);
140 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::Invert().

## ◆ TEST() [181/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | InvertMultMatrix |
| ) |  |

Definition at line 79 of file geometry_unittests.cc.

79 {
80 {
81 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
82 auto invert = rotation.Invert();
83 // clang-format off
84 auto expect = Matrix{k1OverSqrt2, -k1OverSqrt2, 0, 0,
85 k1OverSqrt2, k1OverSqrt2, 0, 0,
86 0, 0, 1, 0,
87 0, 0, 0, 1};
88 // clang-format on
89 ASSERT_MATRIX_NEAR(invert, expect);
90 }
91 {
92 auto scale = Matrix::MakeScale(Vector2{2, 4});
93 auto invert = scale.Invert();
94 auto expect = Matrix{0.5, 0, 0, 0, //
95 0, 0.25, 0, 0, //
96 0, 0, 1, 0, //
97 0, 0, 0, 1};
98 ASSERT_MATRIX_NEAR(invert, expect);
99 }
100 }
impeller::kPiOver4
constexpr float kPiOver4
Definition: constants.h:35
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:50

References ASSERT_MATRIX_NEAR, impeller::Matrix::Invert(), impeller::k1OverSqrt2, impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [182/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MakeColumn |
| ) |  |

Definition at line 40 of file geometry_unittests.cc.

40 {
41 auto matrix = Matrix::MakeColumn(1, 2, 3, 4, //
42 5, 6, 7, 8, //
43 9, 10, 11, 12, //
44 13, 14, 15, 16);
45
46 auto expect = Matrix{1, 2, 3, 4, //
47 5, 6, 7, 8, //
48 9, 10, 11, 12, //
49 13, 14, 15, 16};
50
51 ASSERT_TRUE(matrix == expect);
52 }

References impeller::Matrix::MakeColumn().

## ◆ TEST() [183/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MakeRow |
| ) |  |

Definition at line 54 of file geometry_unittests.cc.

54 {
55 auto matrix = Matrix::MakeRow(1, 2, 3, 4, //
56 5, 6, 7, 8, //
57 9, 10, 11, 12, //
58 13, 14, 15, 16);
59
60 auto expect = Matrix{1, 5, 9, 13, //
61 2, 6, 10, 14, //
62 3, 7, 11, 15, //
63 4, 8, 12, 16};
64
65 ASSERT_TRUE(matrix == expect);
66 }

References impeller::Matrix::MakeRow().

## ◆ TEST() [184/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixBasis |
| ) |  |

Definition at line 102 of file geometry_unittests.cc.

102 {
103 auto matrix = Matrix{1, 2, 3, 4, //
104 5, 6, 7, 8, //
105 9, 10, 11, 12, //
106 13, 14, 15, 16};
107 auto basis = matrix.Basis();
108 auto expect = Matrix{1, 2, 3, 0, //
109 5, 6, 7, 0, //
110 9, 10, 11, 0, //
111 0, 0, 0, 1};
112 ASSERT_MATRIX_NEAR(basis, expect);
113 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::Basis().

## ◆ TEST() [185/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetBasisVectors |
| ) |  |

Definition at line 408 of file geometry_unittests.cc.

408 {
409 {
410 auto m = Matrix();
411 Vector3 x = m.GetBasisX();
412 Vector3 y = m.GetBasisY();
413 Vector3 z = m.GetBasisZ();
414 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
415 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
416 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
417 }
418
419 {
420 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
421 Matrix::MakeRotationX(Radians{kPiOver2}) *
422 Matrix::MakeScale(Vector3(2, 3, 4));
423 Vector3 x = m.GetBasisX();
424 Vector3 y = m.GetBasisY();
425 Vector3 z = m.GetBasisZ();
426 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
427 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
428 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
429 }
430 }
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:194

References ASSERT_VECTOR3_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and x.

## ◆ TEST() [186/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetDirectionScale |
| ) |  |

Definition at line 432 of file geometry_unittests.cc.

432 {
433 {
434 auto m = Matrix();
435 Scalar result = m.GetDirectionScale(Vector3{1, 0, 0});
436 ASSERT_FLOAT_EQ(result, 1);
437 }
438
439 {
440 auto m = Matrix::MakeRotationX(Degrees{10}) *
441 Matrix::MakeRotationY(Degrees{83}) *
442 Matrix::MakeRotationZ(Degrees{172});
443 Scalar result = m.GetDirectionScale(Vector3{0, 1, 0});
444 ASSERT_FLOAT_EQ(result, 1);
445 }
446
447 {
448 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
449 Matrix::MakeScale(Vector3(3, 4, 5));
450 Scalar result = m.GetDirectionScale(Vector3{2, 0, 0});
451 ASSERT_FLOAT_EQ(result, 8);
452 }
453 }

References impeller::Matrix::GetDirectionScale(), impeller::kPiOver2, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [187/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetMaxBasisLengthXY |
| ) |  |

Definition at line 333 of file geometry_unittests.cc.

333 {
334 {
335 auto m = Matrix::MakeScale({3, 1, 1});
336 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
337
338 m = m * Matrix::MakeSkew(0, 4);
339 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
340 }
341
342 {
343 auto m = Matrix::MakeScale({-3, 4, 7});
344 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
345 }
346
347 {
348 // clang-format off
349 auto m = Matrix::MakeColumn(
350 1.0f, 0.0f, 0.0f, 0.0f,
351 0.0f, 1.0f, 0.0f, 0.0f,
352 4.0f, 0.0f, 1.0f, 0.0f,
353 0.0f, 0.0f, 0.0f, 1.0f
354 );
355 // clang-format on
356 ASSERT_EQ(m.GetMaxBasisLengthXY(), 1.0f);
357 }
358 }

References impeller::Matrix::MakeColumn(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeSkew().

## ◆ TEST() [188/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixLookAt |
| ) |  |

Definition at line 481 of file geometry_unittests.cc.

481 {
482 {
483 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
484 Vector3(0, 1, 0));
485 auto expected = Matrix{
486 1, 0, 0, 0, //
487 0, 1, 0, 0, //
488 0, 0, 1, 0, //
489 0, 0, 1, 1, //
490 };
491 ASSERT_MATRIX_NEAR(m, expected);
492 }
493
494 // Sideways tilt.
495 {
496 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
497 Vector3(1, 1, 0).Normalize());
498
499 // clang-format off
500 auto expected = Matrix{
501 k1OverSqrt2, k1OverSqrt2, 0, 0,
502 -k1OverSqrt2, k1OverSqrt2, 0, 0,
503 0, 0, 1, 0,
504 0, 0, 1, 1,
505 };
506 // clang-format on
507 ASSERT_MATRIX_NEAR(m, expected);
508 }
509
510 // Half way between +x and -y, yaw 90
511 {
512 auto m =
513 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
514
515 // clang-format off
516 auto expected = Matrix{
517 -k1OverSqrt2, 0, k1OverSqrt2, 0,
518 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
519 0, -1, 0, 0,
520 0, 0, 0, 1,
521 };
522 // clang-format on
523 ASSERT_MATRIX_NEAR(m, expected);
524 }
525 }

References ASSERT_MATRIX_NEAR, impeller::k1OverSqrt2, and impeller::Matrix::MakeLookAt().

## ◆ TEST() [189/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakeOrthographic |
| ) |  |

Definition at line 360 of file geometry_unittests.cc.

360 {
361 {
362 auto m = Matrix::MakeOrthographic(Size(100, 200));
363 auto expect = Matrix{
364 0.02, 0, 0, 0, //
365 0, -0.01, 0, 0, //
366 0, 0, 0, 0, //
367 -1, 1, 0.5, 1, //
368 };
369 ASSERT_MATRIX_NEAR(m, expect);
370 }
371
372 {
373 auto m = Matrix::MakeOrthographic(Size(400, 100));
374 auto expect = Matrix{
375 0.005, 0, 0, 0, //
376 0, -0.02, 0, 0, //
377 0, 0, 0, 0, //
378 -1, 1, 0.5, 1, //
379 };
380 ASSERT_MATRIX_NEAR(m, expect);
381 }
382 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::MakeOrthographic().

## ◆ TEST() [190/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakePerspective |
| ) |  |

Definition at line 384 of file geometry_unittests.cc.

384 {
385 {
386 auto m = Matrix::MakePerspective(Degrees(60), Size(100, 200), 1, 10);
387 auto expect = Matrix{
388 3.4641, 0, 0, 0, //
389 0, 1.73205, 0, 0, //
390 0, 0, 1.11111, 1, //
391 0, 0, -1.11111, 0, //
392 };
393 ASSERT_MATRIX_NEAR(m, expect);
394 }
395
396 {
397 auto m = Matrix::MakePerspective(Radians(1), 2, 10, 20);
398 auto expect = Matrix{
399 0.915244, 0, 0, 0, //
400 0, 1.83049, 0, 0, //
401 0, 0, 2, 1, //
402 0, 0, -20, 0, //
403 };
404 ASSERT_MATRIX_NEAR(m, expect);
405 }
406 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::MakePerspective().

## ◆ TEST() [191/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakeRotationFromQuaternion |
| ) |  |

Definition at line 278 of file geometry_unittests.cc.

278 {
279 {
280 auto matrix = Matrix::MakeRotation(Quaternion({1, 0, 0}, kPiOver2));
281 auto expected = Matrix::MakeRotationX(Radians(kPiOver2));
282 ASSERT_MATRIX_NEAR(matrix, expected);
283 }
284
285 {
286 auto matrix = Matrix::MakeRotation(Quaternion({0, 1, 0}, kPiOver2));
287 auto expected = Matrix::MakeRotationY(Radians(kPiOver2));
288 ASSERT_MATRIX_NEAR(matrix, expected);
289 }
290
291 {
292 auto matrix = Matrix::MakeRotation(Quaternion({0, 0, 1}, kPiOver2));
293 auto expected = Matrix::MakeRotationZ(Radians(kPiOver2));
294 ASSERT_MATRIX_NEAR(matrix, expected);
295 }
296 }

References ASSERT_MATRIX_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotation(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [192/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixPrinting |
| ) |  |

Definition at line 1726 of file geometry_unittests.cc.

1726 {
1727 {
1728 std::stringstream stream;
1729 Matrix m;
1730 stream << m;
1731 ASSERT_EQ(stream.str(), R"((
1732 1.000000, 0.000000, 0.000000, 0.000000,
1733 0.000000, 1.000000, 0.000000, 0.000000,
1734 0.000000, 0.000000, 1.000000, 0.000000,
1735 0.000000, 0.000000, 0.000000, 1.000000,
1736 ))");
1737 }
1738
1739 {
1740 std::stringstream stream;
1741 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1742 stream << m;
1743
1744 ASSERT_EQ(stream.str(), R"((
1745 1.000000, 0.000000, 0.000000, 10.000000,
1746 0.000000, 1.000000, 0.000000, 20.000000,
1747 0.000000, 0.000000, 1.000000, 30.000000,
1748 0.000000, 0.000000, 0.000000, 1.000000,
1749 ))");
1750 }
1751 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [193/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixTransformDirection |
| ) |  |

Definition at line 298 of file geometry_unittests.cc.

298 {
299 {
300 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
301 Matrix::MakeRotationZ(Radians{kPiOver2}) *
302 Matrix::MakeScale({2.0, 2.0, 2.0});
303 auto vector = Vector4(10, 20, 30, 2);
304
305 Vector4 result = matrix.TransformDirection(vector);
306 auto expected = Vector4(-40, 20, 60, 2);
307 ASSERT_VECTOR4_NEAR(result, expected);
308 }
309
310 {
311 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
312 Matrix::MakeRotationZ(Radians{kPiOver2}) *
313 Matrix::MakeScale({2.0, 2.0, 2.0});
314 auto vector = Vector3(10, 20, 30);
315
316 Vector3 result = matrix.TransformDirection(vector);
317 auto expected = Vector3(-40, 20, 60);
318 ASSERT_VECTOR3_NEAR(result, expected);
319 }
320
321 {
322 auto matrix = Matrix::MakeTranslation({0, -0.4, 100}) *
323 Matrix::MakeRotationZ(Radians{kPiOver2}) *
324 Matrix::MakeScale({2.0, 2.0, 2.0});
325 auto vector = Point(10, 20);
326
327 Point result = matrix.TransformDirection(vector);
328 auto expected = Point(-40, 20);
329 ASSERT_POINT_NEAR(result, expected);
330 }
331 }
ASSERT_VECTOR4_NEAR
#define ASSERT_VECTOR4_NEAR(a, b)
Definition: geometry_asserts.h:195
ASSERT_POINT_NEAR
#define ASSERT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:193

References ASSERT_POINT_NEAR, ASSERT_VECTOR3_NEAR, ASSERT_VECTOR4_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [194/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixTranslationScaleOnly |
| ) |  |

Definition at line 455 of file geometry_unittests.cc.

455 {
456 {
457 auto m = Matrix();
458 bool result = m.IsTranslationScaleOnly();
459 ASSERT_TRUE(result);
460 }
461
462 {
463 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
464 bool result = m.IsTranslationScaleOnly();
465 ASSERT_TRUE(result);
466 }
467
468 {
469 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
470 bool result = m.IsTranslationScaleOnly();
471 ASSERT_TRUE(result);
472 }
473
474 {
475 auto m = Matrix::MakeRotationZ(Degrees(10));
476 bool result = m.IsTranslationScaleOnly();
477 ASSERT_FALSE(result);
478 }
479 }

References impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [195/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixVectorMultiplication |
| ) |  |

Definition at line 213 of file geometry_unittests.cc.

213 {
214 {
215 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
216 Matrix::MakeRotationZ(Radians{kPiOver2}) *
217 Matrix::MakeScale({2.0, 2.0, 2.0});
218 auto vector = Vector4(10, 20, 30, 2);
219
220 Vector4 result = matrix * vector;
221 auto expected = Vector4(160, 220, 260, 2);
222 ASSERT_VECTOR4_NEAR(result, expected);
223 }
224
225 {
226 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
227 Matrix::MakeRotationZ(Radians{kPiOver2}) *
228 Matrix::MakeScale({2.0, 2.0, 2.0});
229 auto vector = Vector3(10, 20, 30);
230
231 Vector3 result = matrix * vector;
232 auto expected = Vector3(60, 120, 160);
233 ASSERT_VECTOR3_NEAR(result, expected);
234 }
235
236 {
237 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
238 Matrix::MakeRotationZ(Radians{kPiOver2}) *
239 Matrix::MakeScale({2.0, 2.0, 2.0});
240 auto vector = Point(10, 20);
241
242 Point result = matrix * vector;
243 auto expected = Point(60, 120);
244 ASSERT_POINT_NEAR(result, expected);
245 }
246
247 // Matrix Vector ops should respect perspective transforms.
248 {
249 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
250 auto vector = Vector3(3, 3, -3);
251
252 Vector3 result = matrix * vector;
253 auto expected = Vector3(-1, -1, 1.3468);
254 ASSERT_VECTOR3_NEAR(result, expected);
255 }
256
257 {
258 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100) *
259 Matrix::MakeTranslation(Vector3(0, 0, -3));
260 auto point = Point(3, 3);
261
262 Point result = matrix * point;
263 auto expected = Point(-1, -1);
264 ASSERT_POINT_NEAR(result, expected);
265 }
266
267 // Resolves to 0 on perspective singularity.
268 {
269 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
270 auto point = Point(3, 3);
271
272 Point result = matrix * point;
273 auto expected = Point(0, 0);
274 ASSERT_POINT_NEAR(result, expected);
275 }
276 }

References ASSERT_POINT_NEAR, ASSERT_VECTOR3_NEAR, ASSERT_VECTOR4_NEAR, impeller::kPiOver2, impeller::Matrix::MakePerspective(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [196/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MutliplicationMatrix |
| ) |  |

Definition at line 115 of file geometry_unittests.cc.

115 {
116 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
117 auto invert = rotation.Invert();
118 ASSERT_MATRIX_NEAR(rotation * invert, Matrix{});
119 }

References ASSERT_MATRIX_NEAR, impeller::Matrix::Invert(), impeller::kPiOver4, and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [197/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointAbs |
| ) |  |

Definition at line 938 of file geometry_unittests.cc.

938 {
939 Point a(-1, -2);
940 auto a_abs = a.Abs();
941 auto expected = Point(1, 2);
942 ASSERT_POINT_NEAR(a_abs, expected);
943 }

References impeller::TPoint< T >::Abs(), and ASSERT_POINT_NEAR.

## ◆ TEST() [198/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointAngleTo |
| ) |  |

Definition at line 975 of file geometry_unittests.cc.

975 {
976 // Negative result in the CCW (with up = -Y) direction.
977 {
978 Point a(1, 1);
979 Point b(1, -1);
980 Radians actual = a.AngleTo(b);
981 Radians expected = Radians{-kPi / 2};
982 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
983 }
984
985 // Check the other direction to ensure the result is signed correctly.
986 {
987 Point a(1, -1);
988 Point b(1, 1);
989 Radians actual = a.AngleTo(b);
990 Radians expected = Radians{kPi / 2};
991 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
992 }
993
994 // Differences in magnitude should have no impact on the result.
995 {
996 Point a(100, -100);
997 Point b(0.01, 0.01);
998 Radians actual = a.AngleTo(b);
999 Radians expected = Radians{kPi / 2};
1000 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1001 }
1002 }
impeller::kPi
constexpr float kPi
Definition: constants.h:26

References impeller::TPoint< T >::AngleTo(), impeller::saturated::b, impeller::kPi, and impeller::Radians::radians.

## ◆ TEST() [199/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointCeil |
| ) |  |

Definition at line 1113 of file geometry_unittests.cc.

1113 {
1114 Point p(1.5, 2.3);
1115 Point result = p.Ceil();
1116 Point expected(2, 3);
1117 ASSERT_POINT_NEAR(result, expected);
1118 }
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:197

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Ceil().

## ◆ TEST() [200/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointCrossProduct |
| ) |  |

Definition at line 893 of file geometry_unittests.cc.

893 {
894 {
895 Point p(1, 0);
896 Scalar s = p.Cross(Point(-1, 0));
897 ASSERT_FLOAT_EQ(s, 0);
898 }
899
900 {
901 Point p(0, -1);
902 Scalar s = p.Cross(Point(-1, 0));
903 ASSERT_FLOAT_EQ(s, -1);
904 }
905
906 {
907 Point p(1, 2);
908 Scalar s = p.Cross(Point(3, -4));
909 ASSERT_FLOAT_EQ(s, -10);
910 }
911 }

References impeller::TPoint< T >::Cross().

## ◆ TEST() [201/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointDotProduct |
| ) |  |

Definition at line 873 of file geometry_unittests.cc.

873 {
874 {
875 Point p(1, 0);
876 Scalar s = p.Dot(Point(-1, 0));
877 ASSERT_FLOAT_EQ(s, -1);
878 }
879
880 {
881 Point p(0, -1);
882 Scalar s = p.Dot(Point(-1, 0));
883 ASSERT_FLOAT_EQ(s, 0);
884 }
885
886 {
887 Point p(1, 2);
888 Scalar s = p.Dot(Point(3, -4));
889 ASSERT_FLOAT_EQ(s, -5);
890 }
891 }

References impeller::TPoint< T >::Dot().

## ◆ TEST() [202/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointFloor |
| ) |  |

Definition at line 1092 of file geometry_unittests.cc.

1092 {
1093 Point p(1.5, 2.3);
1094 Point result = p.Floor();
1095 Point expected(1, 2);
1096 ASSERT_POINT_NEAR(result, expected);
1097 }
impeller::TPoint::Floor
constexpr TPoint Floor() const
Definition: point.h:195

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Floor().

## ◆ TEST() [203/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointIntegerCoercesToFloat |
| ) |  |

Definition at line 678 of file geometry_unittests.cc.

678 {
679 // Integer on LHS, float on RHS
680 {
681 IPoint p1(1, 2);
682 Point p2 = p1 + Point(1, 2);
683 ASSERT_FLOAT_EQ(p2.x, 2u);
684 ASSERT_FLOAT_EQ(p2.y, 4u);
685 }
686
687 {
688 IPoint p1(3, 6);
689 Point p2 = p1 - Point(1, 2);
690 ASSERT_FLOAT_EQ(p2.x, 2u);
691 ASSERT_FLOAT_EQ(p2.y, 4u);
692 }
693
694 {
695 IPoint p1(1, 2);
696 Point p2 = p1 * Point(2, 3);
697 ASSERT_FLOAT_EQ(p2.x, 2u);
698 ASSERT_FLOAT_EQ(p2.y, 6u);
699 }
700
701 {
702 IPoint p1(2, 6);
703 Point p2 = p1 / Point(2, 3);
704 ASSERT_FLOAT_EQ(p2.x, 1u);
705 ASSERT_FLOAT_EQ(p2.y, 2u);
706 }
707
708 // Float on LHS, integer on RHS
709 {
710 Point p1(1, 2);
711 Point p2 = p1 + IPoint(1, 2);
712 ASSERT_FLOAT_EQ(p2.x, 2u);
713 ASSERT_FLOAT_EQ(p2.y, 4u);
714 }
715
716 {
717 Point p1(3, 6);
718 Point p2 = p1 - IPoint(1, 2);
719 ASSERT_FLOAT_EQ(p2.x, 2u);
720 ASSERT_FLOAT_EQ(p2.y, 4u);
721 }
722
723 {
724 Point p1(1, 2);
725 Point p2 = p1 * IPoint(2, 3);
726 ASSERT_FLOAT_EQ(p2.x, 2u);
727 ASSERT_FLOAT_EQ(p2.y, 6u);
728 }
729
730 {
731 Point p1(2, 6);
732 Point p2 = p1 / IPoint(2, 3);
733 ASSERT_FLOAT_EQ(p2.x, 1u);
734 ASSERT_FLOAT_EQ(p2.y, 2u);
735 }
736 }

References p1, and p2.

## ◆ TEST() [204/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointLerp |
| ) |  |

Definition at line 1155 of file geometry_unittests.cc.

1155 {
1156 Point p(1, 2);
1157 Point result = p.Lerp({5, 10}, 0.75);
1158 Point expected(4, 8);
1159 ASSERT_POINT_NEAR(result, expected);
1160 }
impeller::TPoint::Lerp
constexpr TPoint Lerp(const TPoint &p, Scalar t) const
Definition: point.h:334

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Lerp().

## ◆ TEST() [205/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointMax |
| ) |  |

Definition at line 1071 of file geometry_unittests.cc.

1071 {
1072 Point p(1, 2);
1073 Point result = p.Max({0, 10});
1074 Point expected(1, 10);
1075 ASSERT_POINT_NEAR(result, expected);
1076 }
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:191

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Max().

## ◆ TEST() [206/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointMin |
| ) |  |

Definition at line 1004 of file geometry_unittests.cc.

1004 {
1005 Point p(1, 2);
1006 Point result = p.Min({0, 10});
1007 Point expected(0, 2);
1008 ASSERT_POINT_NEAR(result, expected);
1009 }
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:187

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Min().

## ◆ TEST() [207/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointPrinting |
| ) |  |

Definition at line 1753 of file geometry_unittests.cc.

1753 {
1754 {
1755 std::stringstream stream;
1756 Point m;
1757 stream << m;
1758 ASSERT_EQ(stream.str(), "(0, 0)");
1759 }
1760
1761 {
1762 std::stringstream stream;
1763 Point m(13, 37);
1764 stream << m;
1765 ASSERT_EQ(stream.str(), "(13, 37)");
1766 }
1767 }

## ◆ TEST() [208/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointReflect |
| ) |  |

Definition at line 913 of file geometry_unittests.cc.

913 {
914 {
915 Point axis = Point(0, 1);
916 Point a(2, 3);
917 auto reflected = a.Reflect(axis);
918 auto expected = Point(2, -3);
919 ASSERT_POINT_NEAR(reflected, expected);
920 }
921
922 {
923 Point axis = Point(1, 1).Normalize();
924 Point a(1, 0);
925 auto reflected = a.Reflect(axis);
926 auto expected = Point(0, -1);
927 ASSERT_POINT_NEAR(reflected, expected);
928 }
929
930 {
931 Point axis = Point(1, 1).Normalize();
932 Point a(-1, -1);
933 auto reflected = a.Reflect(axis);
934 ASSERT_POINT_NEAR(reflected, -a);
935 }
936 }
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:285

References ASSERT_POINT_NEAR, impeller::TPoint< T >::Normalize(), and impeller::TPoint< T >::Reflect().

## ◆ TEST() [209/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointRotate |
| ) |  |

Definition at line 945 of file geometry_unittests.cc.

945 {
946 {
947 Point a(1, 0);
948 auto rotated = a.Rotate(Radians{kPiOver2});
949 auto expected = Point(0, 1);
950 ASSERT_POINT_NEAR(rotated, expected);
951 }
952
953 {
954 Point a(1, 0);
955 auto rotated = a.Rotate(Radians{-kPiOver2});
956 auto expected = Point(0, -1);
957 ASSERT_POINT_NEAR(rotated, expected);
958 }
959
960 {
961 Point a(1, 0);
962 auto rotated = a.Rotate(Radians{kPi});
963 auto expected = Point(-1, 0);
964 ASSERT_POINT_NEAR(rotated, expected);
965 }
966
967 {
968 Point a(1, 0);
969 auto rotated = a.Rotate(Radians{kPi * 1.5});
970 auto expected = Point(0, -1);
971 ASSERT_POINT_NEAR(rotated, expected);
972 }
973 }

References ASSERT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, and impeller::TPoint< T >::Rotate().

## ◆ TEST() [210/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointRound |
| ) |  |

Definition at line 1134 of file geometry_unittests.cc.

1134 {
1135 Point p(1.5, 2.3);
1136 Point result = p.Round();
1137 Point expected(2, 2);
1138 ASSERT_POINT_NEAR(result, expected);
1139 }
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:50

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Round().

## ◆ TEST() [211/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | QuaternionLerp |
| ) |  |

Definition at line 527 of file geometry_unittests.cc.

527 {
528 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
529 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
530
531 auto q3 = q1.Slerp(q2, 0.5);
532
533 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
534
535 ASSERT_QUATERNION_NEAR(q3, expected);
536 }
ASSERT_QUATERNION_NEAR
#define ASSERT_QUATERNION_NEAR(a, b)
Definition: geometry_asserts.h:190

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [212/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | QuaternionVectorMultiply |
| ) |  |

Definition at line 538 of file geometry_unittests.cc.

538 {
539 {
540 Quaternion q({0, 0, 1}, 0);
541 Vector3 v(0, 1, 0);
542
543 Vector3 result = q * v;
544 Vector3 expected(0, 1, 0);
545
546 ASSERT_VECTOR3_NEAR(result, expected);
547 }
548
549 {
550 Quaternion q({0, 0, 1}, k2Pi);
551 Vector3 v(1, 0, 0);
552
553 Vector3 result = q * v;
554 Vector3 expected(1, 0, 0);
555
556 ASSERT_VECTOR3_NEAR(result, expected);
557 }
558
559 {
560 Quaternion q({0, 0, 1}, kPiOver4);
561 Vector3 v(0, 1, 0);
562
563 Vector3 result = q * v;
564 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
565
566 ASSERT_VECTOR3_NEAR(result, expected);
567 }
568
569 {
570 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
571 Vector3 v(0, 0, -1);
572
573 Vector3 result = q * v;
574 Vector3 expected(-1, 0, 0);
575
576 ASSERT_VECTOR3_NEAR(result, expected);
577 }
578 }
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29

References ASSERT_VECTOR3_NEAR, impeller::k1OverSqrt2, impeller::k2Pi, impeller::kPi, and impeller::kPiOver4.

## ◆ TEST() [213/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RotationMatrix |
| ) |  |

Definition at line 68 of file geometry_unittests.cc.

68 {
69 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
70 // clang-format off
71 auto expect = Matrix{k1OverSqrt2, k1OverSqrt2, 0, 0,
72 -k1OverSqrt2, k1OverSqrt2, 0, 0,
73 0, 0, 1, 0,
74 0, 0, 0, 1};
75 // clang-format on
76 ASSERT_MATRIX_NEAR(rotation, expect);
77 }

References ASSERT_MATRIX_NEAR, impeller::k1OverSqrt2, impeller::kPiOver4, and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [214/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ScalarNearlyEqual |
| ) |  |

Definition at line 31 of file geometry_unittests.cc.

31 {
32 ASSERT_FALSE(ScalarNearlyEqual(0.0021f, 0.001f));
33 ASSERT_TRUE(ScalarNearlyEqual(0.0019f, 0.001f));
34 ASSERT_TRUE(ScalarNearlyEqual(0.002f, 0.001f, 0.0011f));
35 ASSERT_FALSE(ScalarNearlyEqual(0.002f, 0.001f, 0.0009f));
36 ASSERT_TRUE(ScalarNearlyEqual(
37 1.0f, 1.0f + std::numeric_limits<float>::epsilon() * 4));
38 }
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:36

References impeller::ScalarNearlyEqual().

## ◆ TEST() [215/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SeparatedVector2AngleTo |
| ) |  |

Definition at line 1210 of file geometry_unittests.cc.

1210 {
1211 {
1212 SeparatedVector2 v(Vector2(10, 0));
1213 Radians actual = v.AngleTo(SeparatedVector2(Vector2(5, 0)));
1214 Radians expected = Radians{0};
1215 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1216 }
1217
1218 {
1219 SeparatedVector2 v(Vector2(10, 0));
1220 Radians actual = v.AngleTo(SeparatedVector2(Vector2(0, -5)));
1221 Radians expected = Radians{-kPi / 2};
1222 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1223 }
1224 }
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:57

References impeller::SeparatedVector2::AngleTo(), impeller::kEhCloseEnough, impeller::kPi, and impeller::Radians::radians.

## ◆ TEST() [216/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SeparatedVector2GetAlignment |
| ) |  |

Definition at line 1187 of file geometry_unittests.cc.

1187 {
1188 // Parallel
1189 {
1190 SeparatedVector2 v(Vector2(10, 0));
1191 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(5, 0)));
1192 ASSERT_NEAR(actual, 1, kEhCloseEnough);
1193 }
1194
1195 // Perpendicular
1196 {
1197 SeparatedVector2 v(Vector2(10, 0));
1198 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, 5)));
1199 ASSERT_NEAR(actual, 0, kEhCloseEnough);
1200 }
1201
1202 // Opposite parallel
1203 {
1204 SeparatedVector2 v(Vector2(0, 10));
1205 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, -5)));
1206 ASSERT_NEAR(actual, -1, kEhCloseEnough);
1207 }
1208 }

References impeller::SeparatedVector2::GetAlignment(), and impeller::kEhCloseEnough.

## ◆ TEST() [217/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SeparatedVector2GetVector |
| ) |  |

Definition at line 1182 of file geometry_unittests.cc.

1182 {
1183 SeparatedVector2 v(Vector2(10, 0));
1184 ASSERT_POINT_NEAR(v.GetVector(), Vector2(10, 0));
1185 }

References ASSERT_POINT_NEAR, and impeller::SeparatedVector2::GetVector().

## ◆ TEST() [218/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SeparatedVector2NormalizesWithConstructor |
| ) |  |

Definition at line 1176 of file geometry_unittests.cc.

1176 {
1177 SeparatedVector2 v(Vector2(10, 0));
1178 ASSERT_POINT_NEAR(v.direction, Vector2(1, 0));
1179 ASSERT_NEAR(v.magnitude, 10, kEhCloseEnough);
1180 }

References ASSERT_POINT_NEAR, impeller::SeparatedVector2::direction, impeller::kEhCloseEnough, and impeller::SeparatedVector2::magnitude.

## ◆ TEST() [219/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SizeCoercesToPoint |
| ) |  |

Definition at line 738 of file geometry_unittests.cc.

738 {
739 // Point on LHS, Size on RHS
740 {
741 IPoint p1(1, 2);
742 IPoint p2 = p1 + ISize(1, 2);
743 ASSERT_EQ(p2.x, 2u);
744 ASSERT_EQ(p2.y, 4u);
745 }
746
747 {
748 IPoint p1(3, 6);
749 IPoint p2 = p1 - ISize(1, 2);
750 ASSERT_EQ(p2.x, 2u);
751 ASSERT_EQ(p2.y, 4u);
752 }
753
754 {
755 IPoint p1(1, 2);
756 IPoint p2 = p1 * ISize(2, 3);
757 ASSERT_EQ(p2.x, 2u);
758 ASSERT_EQ(p2.y, 6u);
759 }
760
761 {
762 IPoint p1(2, 6);
763 IPoint p2 = p1 / ISize(2, 3);
764 ASSERT_EQ(p2.x, 1u);
765 ASSERT_EQ(p2.y, 2u);
766 }
767
768 // Size on LHS, Point on RHS
769 {
770 ISize p1(1, 2);
771 IPoint p2 = p1 + IPoint(1, 2);
772 ASSERT_EQ(p2.x, 2u);
773 ASSERT_EQ(p2.y, 4u);
774 }
775
776 {
777 ISize p1(3, 6);
778 IPoint p2 = p1 - IPoint(1, 2);
779 ASSERT_EQ(p2.x, 2u);
780 ASSERT_EQ(p2.y, 4u);
781 }
782
783 {
784 ISize p1(1, 2);
785 IPoint p2 = p1 * IPoint(2, 3);
786 ASSERT_EQ(p2.x, 2u);
787 ASSERT_EQ(p2.y, 6u);
788 }
789
790 {
791 ISize p1(2, 6);
792 IPoint p2 = p1 / IPoint(2, 3);
793 ASSERT_EQ(p2.x, 1u);
794 ASSERT_EQ(p2.y, 2u);
795 }
796 }

References p1, and p2.

## ◆ TEST() [220/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestDecomposition |
| ) |  |

Definition at line 142 of file geometry_unittests.cc.

142 {
143 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
144
145 auto result = rotated.Decompose();
146
147 ASSERT_TRUE(result.has_value());
148
149 MatrixDecomposition res = result.value();
150
151 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
152 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
153 }

References ASSERT_QUATERNION_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::MatrixDecomposition::rotation.

## ◆ TEST() [221/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestDecomposition2 |
| ) |  |

Definition at line 155 of file geometry_unittests.cc.

155 {
156 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
157 auto scaled = Matrix::MakeScale({2.0, 3.0, 1.0});
158 auto translated = Matrix::MakeTranslation({-200, 750, 20});
159
160 auto result = (translated * rotated * scaled).Decompose();
161
162 ASSERT_TRUE(result.has_value());
163
164 MatrixDecomposition res = result.value();
165
166 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
167
168 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
169
170 ASSERT_FLOAT_EQ(res.translation.x, -200);
171 ASSERT_FLOAT_EQ(res.translation.y, 750);
172 ASSERT_FLOAT_EQ(res.translation.z, 20);
173
174 ASSERT_FLOAT_EQ(res.scale.x, 2);
175 ASSERT_FLOAT_EQ(res.scale.y, 3);
176 ASSERT_FLOAT_EQ(res.scale.z, 1);
177 }

References ASSERT_QUATERNION_NEAR, impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::MatrixDecomposition::rotation, impeller::MatrixDecomposition::scale, impeller::MatrixDecomposition::translation, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [222/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestRecomposition |
| ) |  |

Definition at line 179 of file geometry_unittests.cc.

179 {
180 /*
181 * Decomposition.
182 */
183 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
184
185 auto result = rotated.Decompose();
186
187 ASSERT_TRUE(result.has_value());
188
189 MatrixDecomposition res = result.value();
190
191 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
192
193 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
194
195 /*
196 * Recomposition.
197 */
198 ASSERT_MATRIX_NEAR(rotated, Matrix{res});
199 }

References ASSERT_MATRIX_NEAR, ASSERT_QUATERNION_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::MatrixDecomposition::rotation.

## ◆ TEST() [223/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestRecomposition2 |
| ) |  |

Definition at line 201 of file geometry_unittests.cc.

201 {
202 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
203 Matrix::MakeRotationZ(Radians{kPiOver4}) *
204 Matrix::MakeScale({2.0, 2.0, 2.0});
205
206 auto result = matrix.Decompose();
207
208 ASSERT_TRUE(result.has_value());
209
210 ASSERT_MATRIX_NEAR(matrix, Matrix{result.value()});
211 }

References ASSERT_MATRIX_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [224/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ToIColor |
| ) |  |

Definition at line 1817 of file geometry_unittests.cc.

1817 {
1818 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1819 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1820 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1821 }

References impeller::Color::ToIColor().

## ◆ TEST() [225/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Ceil |
| ) |  |

Definition at line 1120 of file geometry_unittests.cc.

1120 {
1121 Vector3 p(1.5, 2.3, 3.9);
1122 Vector3 result = p.Ceil();
1123 Vector3 expected(2, 3, 4);
1124 ASSERT_VECTOR3_NEAR(result, expected);
1125 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Ceil().

## ◆ TEST() [226/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Floor |
| ) |  |

Definition at line 1099 of file geometry_unittests.cc.

1099 {
1100 Vector3 p(1.5, 2.3, 3.9);
1101 Vector3 result = p.Floor();
1102 Vector3 expected(1, 2, 3);
1103 ASSERT_VECTOR3_NEAR(result, expected);
1104 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Floor().

## ◆ TEST() [227/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Lerp |
| ) |  |

Definition at line 1162 of file geometry_unittests.cc.

1162 {
1163 Vector3 p(1, 2, 3);
1164 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1165 Vector3 expected(4, 8, 12);
1166 ASSERT_VECTOR3_NEAR(result, expected);
1167 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Lerp().

## ◆ TEST() [228/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Max |
| ) |  |

Definition at line 1078 of file geometry_unittests.cc.

1078 {
1079 Vector3 p(1, 2, 3);
1080 Vector3 result = p.Max({0, 10, 2});
1081 Vector3 expected(1, 10, 3);
1082 ASSERT_VECTOR3_NEAR(result, expected);
1083 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Max().

## ◆ TEST() [229/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Min |
| ) |  |

Definition at line 1057 of file geometry_unittests.cc.

1057 {
1058 Vector3 p(1, 2, 3);
1059 Vector3 result = p.Min({0, 10, 2});
1060 Vector3 expected(0, 2, 2);
1061 ASSERT_VECTOR3_NEAR(result, expected);
1062 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Min().

## ◆ TEST() [230/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Printing |
| ) |  |

Definition at line 1769 of file geometry_unittests.cc.

1769 {
1770 {
1771 std::stringstream stream;
1772 Vector3 m;
1773 stream << m;
1774 ASSERT_EQ(stream.str(), "(0, 0, 0)");
1775 }
1776
1777 {
1778 std::stringstream stream;
1779 Vector3 m(1, 2, 3);
1780 stream << m;
1781 ASSERT_EQ(stream.str(), "(1, 2, 3)");
1782 }
1783 }

## ◆ TEST() [231/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Round |
| ) |  |

Definition at line 1141 of file geometry_unittests.cc.

1141 {
1142 Vector3 p(1.5, 2.3, 3.9);
1143 Vector3 result = p.Round();
1144 Vector3 expected(2, 2, 4);
1145 ASSERT_VECTOR3_NEAR(result, expected);
1146 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Round().

## ◆ TEST() [232/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Ceil |
| ) |  |

Definition at line 1127 of file geometry_unittests.cc.

1127 {
1128 Vector4 p(1.5, 2.3, 3.9, 4.0);
1129 Vector4 result = p.Ceil();
1130 Vector4 expected(2, 3, 4, 4);
1131 ASSERT_VECTOR4_NEAR(result, expected);
1132 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Ceil().

## ◆ TEST() [233/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Floor |
| ) |  |

Definition at line 1106 of file geometry_unittests.cc.

1106 {
1107 Vector4 p(1.5, 2.3, 3.9, 4.0);
1108 Vector4 result = p.Floor();
1109 Vector4 expected(1, 2, 3, 4);
1110 ASSERT_VECTOR4_NEAR(result, expected);
1111 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Floor().

## ◆ TEST() [234/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4IsFinite |
| ) |  |

Definition at line 1011 of file geometry_unittests.cc.

1011 {
1012 {
1013 Vector4 v;
1014 ASSERT_TRUE(v.IsFinite());
1015 v.x = std::numeric_limits<Scalar>::infinity();
1016 ASSERT_FALSE(v.IsFinite());
1017 v.x = -std::numeric_limits<Scalar>::infinity();
1018 ASSERT_FALSE(v.IsFinite());
1019 v.x = -std::numeric_limits<Scalar>::quiet_NaN();
1020 ASSERT_FALSE(v.IsFinite());
1021 }
1022
1023 {
1024 Vector4 v;
1025 ASSERT_TRUE(v.IsFinite());
1026 v.y = std::numeric_limits<Scalar>::infinity();
1027 ASSERT_FALSE(v.IsFinite());
1028 v.y = -std::numeric_limits<Scalar>::infinity();
1029 ASSERT_FALSE(v.IsFinite());
1030 v.y = -std::numeric_limits<Scalar>::quiet_NaN();
1031 ASSERT_FALSE(v.IsFinite());
1032 }
1033
1034 {
1035 Vector4 v;
1036 ASSERT_TRUE(v.IsFinite());
1037 v.z = std::numeric_limits<Scalar>::infinity();
1038 ASSERT_FALSE(v.IsFinite());
1039 v.z = -std::numeric_limits<Scalar>::infinity();
1040 ASSERT_FALSE(v.IsFinite());
1041 v.z = -std::numeric_limits<Scalar>::quiet_NaN();
1042 ASSERT_FALSE(v.IsFinite());
1043 }
1044
1045 {
1046 Vector4 v;
1047 ASSERT_TRUE(v.IsFinite());
1048 v.w = std::numeric_limits<Scalar>::infinity();
1049 ASSERT_FALSE(v.IsFinite());
1050 v.w = -std::numeric_limits<Scalar>::infinity();
1051 ASSERT_FALSE(v.IsFinite());
1052 v.w = -std::numeric_limits<Scalar>::quiet_NaN();
1053 ASSERT_FALSE(v.IsFinite());
1054 }
1055 }

References impeller::Vector4::IsFinite(), impeller::Vector4::w, impeller::Vector4::x, impeller::Vector4::y, and impeller::Vector4::z.

## ◆ TEST() [235/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Lerp |
| ) |  |

Definition at line 1169 of file geometry_unittests.cc.

1169 {
1170 Vector4 p(1, 2, 3, 4);
1171 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1172 Vector4 expected(4, 8, 12, 16);
1173 ASSERT_VECTOR4_NEAR(result, expected);
1174 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Lerp().

## ◆ TEST() [236/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Max |
| ) |  |

Definition at line 1085 of file geometry_unittests.cc.

1085 {
1086 Vector4 p(1, 2, 3, 4);
1087 Vector4 result = p.Max({0, 10, 2, 1});
1088 Vector4 expected(1, 10, 3, 4);
1089 ASSERT_VECTOR4_NEAR(result, expected);
1090 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Max().

## ◆ TEST() [237/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Min |
| ) |  |

Definition at line 1064 of file geometry_unittests.cc.

1064 {
1065 Vector4 p(1, 2, 3, 4);
1066 Vector4 result = p.Min({0, 10, 2, 1});
1067 Vector4 expected(0, 2, 2, 1);
1068 ASSERT_VECTOR4_NEAR(result, expected);
1069 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Min().

## ◆ TEST() [238/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Printing |
| ) |  |

Definition at line 1785 of file geometry_unittests.cc.

1785 {
1786 {
1787 std::stringstream stream;
1788 Vector4 m;
1789 stream << m;
1790 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
1791 }
1792
1793 {
1794 std::stringstream stream;
1795 Vector4 m(1, 2, 3, 4);
1796 stream << m;
1797 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1798 }
1799 }

## ◆ TEST() [239/574]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Round |
| ) |  |

Definition at line 1148 of file geometry_unittests.cc.

1148 {
1149 Vector4 p(1.5, 2.3, 3.9, 4.0);
1150 Vector4 result = p.Round();
1151 Vector4 expected(2, 2, 4, 4);
1152 ASSERT_VECTOR4_NEAR(result, expected);
1153 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Round().

## ◆ TEST() [240/574]

impeller::testing::TEST | ( | LineContents | ,
|  | CalculatePerVertex |
| ) |  |

Definition at line 59 of file line_contents_unittests.cc.

59 {
60 LineVertexShader::PerVertexData per_vertex[4];
61 auto geometry = std::make_unique<LineGeometry>(
62 /*p0=*/Point{100, 100}, //
63 /*p1=*/Point{200, 100}, //
64 StrokeParameters{
65 .width = 5.f,
66 .cap = Cap::kButt,
67 });
68 Matrix transform;
69
70 fml::StatusOr<LineContents::EffectiveLineParameters> status =
71 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
72 Scalar offset =
73 (LineContents::kSampleRadius * 2.0 + geometry->GetWidth()) / 2.f;
74 ASSERT_TRUE(status.ok());
75 EXPECT_EQ(status.value().width, 5.f);
76 EXPECT_EQ(status.value().radius, LineContents::kSampleRadius);
77 EXPECT_POINT_NEAR(per_vertex[0].position,
78 Point(100 - LineContents::kSampleRadius, 100 + offset));
79 EXPECT_POINT_NEAR(per_vertex[1].position,
80 Point(200 + LineContents::kSampleRadius, 100 + offset));
81 EXPECT_POINT_NEAR(per_vertex[2].position,
82 Point(100 - LineContents::kSampleRadius, 100 - offset));
83 EXPECT_POINT_NEAR(per_vertex[3].position,
84 Point(200 + LineContents::kSampleRadius, 100 - offset));
85
86 for (int i = 1; i < 4; ++i) {
87 EXPECT_VECTOR3_NEAR(per_vertex[0].e0, per_vertex[i].e0) << i;
88 EXPECT_VECTOR3_NEAR(per_vertex[0].e1, per_vertex[i].e1) << i;
89 EXPECT_VECTOR3_NEAR(per_vertex[0].e2, per_vertex[i].e2) << i;
90 EXPECT_VECTOR3_NEAR(per_vertex[0].e3, per_vertex[i].e3) << i;
91 }
92
93 EXPECT_EQ(CalculateLine(per_vertex[0], Point(0, 0)), 0.f);
94 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset)), 0.f,
95 kEhCloseEnough);
96 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 + offset * 0.5)),
97 0.5f, kEhCloseEnough);
98 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
99 kEhCloseEnough);
100 }
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:312
EXPECT_VECTOR3_NEAR
#define EXPECT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:206
e0
Vector3 e0
Definition: line_contents.cc:106
e2
Vector3 e2
Definition: line_contents.cc:108
e1
Vector3 e1
Definition: line_contents.cc:107

References impeller::LineContents::CalculatePerVertex(), e0, e1, e2, e3, EXPECT_POINT_NEAR, EXPECT_VECTOR3_NEAR, impeller::kButt, impeller::kEhCloseEnough, impeller::LineContents::kSampleRadius, transform, and impeller::StrokeParameters::width.

## ◆ TEST() [241/574]

impeller::testing::TEST | ( | LineContents | ,
|  | CalculatePerVertexLimit |
| ) |  |

Definition at line 125 of file line_contents_unittests.cc.

125 {
126 LineVertexShader::PerVertexData per_vertex[4];
127 Scalar scale = 0.05;
128 auto geometry = std::make_unique<LineGeometry>(
129 /*p0=*/Point{100, 100}, //
130 /*p1=*/Point{200, 100}, //
131 StrokeParameters{
132 .width = 10.f,
133 .cap = Cap::kButt,
134 });
135 Matrix transform = Matrix::MakeTranslation({100, 100, 1.0}) *
136 Matrix::MakeScale({scale, scale, 1.0}) *
137 Matrix::MakeTranslation({-100, -100, 1.0});
138
139 fml::StatusOr<LineContents::EffectiveLineParameters> status =
140 LineContents::CalculatePerVertex(per_vertex, geometry.get(), transform);
141
142 Scalar one_radius_size = std::max(LineContents::kSampleRadius / scale,
143 LineContents::kSampleRadius);
144 Scalar one_px_size = 1.f / scale;
145 Scalar offset = one_px_size / 2.f + one_radius_size;
146 ASSERT_TRUE(status.ok());
147 EXPECT_NEAR(status.value().width, 20.f, kEhCloseEnough);
148 EXPECT_NEAR(status.value().radius, one_px_size * LineContents::kSampleRadius,
149 kEhCloseEnough);
150 EXPECT_POINT_NEAR(per_vertex[0].position,
151 Point(100 - one_radius_size, 100 + offset));
152 EXPECT_POINT_NEAR(per_vertex[1].position,
153 Point(200 + one_radius_size, 100 + offset));
154 EXPECT_POINT_NEAR(per_vertex[2].position,
155 Point(100 - one_radius_size, 100 - offset));
156 EXPECT_POINT_NEAR(per_vertex[3].position,
157 Point(200 + one_radius_size, 100 - offset));
158
159 EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100)), 1.f,
160 kEhCloseEnough);
161 // EXPECT_NEAR(CalculateLine(per_vertex[0], Point(150, 100 +
162 // one_px_size)), 1.f,
163 // kEhCloseEnough);
164 }

References impeller::LineContents::CalculatePerVertex(), EXPECT_POINT_NEAR, impeller::kButt, impeller::kEhCloseEnough, impeller::LineContents::kSampleRadius, impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), transform, and impeller::StrokeParameters::width.

## ◆ TEST() [242/574]

impeller::testing::TEST | ( | LineContents | ,
|  | Create |
| ) |  |

Definition at line 37 of file line_contents_unittests.cc.

37 {
38 Scalar width = 5.0f;
39 auto geometry = std::make_unique<LineGeometry>(
40 /*p0=*/Point{0, 0}, //
41 /*p1=*/Point{100, 100}, //
42 StrokeParameters{
43 .width = width,
44 .cap = Cap::kSquare,
45 });
46 std::unique_ptr<LineContents> contents =
47 LineContents::Make(std::move(geometry), Color(1.f, 0.f, 0.f, 1.f));
48 EXPECT_TRUE(contents);
49 Entity entity;
50 std::optional<Rect> coverage = contents->GetCoverage(entity);
51 EXPECT_TRUE(coverage.has_value());
52 if (coverage.has_value()) {
53 Scalar lip = sqrt((width * width) / 2.f);
54 EXPECT_EQ(*coverage,
55 Rect::MakeXYWH(-lip, -lip, 100 + 2 * lip, 100 + 2 * lip));
56 }
57 }

References impeller::Entity::GetCoverage(), impeller::kSquare, impeller::LineContents::Make(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::StrokeParameters::width.

## ◆ TEST() [243/574]

impeller::testing::TEST | ( | LineContents | ,
|  | CreateCurveData |
| ) |  |

Definition at line 102 of file line_contents_unittests.cc.

102 {
103 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/31,
104 /*radius=*/1,
105 /*scale=*/1);
106 EXPECT_EQ(data.size(), 32u);
107 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
108 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
109 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
110 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
111 }

References impeller::LineContents::CreateCurveData(), data, and impeller::kEhCloseEnough.

## ◆ TEST() [244/574]

impeller::testing::TEST | ( | LineContents | ,
|  | CreateCurveDataScaled |
| ) |  |

Definition at line 113 of file line_contents_unittests.cc.

113 {
114 std::vector<uint8_t> data = LineContents::CreateCurveData(/*width=*/15.5,
115 /*radius=*/1,
116 /*scale=*/2);
117 EXPECT_EQ(data.size(), 32u);
118 EXPECT_NEAR(data[0] / 255.f, 0.f, kEhCloseEnough);
119 EXPECT_NEAR(data[1] / 255.f, 0.5f, 0.02);
120 EXPECT_NEAR(data[2] / 255.f, 1.f, kEhCloseEnough);
121 EXPECT_NEAR(data[3] / 255.f, 1.f, kEhCloseEnough);
122 }

References impeller::LineContents::CreateCurveData(), data, and impeller::kEhCloseEnough.

## ◆ TEST() [245/574]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | Coverage2x |
| ) |  |

Definition at line 65 of file matrix_filter_contents_unittests.cc.

65 {
66 MatrixFilterContents contents;
67 contents.SetMatrix(Matrix::MakeScale({2.0, 2.0, 1.0}));
68 FilterInput::Vector inputs = {
69 FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
70 Entity entity;
71 std::optional<Rect> coverage =
72 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
73
74 ASSERT_EQ(coverage, Rect::MakeXYWH(20, 20, 200, 200));
75 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::MatrixFilterContents::SetMatrix().

## ◆ TEST() [246/574]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | Coverage2xEffect |
| ) |  |

Definition at line 77 of file matrix_filter_contents_unittests.cc.

77 {
78 MatrixFilterContents contents;
79 FilterInput::Vector inputs = {
80 FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
81 Entity entity;
82 std::optional<Rect> coverage = contents.GetFilterCoverage(
83 inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
84
85 ASSERT_EQ(coverage, Rect::MakeXYWH(10, 10, 100, 100));
86 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [247/574]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | CoverageEmpty |
| ) |  |

Definition at line 45 of file matrix_filter_contents_unittests.cc.

45 {
46 MatrixFilterContents contents;
47 FilterInput::Vector inputs = {};
48 Entity entity;
49 std::optional<Rect> coverage =
50 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
51 ASSERT_FALSE(coverage.has_value());
52 }

References impeller::MatrixFilterContents::GetFilterCoverage().

## ◆ TEST() [248/574]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | CoverageSimple |
| ) |  |

Definition at line 54 of file matrix_filter_contents_unittests.cc.

54 {
55 MatrixFilterContents contents;
56 FilterInput::Vector inputs = {
57 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
58 Entity entity;
59 std::optional<Rect> coverage =
60 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
61
62 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
63 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [249/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | Equals |
| ) |  |

Definition at line 28 of file matrix_unittests.cc.

28 {
29 Matrix x;
30 Matrix y = x;
31 EXPECT_TRUE(x.Equals(y));
32 }

References x.

## ◆ TEST() [250/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | GetMaxBasisXYNegativeScale |
| ) |  |

Definition at line 263 of file matrix_unittests.cc.

263 {
264 Matrix m = Matrix::MakeScale({-2, 1, 1});
265
266 EXPECT_EQ(m.GetMaxBasisLengthXY(), 2);
267
268 m = Matrix::MakeScale({1, -3, 1});
269
270 EXPECT_EQ(m.GetMaxBasisLengthXY(), 3);
271 }

References impeller::Matrix::GetMaxBasisLengthXY(), and impeller::Matrix::MakeScale().

## ◆ TEST() [251/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | GetMaxBasisXYWithLargeAndSmallScalingFactor |
| ) |  |

Definition at line 274 of file matrix_unittests.cc.

274 {
275 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
276 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e+20, 1e+20);
277
278 m = Matrix::MakeScale({2.625e-20, 2.625e-20, 1});
279 EXPECT_NEAR(m.GetMaxBasisLengthXY(), 2.625e-20, 1e-20);
280 }

References impeller::Matrix::GetMaxBasisLengthXY(), and impeller::Matrix::MakeScale().

## ◆ TEST() [252/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | GetMaxBasisXYWithLargeAndSmallScalingFactorNonScaleTranslate |
| ) |  |

Definition at line 282 of file matrix_unittests.cc.

282 {
283 Matrix m = Matrix::MakeScale({2.625e+20, 2.625e+20, 1});
284 m.e[0][1] = 2;
285
286 EXPECT_TRUE(std::isinf(m.GetMaxBasisLengthXY()));
287 }

References impeller::Matrix::e, impeller::Matrix::GetMaxBasisLengthXY(), and impeller::Matrix::MakeScale().

## ◆ TEST() [253/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasPerspective |
| ) |  |

Definition at line 58 of file matrix_unittests.cc.

58 {
59 EXPECT_FALSE(Matrix().HasPerspective());
60
61 auto test = [](int index, bool expect) {
62 Matrix matrix;
63 EXPECT_FALSE(matrix.HasPerspective());
64 matrix.m[index] = 0.5f;
65 EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
66 };
67
68 // clang-format off
69 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
70 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
71 test( 8, false); test( 9, false); test(10, false); test(11, true);
72 test(12, false); test(13, false); test(14, false); test(15, true);
73 // clang-format on
74 }

References impeller::Matrix::HasPerspective(), and impeller::Matrix::m.

## ◆ TEST() [254/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasPerspective2D |
| ) |  |

Definition at line 40 of file matrix_unittests.cc.

40 {
41 EXPECT_FALSE(Matrix().HasPerspective2D());
42
43 auto test = [](int index, bool expect) {
44 Matrix matrix;
45 EXPECT_FALSE(matrix.HasPerspective2D());
46 matrix.m[index] = 0.5f;
47 EXPECT_EQ(matrix.HasPerspective2D(), expect) << "index: " << index;
48 };
49
50 // clang-format off
51 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
52 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
53 test( 8, false); test( 9, false); test(10, false); test(11, false);
54 test(12, false); test(13, false); test(14, false); test(15, true);
55 // clang-format on
56 }

References impeller::Matrix::HasPerspective2D(), and impeller::Matrix::m.

## ◆ TEST() [255/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasTranslation |
| ) |  |

Definition at line 76 of file matrix_unittests.cc.

76 {
77 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).HasTranslation());
78 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).HasTranslation());
79 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).HasTranslation());
80 EXPECT_FALSE(Matrix().HasTranslation());
81 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [256/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsAligned |
| ) |  |

Definition at line 203 of file matrix_unittests.cc.

203 {
204 EXPECT_TRUE(Matrix().IsAligned());
205 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
206
207 // Begin Legacy tests transferred over from geometry_unittests.cc
208 {
209 auto m = Matrix::MakeTranslation({1, 2, 3});
210 bool result = m.IsAligned();
211 ASSERT_TRUE(result);
212 }
213
214 {
215 auto m = Matrix::MakeRotationZ(Degrees{123});
216 bool result = m.IsAligned();
217 ASSERT_FALSE(result);
218 }
219 // End Legacy tests transferred over from geometry_unittests.cc
220
221 auto test = [](int index, bool expect) {
222 Matrix matrix;
223 EXPECT_TRUE(matrix.IsAligned());
224 matrix.m[index] = 0.5f;
225 EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
226 };
227
228 // clang-format off
229 test( 0, true); test( 1, false); test( 2, false); test( 3, false);
230 test( 4, false); test( 5, true); test( 6, false); test( 7, false);
231 test( 8, false); test( 9, false); test(10, true); test(11, false);
232 test(12, true); test(13, true); test(14, true); test(15, false);
233 // clang-format on
234
235 // True for quadrant rotations from -250 to +250 full circles
236 for (int i = -1000; i < 1000; i++) {
237 Degrees d = Degrees(i * 90);
238 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
239 EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
240 }
241
242 // False for half degree rotations from -999.5 to +1000.5 degrees
243 for (int i = -1000; i < 1000; i++) {
244 Degrees d = Degrees(i + 0.5f);
245 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
246 EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
247 }
248 }

References impeller::Degrees::degrees, impeller::Matrix::IsAligned(), impeller::Matrix::m, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [257/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsAligned2D |
| ) |  |

Definition at line 170 of file matrix_unittests.cc.

170 {
171 EXPECT_TRUE(Matrix().IsAligned2D());
172 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
173
174 auto test = [](int index, bool expect) {
175 Matrix matrix;
176 EXPECT_TRUE(matrix.IsAligned2D());
177 matrix.m[index] = 0.5f;
178 EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
179 };
180
181 // clang-format off
182 test( 0, true); test( 1, false); test( 2, true); test( 3, false);
183 test( 4, false); test( 5, true); test( 6, true); test( 7, false);
184 test( 8, true); test( 9, true); test(10, true); test(11, true);
185 test(12, true); test(13, true); test(14, true); test(15, false);
186 // clang-format on
187
188 // True for quadrant rotations from -250 to +250 full circles
189 for (int i = -1000; i < 1000; i++) {
190 Degrees d = Degrees(i * 90);
191 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
192 EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
193 }
194
195 // False for half degree rotations from -999.5 to +1000.5 degrees
196 for (int i = -1000; i < 1000; i++) {
197 Degrees d = Degrees(i + 0.5f);
198 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
199 EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
200 }
201 }

References impeller::Degrees::degrees, impeller::Matrix::IsAligned2D(), impeller::Matrix::m, impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [258/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsFinite |
| ) |  |

Definition at line 132 of file matrix_unittests.cc.

132 {
133 EXPECT_TRUE(Matrix().IsFinite());
134
135 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsFinite());
136 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsFinite());
137
138 EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsFinite());
139 EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsFinite());
140 EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsFinite());
141
142 EXPECT_TRUE(Matrix::MakeScale({0, 1, 1}).IsFinite());
143 EXPECT_TRUE(Matrix::MakeScale({1, 0, 1}).IsFinite());
144 EXPECT_TRUE(Matrix::MakeScale({1, 1, 0}).IsFinite());
145
146 for (int i = 0; i < 16; i++) {
147 {
148 Matrix matrix;
149 ASSERT_TRUE(matrix.IsFinite());
150 matrix.m[i] = std::numeric_limits<Scalar>::infinity();
151 ASSERT_FALSE(matrix.IsFinite());
152 }
153
154 {
155 Matrix matrix;
156 ASSERT_TRUE(matrix.IsFinite());
157 matrix.m[i] = -std::numeric_limits<Scalar>::infinity();
158 ASSERT_FALSE(matrix.IsFinite());
159 }
160
161 {
162 Matrix matrix;
163 ASSERT_TRUE(matrix.IsFinite());
164 matrix.m[i] = -std::numeric_limits<Scalar>::quiet_NaN();
165 ASSERT_FALSE(matrix.IsFinite());
166 }
167 }
168 }

References impeller::Matrix::IsFinite(), impeller::Matrix::m, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [259/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsInvertibleGetDeterminant |
| ) |  |

Definition at line 105 of file matrix_unittests.cc.

105 {
106 EXPECT_TRUE(Matrix().IsInvertible());
107 EXPECT_NE(Matrix().GetDeterminant(), 0.0f);
108
109 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsInvertible());
110 EXPECT_NE(Matrix::MakeTranslation({100, 100, 0}).GetDeterminant(), 0.0f);
111
112 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsInvertible());
113 EXPECT_NE(Matrix::MakeScale({100, 100, 1}).GetDeterminant(), 0.0f);
114
115 EXPECT_TRUE(Matrix::MakeRotationX(Degrees(30)).IsInvertible());
116 EXPECT_NE(Matrix::MakeRotationX(Degrees(30)).GetDeterminant(), 0.0f);
117
118 EXPECT_TRUE(Matrix::MakeRotationY(Degrees(30)).IsInvertible());
119 EXPECT_NE(Matrix::MakeRotationY(Degrees(30)).GetDeterminant(), 0.0f);
120
121 EXPECT_TRUE(Matrix::MakeRotationZ(Degrees(30)).IsInvertible());
122 EXPECT_NE(Matrix::MakeRotationZ(Degrees(30)).GetDeterminant(), 0.0f);
123
124 EXPECT_FALSE(Matrix::MakeScale({0, 1, 1}).IsInvertible());
125 EXPECT_EQ(Matrix::MakeScale({0, 1, 1}).GetDeterminant(), 0.0f);
126 EXPECT_FALSE(Matrix::MakeScale({1, 0, 1}).IsInvertible());
127 EXPECT_EQ(Matrix::MakeScale({1, 0, 1}).GetDeterminant(), 0.0f);
128 EXPECT_FALSE(Matrix::MakeScale({1, 1, 0}).IsInvertible());
129 EXPECT_EQ(Matrix::MakeScale({1, 1, 0}).GetDeterminant(), 0.0f);
130 }

References impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [260/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsTranslationOnly |
| ) |  |

Definition at line 83 of file matrix_unittests.cc.

83 {
84 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationOnly());
85 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).IsTranslationScaleOnly());
86 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationOnly());
87 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).IsTranslationScaleOnly());
88 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationOnly());
89 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).IsTranslationScaleOnly());
90 EXPECT_TRUE(Matrix().IsTranslationOnly());
91 EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
92 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [261/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsTranslationScaleOnly |
| ) |  |

Definition at line 94 of file matrix_unittests.cc.

94 {
95 EXPECT_FALSE(Matrix::MakeScale({100, 100, 1}).IsTranslationOnly());
96 EXPECT_TRUE(Matrix::MakeScale({100, 100, 1}).IsTranslationScaleOnly());
97 EXPECT_FALSE(Matrix::MakeScale({1, 100, 1}).IsTranslationOnly());
98 EXPECT_TRUE(Matrix::MakeScale({1, 100, 1}).IsTranslationScaleOnly());
99 EXPECT_FALSE(Matrix::MakeScale({100, 1, 1}).IsTranslationOnly());
100 EXPECT_TRUE(Matrix::MakeScale({100, 1, 1}).IsTranslationScaleOnly());
101 EXPECT_TRUE(Matrix().IsTranslationOnly());
102 EXPECT_TRUE(Matrix().IsTranslationScaleOnly());
103 }

References impeller::Matrix::MakeScale().

## ◆ TEST() [262/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | MakeScaleTranslate |
| ) |  |

Definition at line 301 of file matrix_unittests.cc.

301 {
302 EXPECT_TRUE(MatrixNear(
303 Matrix::MakeTranslateScale({1, 1, 1.0 / 1024}, {10, 10, 1.0 / 1024}),
304 Matrix::MakeTranslation({10, 10, 1.0 / 1024}) *
305 Matrix::MakeScale({1, 1, 1.0 / 1024})));
306
307 EXPECT_TRUE(MatrixNear(
308 Matrix::MakeTranslateScale({2, 2, 2}, {10, 10, 0}),
309 Matrix::MakeTranslation({10, 10, 0}) * Matrix::MakeScale({2, 2, 2})));
310
311 EXPECT_TRUE(MatrixNear(
312 Matrix::MakeTranslateScale({0, 0, 0}, {0, 0, 0}),
313 Matrix::MakeTranslation({0, 0, 0}) * Matrix::MakeScale({0, 0, 0})));
314 }
MatrixNear
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
Definition: geometry_asserts.h:56

References impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslateScale(), impeller::Matrix::MakeTranslation(), and MatrixNear().

## ◆ TEST() [263/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | MinMaxScales2D |
| ) |  |

Definition at line 325 of file matrix_unittests.cc.

325 {
326 // The GetScales2D() method is allowed to return the scales in any
327 // order so we need to take special care in verifying the return
328 // value to test them in either order.
329 auto check_pair = [](const Matrix& matrix, Scalar scale1, Scalar scale2) {
330 auto pair = matrix.GetScales2D();
331 EXPECT_TRUE(pair.has_value())
332 << "Scales: " << scale1 << ", " << scale2 << ", " << matrix;
333 if (ScalarNearlyEqual(pair->first, scale1)) {
334 EXPECT_FLOAT_EQ(pair->first, scale1) << matrix;
335 EXPECT_FLOAT_EQ(pair->second, scale2) << matrix;
336 } else {
337 EXPECT_FLOAT_EQ(pair->first, scale2) << matrix;
338 EXPECT_FLOAT_EQ(pair->second, scale1) << matrix;
339 }
340 };
341
342 for (int i = 1; i < 10; i++) {
343 Scalar xScale = static_cast<Scalar>(i);
344 for (int j = 1; j < 10; j++) {
345 Scalar yScale = static_cast<Scalar>(j);
346 Scalar minScale = std::min(xScale, yScale);
347 Scalar maxScale = std::max(xScale, yScale);
348
349 {
350 // Simple scale
351 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
352 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
353 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
354 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
355 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
356 check_pair(matrix, xScale, yScale);
357 }
358
359 {
360 // Simple scale with Z scale
361 Matrix matrix = Matrix::MakeScale({xScale, yScale, 5.0f});
362 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
363 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
364 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
365 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
366 check_pair(matrix, xScale, yScale);
367 }
368
369 {
370 // Simple scale + translate
371 Matrix matrix = Matrix::MakeTranslateScale({xScale, yScale, 1.0f},
372 {10.0f, 15.0f, 2.0f});
373 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
374 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
375 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
376 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
377 check_pair(matrix, xScale, yScale);
378 }
379
380 for (int d = 45; d < 360; d += 45) {
381 {
382 // Rotation * Scale
383 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f}) *
384 Matrix::MakeRotationZ(Degrees(d));
385 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
386 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
387 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
388 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
389 check_pair(matrix, xScale, yScale);
390 }
391
392 {
393 // Scale * Rotation
394 Matrix matrix = Matrix::MakeRotationZ(Degrees(d)) *
395 Matrix::MakeScale({xScale, yScale, 1.0f});
396 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
397 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
398 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
399 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
400 check_pair(matrix, xScale, yScale);
401 }
402 }
403
404 {
405 // Scale + PerspectiveX (returns invalid values)
406 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
407 matrix.m[3] = 0.1;
408 EXPECT_FALSE(matrix.GetMinScale2D().has_value());
409 EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
410 EXPECT_FALSE(matrix.GetScales2D().has_value());
411 }
412
413 {
414 // Scale + PerspectiveY (returns invalid values)
415 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
416 matrix.m[7] = 0.1;
417 EXPECT_FALSE(matrix.GetMinScale2D().has_value());
418 EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
419 EXPECT_FALSE(matrix.GetScales2D().has_value());
420 }
421
422 {
423 // Scale + PerspectiveZ (Z ignored; returns actual scales)
424 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
425 matrix.m[11] = 0.1;
426 EXPECT_TRUE(matrix.GetMinScale2D().has_value());
427 EXPECT_TRUE(matrix.GetMaxScale2D().has_value());
428 EXPECT_FLOAT_EQ(matrix.GetMinScale2D().value_or(-1.0f), minScale);
429 EXPECT_FLOAT_EQ(matrix.GetMaxScale2D().value_or(-1.0f), maxScale);
430 check_pair(matrix, xScale, yScale);
431 }
432
433 {
434 // Scale + PerspectiveW (returns invalid values)
435 Matrix matrix = Matrix::MakeScale({xScale, yScale, 1.0f});
436 matrix.m[15] = 0.1;
437 EXPECT_FALSE(matrix.GetMinScale2D().has_value());
438 EXPECT_FALSE(matrix.GetMaxScale2D().has_value());
439 EXPECT_FALSE(matrix.GetScales2D().has_value());
440 }
441 }
442 }
443 }

References impeller::Matrix::GetMaxScale2D(), impeller::Matrix::GetMinScale2D(), impeller::Matrix::GetScales2D(), impeller::Matrix::m, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslateScale(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [264/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | Multiply |
| ) |  |

Definition at line 15 of file matrix_unittests.cc.

15 {
16 Matrix x(0.0, 0.0, 0.0, 1.0, //
17 1.0, 0.0, 0.0, 1.0, //
18 0.0, 1.0, 0.0, 1.0, //
19 1.0, 1.0, 0.0, 1.0);
20 Matrix translate = Matrix::MakeTranslation({10, 20, 0});
21 Matrix result = translate * x;
22 EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
23 11.0, 20.0, 0.0, 1.0, //
24 10.0, 21.0, 0.0, 1.0, //
25 11.0, 21.0, 0.0, 1.0)));
26 }

References impeller::Matrix::MakeTranslation(), MatrixNear(), and x.

## ◆ TEST() [265/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | NotEquals |
| ) |  |

Definition at line 34 of file matrix_unittests.cc.

34 {
35 Matrix x;
36 Matrix y = x.Translate({1, 0, 0});
37 EXPECT_FALSE(x.Equals(y));
38 }

References x.

## ◆ TEST() [266/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | To3x3 |
| ) |  |

Definition at line 316 of file matrix_unittests.cc.

316 {
317 Matrix x(1.0, 0.0, 4.0, 0.0, //
318 0.0, 1.0, 4.0, 0.0, //
319 6.0, 5.0, 111.0, 7.0, //
320 0.0, 0.0, 9.0, 1.0);
321
322 EXPECT_TRUE(MatrixNear(x.To3x3(), Matrix()));
323 }

References MatrixNear(), and x.

## ◆ TEST() [267/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | TransformHomogenous |
| ) |  |

Definition at line 250 of file matrix_unittests.cc.

250 {
251 Matrix matrix = Matrix::MakeColumn(
252 // clang-format off
253 2.0f, 3.0f, 5.0f, 7.0f,
254 11.0f, 13.0f, 17.0f, 19.0f,
255 23.0f, 29.0f, 31.0f, 37.0f,
256 41.0f, 43.0f, 47.0f, 53.0f
257 // clang-format on
258 );
259 EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
260 Vector3(32.0f, 33.0f, 41.0f));
261 }

References impeller::Matrix::MakeColumn(), and impeller::Matrix::TransformHomogenous().

## ◆ TEST() [268/574]

impeller::testing::TEST | ( | MatrixTest | ,
|  | TranslateWithPerspective |
| ) |  |

Definition at line 289 of file matrix_unittests.cc.

289 {
290 Matrix m = Matrix::MakeRow(1.0, 0.0, 0.0, 10.0, //
291 0.0, 1.0, 0.0, 20.0, //
292 0.0, 0.0, 1.0, 0.0, //
293 0.0, 2.0, 0.0, 30.0);
294 Matrix result = m.Translate({100, 200});
295 EXPECT_TRUE(MatrixNear(result, Matrix::MakeRow(1.0, 0.0, 0.0, 110.0, //
296 0.0, 1.0, 0.0, 220.0, //
297 0.0, 0.0, 1.0, 0.0, //
298 0.0, 2.0, 0.0, 430.0)));
299 }

References impeller::Matrix::MakeRow(), MatrixNear(), and impeller::Matrix::Translate().

## ◆ TEST() [269/574]

impeller::testing::TEST | ( | MockPipelineLibrary | ,
|  | LogAndGetPipelineUsageMultiplePipelines |
| ) |  |

Definition at line 28 of file pipeline_library_unittests.cc.

28 {
29 MockPipelineLibrary pipeline_library;
30
31 PipelineDescriptor pipeline_a;
32 pipeline_a.SetLabel("pipeline_a");
33
34 PipelineDescriptor pipeline_b;
35 pipeline_b.SetLabel("pipeline_b");
36
37 pipeline_library.LogPipelineUsage(pipeline_a);
38 pipeline_library.LogPipelineUsage(pipeline_a);
39 pipeline_library.LogPipelineUsage(pipeline_b);
40
41 auto usage_counts = pipeline_library.GetPipelineUseCounts();
42
43 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
44 FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
45 EXPECT_EQ(usage_counts[pipeline_a], 2);
46 EXPECT_EQ(usage_counts[pipeline_b], 1);
47 #else
48 EXPECT_EQ(usage_counts[pipeline_a], 0);
49 EXPECT_EQ(usage_counts[pipeline_b], 0);
50 #endif
51 }

References impeller::PipelineDescriptor::SetLabel().

## ◆ TEST() [270/574]

impeller::testing::TEST | ( | MockPipelineLibrary | ,
|  | LogAndGetPipelineUsageSinglePipeline |
| ) |  |

Definition at line 10 of file pipeline_library_unittests.cc.

10 {
11 MockPipelineLibrary pipeline_library;
12
13 PipelineDescriptor pipeline_desc;
14 pipeline_desc.SetLabel("pipeline");
15
16 pipeline_library.LogPipelineUsage(pipeline_desc);
17 pipeline_library.LogPipelineUsage(pipeline_desc);
18
19 auto usage_counts = pipeline_library.GetPipelineUseCounts();
20 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
21 FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
22 EXPECT_EQ(usage_counts[pipeline_desc], 2);
23 #else
24 EXPECT_EQ(usage_counts[pipeline_desc], 0);
25 #endif
26 }

References impeller::PipelineDescriptor::SetLabel().

## ◆ TEST() [271/574]

impeller::testing::TEST | ( | PaintTest | ,
|  | GradientConversionNonMonotonic |
| ) |  |

Definition at line 121 of file paint_unittests.cc.

121 {
122 std::vector<flutter::DlColor> colors = {
123 flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
124 flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
125 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
126 const auto gradient =
127 flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
128 flutter::DlPoint(1.0, 1.0), //
129 4, //
130 colors.data(), //
131 stops.data(), //
132 flutter::DlTileMode::kClamp, //
133 nullptr //
134 );
135
136 std::vector<Color> converted_colors;
137 std::vector<Scalar> converted_stops;
138 Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
139 converted_stops);
140
141 // Value is clamped to 0.5
142 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
143 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
144 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
145 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
146 }

References impeller::Paint::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [272/574]

impeller::testing::TEST | ( | PaintTest | ,
|  | GradientMissing0 |
| ) |  |

Definition at line 43 of file paint_unittests.cc.

43 {
44 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
45 flutter::DlColor::kRed()};
46 std::vector<float> stops = {0.5, 1.0};
47 const auto gradient =
48 flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
49 flutter::DlPoint(1.0, 1.0), //
50 2, //
51 colors.data(), //
52 stops.data(), //
53 flutter::DlTileMode::kClamp, //
54 nullptr //
55 );
56
57 std::vector<Color> converted_colors;
58 std::vector<Scalar> converted_stops;
59 Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
60 converted_stops);
61
62 // First color is inserted as blue.
63 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
64 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
65 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
66 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
67 }

References impeller::Paint::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [273/574]

impeller::testing::TEST | ( | PaintTest | ,
|  | GradientMissingLastValue |
| ) |  |

Definition at line 69 of file paint_unittests.cc.

69 {
70 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
71 flutter::DlColor::kRed()};
72 std::vector<float> stops = {0.0, .5};
73 const auto gradient =
74 flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
75 flutter::DlPoint(1.0, 1.0), //
76 2, //
77 colors.data(), //
78 stops.data(), //
79 flutter::DlTileMode::kClamp, //
80 nullptr //
81 );
82
83 std::vector<Color> converted_colors;
84 std::vector<Scalar> converted_stops;
85 Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
86 converted_stops);
87
88 // Last color is inserted as red.
89 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
90 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
91 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
92 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
93 }

References impeller::Paint::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [274/574]

impeller::testing::TEST | ( | PaintTest | ,
|  | GradientStopConversion |
| ) |  |

Definition at line 17 of file paint_unittests.cc.

17 {
18 // Typical gradient.
19 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
20 flutter::DlColor::kRed(),
21 flutter::DlColor::kGreen()};
22 std::vector<float> stops = {0.0, 0.5, 1.0};
23 const auto gradient =
24 flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
25 flutter::DlPoint(1.0, 1.0), //
26 3, //
27 colors.data(), //
28 stops.data(), //
29 flutter::DlTileMode::kClamp, //
30 nullptr //
31 );
32
33 std::vector<Color> converted_colors;
34 std::vector<Scalar> converted_stops;
35 Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
36 converted_stops);
37
38 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
39 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
40 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
41 }

References impeller::Paint::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [275/574]

impeller::testing::TEST | ( | PaintTest | ,
|  | GradientStopGreaterThan1 |
| ) |  |

Definition at line 95 of file paint_unittests.cc.

95 {
96 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
97 flutter::DlColor::kGreen(),
98 flutter::DlColor::kRed()};
99 std::vector<float> stops = {0.0, 100, 1.0};
100 const auto gradient =
101 flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
102 flutter::DlPoint(1.0, 1.0), //
103 3, //
104 colors.data(), //
105 stops.data(), //
106 flutter::DlTileMode::kClamp, //
107 nullptr //
108 );
109
110 std::vector<Color> converted_colors;
111 std::vector<Scalar> converted_stops;
112 Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
113 converted_stops);
114
115 // Value is clamped to 1.0
116 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
117 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
118 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
119 }

References impeller::Paint::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [276/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSource |
| ) |  |

Definition at line 158 of file path_source_unittests.cc.

158 {
159 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 5);
160
161 EXPECT_FALSE(source.IsConvex());
162 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
163 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
164
165 ::testing::StrictMock<DlPathReceiverMock> receiver;
166
167 {
168 ::testing::Sequence sequence;
169
170 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
171 EXPECT_CALL(receiver, LineTo(Point(15, 10)));
172 EXPECT_CALL(receiver, MoveTo(Point(20, 10), false));
173 EXPECT_CALL(receiver, LineTo(Point(25, 10)));
174 }
175
176 source.Dispatch(receiver);
177 }
impeller::MoveTo
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:20
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24

References impeller::DashedLinePathSource::Dispatch(), impeller::DashedLinePathSource::GetBounds(), impeller::DashedLinePathSource::GetFillType(), impeller::DashedLinePathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [277/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceInvalidOffGaps |
| ) |  |

Definition at line 217 of file path_source_unittests.cc.

217 {
218 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, -1);
219
220 EXPECT_FALSE(source.IsConvex());
221 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
222 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
223
224 ::testing::StrictMock<DlPathReceiverMock> receiver;
225
226 {
227 ::testing::Sequence sequence;
228
229 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
230 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
231 }
232
233 source.Dispatch(receiver);
234 }

References impeller::DashedLinePathSource::Dispatch(), impeller::DashedLinePathSource::GetBounds(), impeller::DashedLinePathSource::GetFillType(), impeller::DashedLinePathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [278/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceInvalidOnRegion |
| ) |  |

Definition at line 236 of file path_source_unittests.cc.

236 {
237 DashedLinePathSource source(Point(10, 10), Point(30, 10), -1, 5);
238
239 EXPECT_FALSE(source.IsConvex());
240 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
241 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
242
243 ::testing::StrictMock<DlPathReceiverMock> receiver;
244
245 {
246 ::testing::Sequence sequence;
247
248 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
249 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
250 }
251
252 source.Dispatch(receiver);
253 }

References impeller::DashedLinePathSource::Dispatch(), impeller::DashedLinePathSource::GetBounds(), impeller::DashedLinePathSource::GetFillType(), impeller::DashedLinePathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [279/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceZeroOffGaps |
| ) |  |

Definition at line 198 of file path_source_unittests.cc.

198 {
199 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 0);
200
201 EXPECT_FALSE(source.IsConvex());
202 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
203 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
204
205 ::testing::StrictMock<DlPathReceiverMock> receiver;
206
207 {
208 ::testing::Sequence sequence;
209
210 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
211 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
212 }
213
214 source.Dispatch(receiver);
215 }

References impeller::DashedLinePathSource::Dispatch(), impeller::DashedLinePathSource::GetBounds(), impeller::DashedLinePathSource::GetFillType(), impeller::DashedLinePathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [280/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DiffRoundRectSourceTest |
| ) |  |

Definition at line 105 of file path_source_unittests.cc.

105 {
106 Rect outer_rect = Rect::MakeLTRB(10, 15, 200, 300);
107 Rect inner_rect = Rect::MakeLTRB(50, 60, 100, 200);
108 ASSERT_TRUE(outer_rect.Contains(inner_rect));
109 RoundingRadii radii = {
110 .top_left = Size(1, 11),
111 .top_right = Size(2, 12),
112 .bottom_left = Size(4, 14),
113 .bottom_right = Size(3, 13),
114 };
115 RoundRect outer_rrect = RoundRect::MakeRectRadii(outer_rect, radii);
116 RoundRect inner_rrect = RoundRect::MakeRectRadii(inner_rect, radii);
117 DiffRoundRectPathSource source(outer_rrect, inner_rrect);
118
119 EXPECT_FALSE(source.IsConvex());
120 EXPECT_EQ(source.GetFillType(), FillType::kOdd);
121 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 200, 300));
122
123 ::testing::StrictMock<DlPathReceiverMock> receiver;
124
125 {
126 ::testing::Sequence sequence;
127
128 EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
129 EXPECT_CALL(receiver, LineTo(Point(198, 15)));
130 EXPECT_CALL(receiver, ConicTo(Point(200, 15), Point(200, 27), kSqrt2Over2));
131 EXPECT_CALL(receiver, LineTo(Point(200, 287)));
132 EXPECT_CALL(receiver,
133 ConicTo(Point(200, 300), Point(197, 300), kSqrt2Over2));
134 EXPECT_CALL(receiver, LineTo(Point(14, 300)));
135 EXPECT_CALL(receiver, ConicTo(Point(10, 300), Point(10, 286), kSqrt2Over2));
136 EXPECT_CALL(receiver, LineTo(Point(10, 26)));
137 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
138 // RetiresOnSaturation keeps identical calls from matching each other
139 EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
140
141 EXPECT_CALL(receiver, MoveTo(Point(51, 60), true));
142 EXPECT_CALL(receiver, LineTo(Point(98, 60)));
143 EXPECT_CALL(receiver, ConicTo(Point(100, 60), Point(100, 72), kSqrt2Over2));
144 EXPECT_CALL(receiver, LineTo(Point(100, 187)));
145 EXPECT_CALL(receiver,
146 ConicTo(Point(100, 200), Point(97, 200), kSqrt2Over2));
147 EXPECT_CALL(receiver, LineTo(Point(54, 200)));
148 EXPECT_CALL(receiver, ConicTo(Point(50, 200), Point(50, 186), kSqrt2Over2));
149 EXPECT_CALL(receiver, LineTo(Point(50, 71)));
150 EXPECT_CALL(receiver, ConicTo(Point(50, 60), Point(51, 60), kSqrt2Over2));
151 // RetiresOnSaturation keeps identical calls from matching each other
152 EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
153 }
154
155 source.Dispatch(receiver);
156 }
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:38

References impeller::Close(), impeller::TRect< T >::Contains(), impeller::DiffRoundRectPathSource::Dispatch(), impeller::DiffRoundRectPathSource::GetBounds(), impeller::DiffRoundRectPathSource::GetFillType(), impeller::DiffRoundRectPathSource::IsConvex(), impeller::kOdd, impeller::kSqrt2Over2, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::MoveTo(), and impeller::RoundingRadii::top_left.

## ◆ TEST() [281/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | EllipseSourceTest |
| ) |  |

Definition at line 46 of file path_source_unittests.cc.

46 {
47 Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
48 EllipsePathSource source(rect);
49
50 EXPECT_TRUE(source.IsConvex());
51 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
52 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
53
54 ::testing::StrictMock<DlPathReceiverMock> receiver;
55
56 {
57 ::testing::Sequence sequence;
58
59 EXPECT_CALL(receiver, MoveTo(Point(10, 22.5), true));
60 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(15, 15), kSqrt2Over2));
61 EXPECT_CALL(receiver, ConicTo(Point(20, 15), Point(20, 22.5), kSqrt2Over2));
62 EXPECT_CALL(receiver, ConicTo(Point(20, 30), Point(15, 30), kSqrt2Over2));
63 EXPECT_CALL(receiver, ConicTo(Point(10, 30), Point(10, 22.5), kSqrt2Over2));
64 EXPECT_CALL(receiver, Close());
65 }
66
67 source.Dispatch(receiver);
68 }

References impeller::Close(), impeller::EllipsePathSource::Dispatch(), impeller::EllipsePathSource::GetBounds(), impeller::EllipsePathSource::GetFillType(), impeller::EllipsePathSource::IsConvex(), impeller::kNonZero, impeller::kSqrt2Over2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [282/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | EmptyDashedLinePathSource |
| ) |  |

Definition at line 179 of file path_source_unittests.cc.

179 {
180 DashedLinePathSource source(Point(10, 10), Point(10, 10), 5, 5);
181
182 EXPECT_FALSE(source.IsConvex());
183 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
184 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 10, 10));
185
186 ::testing::StrictMock<DlPathReceiverMock> receiver;
187
188 {
189 ::testing::Sequence sequence;
190
191 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
192 EXPECT_CALL(receiver, LineTo(Point(10, 10)));
193 }
194
195 source.Dispatch(receiver);
196 }

References impeller::DashedLinePathSource::Dispatch(), impeller::DashedLinePathSource::GetBounds(), impeller::DashedLinePathSource::GetFillType(), impeller::DashedLinePathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [283/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | PathTransformerAllSegmentsTest |
| ) |  |

Definition at line 282 of file path_source_unittests.cc.

282 {
283 Matrix matrix =
284 Matrix::MakeTranslateScale({2.0f, 3.0f, 1.0f}, {1.5f, 4.25f, 0.0f});
285
286 ::testing::StrictMock<DlPathReceiverMock> mock_receiver;
287 PathTransformer receiver = PathTransformer(mock_receiver, matrix);
288
289 {
290 ::testing::Sequence sequence;
291
292 EXPECT_CALL(mock_receiver, MoveTo(Point(21.5f, 49.25f), false));
293 EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 49.25f)));
294
295 EXPECT_CALL(mock_receiver, MoveTo(Point(221.5f, 349.25f), true));
296 EXPECT_CALL(mock_receiver,
297 QuadTo(Point(241.5f, 349.25f), Point(241.5f, 394.25f)));
298 EXPECT_CALL(mock_receiver,
299 ConicTo(Point(237.5f, 409.25f), Point(231.5f, 409.25f), 5))
300 .WillOnce(Return(true));
301 EXPECT_CALL(mock_receiver,
302 ConicTo(Point(225.5f, 409.25f), Point(221.5f, 394.25f), 6))
303 .WillOnce(Return(false));
304 EXPECT_CALL(mock_receiver,
305 CubicTo(Point(211.5f, 379.25f), Point(211.5f, 364.25f),
306 Point(221.5f, 349.25f)));
307 EXPECT_CALL(mock_receiver, Close());
308 }
309
310 receiver.MoveTo(Point(10, 15), false);
311 receiver.LineTo(Point(20, 15));
312
313 receiver.MoveTo(Point(110, 115), true);
314 receiver.QuadTo(Point(120, 115), Point(120, 130));
315 EXPECT_TRUE(receiver.ConicTo(Point(118, 135), Point(115, 135), 5));
316 EXPECT_FALSE(receiver.ConicTo(Point(112, 135), Point(110, 130), 6));
317 receiver.CubicTo(Point(105, 125), Point(105, 120), Point(110, 115));
318 receiver.Close();
319 }
impeller::CubicTo
void CubicTo(PathBuilder *builder, Scalar x1, Scalar y1, Scalar x2, Scalar y2, Scalar x3, Scalar y3)
Definition: tessellator.cc:28

References impeller::PathTransformer::Close(), impeller::Close(), impeller::PathTransformer::ConicTo(), impeller::PathTransformer::CubicTo(), impeller::CubicTo(), impeller::PathTransformer::LineTo(), impeller::LineTo(), impeller::Matrix::MakeTranslateScale(), impeller::PathTransformer::MoveTo(), impeller::MoveTo(), and impeller::PathTransformer::QuadTo().

## ◆ TEST() [284/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | PathTransformerRectSourceTest |
| ) |  |

Definition at line 255 of file path_source_unittests.cc.

255 {
256 Matrix matrix =
257 Matrix::MakeTranslateScale({2.0f, 3.0f, 1.0f}, {1.5f, 4.25f, 0.0f});
258 Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
259 RectPathSource source(rect);
260
261 EXPECT_TRUE(source.IsConvex());
262 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
263 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
264
265 ::testing::StrictMock<DlPathReceiverMock> mock_receiver;
266 PathTransformer receiver = PathTransformer(mock_receiver, matrix);
267
268 {
269 ::testing::Sequence sequence;
270
271 EXPECT_CALL(mock_receiver, MoveTo(Point(21.5f, 49.25f), true));
272 EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 49.25f)));
273 EXPECT_CALL(mock_receiver, LineTo(Point(41.5f, 94.25f)));
274 EXPECT_CALL(mock_receiver, LineTo(Point(21.5f, 94.25f)));
275 EXPECT_CALL(mock_receiver, LineTo(Point(21.5f, 49.25f)));
276 EXPECT_CALL(mock_receiver, Close());
277 }
278
279 source.Dispatch(receiver);
280 }

References impeller::Close(), impeller::RectPathSource::Dispatch(), impeller::RectPathSource::GetBounds(), impeller::RectPathSource::GetFillType(), impeller::RectPathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslateScale(), and impeller::MoveTo().

## ◆ TEST() [285/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | RectSourceTest |
| ) |  |

Definition at line 22 of file path_source_unittests.cc.

22 {
23 Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
24 RectPathSource source(rect);
25
26 EXPECT_TRUE(source.IsConvex());
27 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
28 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
29
30 ::testing::StrictMock<DlPathReceiverMock> receiver;
31
32 {
33 ::testing::Sequence sequence;
34
35 EXPECT_CALL(receiver, MoveTo(Point(10, 15), true));
36 EXPECT_CALL(receiver, LineTo(Point(20, 15)));
37 EXPECT_CALL(receiver, LineTo(Point(20, 30)));
38 EXPECT_CALL(receiver, LineTo(Point(10, 30)));
39 EXPECT_CALL(receiver, LineTo(Point(10, 15)));
40 EXPECT_CALL(receiver, Close());
41 }
42
43 source.Dispatch(receiver);
44 }

References impeller::Close(), impeller::RectPathSource::Dispatch(), impeller::RectPathSource::GetBounds(), impeller::RectPathSource::GetFillType(), impeller::RectPathSource::IsConvex(), impeller::kNonZero, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::MoveTo().

## ◆ TEST() [286/574]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | RoundRectSourceTest |
| ) |  |

Definition at line 70 of file path_source_unittests.cc.

70 {
71 Rect rect = Rect::MakeLTRB(10, 15, 40, 60);
72 RoundingRadii radii = {
73 .top_left = Size(1, 11),
74 .top_right = Size(2, 12),
75 .bottom_left = Size(4, 14),
76 .bottom_right = Size(3, 13),
77 };
78 RoundRect round_rect = RoundRect::MakeRectRadii(rect, radii);
79 RoundRectPathSource source(round_rect);
80
81 EXPECT_TRUE(source.IsConvex());
82 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
83 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 40, 60));
84
85 ::testing::StrictMock<DlPathReceiverMock> receiver;
86
87 {
88 ::testing::Sequence sequence;
89
90 EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
91 EXPECT_CALL(receiver, LineTo(Point(38, 15)));
92 EXPECT_CALL(receiver, ConicTo(Point(40, 15), Point(40, 27), kSqrt2Over2));
93 EXPECT_CALL(receiver, LineTo(Point(40, 47)));
94 EXPECT_CALL(receiver, ConicTo(Point(40, 60), Point(37, 60), kSqrt2Over2));
95 EXPECT_CALL(receiver, LineTo(Point(14, 60)));
96 EXPECT_CALL(receiver, ConicTo(Point(10, 60), Point(10, 46), kSqrt2Over2));
97 EXPECT_CALL(receiver, LineTo(Point(10, 26)));
98 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
99 EXPECT_CALL(receiver, Close());
100 }
101
102 source.Dispatch(receiver);
103 }

References impeller::Close(), impeller::RoundRectPathSource::Dispatch(), impeller::RoundRectPathSource::GetBounds(), impeller::RoundRectPathSource::GetFillType(), impeller::RoundRectPathSource::IsConvex(), impeller::kNonZero, impeller::kSqrt2Over2, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::MoveTo(), and impeller::RoundingRadii::top_left.

## ◆ TEST() [287/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | ComplexPath |
| ) |  |

Definition at line 396 of file path_tessellator_unittests.cc.

396 {
397 PathTessellator::Quad quad{{10, 10}, {20, 20}, {20, 10}};
398 PathTessellator::Conic conic{{20, 10}, {30, 20}, {30, 10}, 2.0f};
399 PathTessellator::Cubic cubic{{30, 10}, {40, 20}, {40, 10}, {42, 15}};
400
401 flutter::DlPathBuilder builder;
402 builder.MoveTo({0, 0});
403 builder.LineTo({10, 10});
404 builder.QuadraticCurveTo(quad.cp, quad.p2);
405 builder.ConicCurveTo(conic.cp, conic.p2, conic.weight);
406 builder.CubicCurveTo(cubic.cp1, cubic.cp2, cubic.p2);
407 builder.Close();
408 flutter::DlPath path = builder.TakePath();
409
410 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
411 {
412 ::testing::InSequence sequence;
413
414 EXPECT_CALL(mock_receiver,
415 BeginContour(Point(0, 0), /*will_be_closed=*/true));
416 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
417 EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
418 EXPECT_CALL(mock_receiver,
419 RecordConic(conic.p1, conic.cp, conic.p2, conic.weight));
420 EXPECT_CALL(mock_receiver,
421 RecordCubic(cubic.p1, cubic.cp1, cubic.cp2, cubic.p2));
422 EXPECT_CALL(mock_receiver, RecordLine(cubic.p2, Point(0, 0)));
423 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
424 }
425 PathTessellator::PathToFilledSegments(path, mock_receiver);
426
427 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
428 EXPECT_EQ(points, 25u);
429 EXPECT_EQ(contours, 1u);
430
431 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
432 {
433 ::testing::InSequence sequence;
434
435 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
436 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
437 {
438 EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
439 EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
440 EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
441 EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
442 EXPECT_CALL(mock_writer, Write(quad.p2));
443 }
444 {
445 EXPECT_CALL(mock_writer, Write(conic.Solve(1 / 8.0f)));
446 EXPECT_CALL(mock_writer, Write(conic.Solve(2 / 8.0f)));
447 EXPECT_CALL(mock_writer, Write(conic.Solve(3 / 8.0f)));
448 EXPECT_CALL(mock_writer, Write(conic.Solve(4 / 8.0f)));
449 EXPECT_CALL(mock_writer, Write(conic.Solve(5 / 8.0f)));
450 EXPECT_CALL(mock_writer, Write(conic.Solve(6 / 8.0f)));
451 EXPECT_CALL(mock_writer, Write(conic.Solve(7 / 8.0f)));
452 EXPECT_CALL(mock_writer, Write(conic.p2));
453 }
454 {
455 EXPECT_CALL(mock_writer, Write(cubic.Solve(1 / 9.0f)));
456 EXPECT_CALL(mock_writer, Write(cubic.Solve(2 / 9.0f)));
457 EXPECT_CALL(mock_writer, Write(cubic.Solve(3 / 9.0f)));
458 EXPECT_CALL(mock_writer, Write(cubic.Solve(4 / 9.0f)));
459 EXPECT_CALL(mock_writer, Write(cubic.Solve(5 / 9.0f)));
460 EXPECT_CALL(mock_writer, Write(cubic.Solve(6 / 9.0f)));
461 EXPECT_CALL(mock_writer, Write(cubic.Solve(7 / 9.0f)));
462 EXPECT_CALL(mock_writer, Write(cubic.Solve(8 / 9.0f)));
463 EXPECT_CALL(mock_writer, Write(cubic.p2));
464 }
465 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
466 EXPECT_CALL(mock_writer, EndContour());
467 }
468 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
469 }
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:430
contours
std::vector< Contour > contours
Definition: tessellator_libtess.cc:77

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [288/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | ComplexPathTrailingMoveTo |
| ) |  |

Definition at line 471 of file path_tessellator_unittests.cc.

471 {
472 PathTessellator::Quad quad{{10, 10}, {20, 20}, {20, 10}};
473 PathTessellator::Conic conic{{20, 10}, {30, 20}, {30, 10}, 2.0f};
474 PathTessellator::Cubic cubic{{30, 10}, {40, 20}, {40, 10}, {42, 15}};
475
476 flutter::DlPathBuilder builder;
477 builder.MoveTo({0, 0});
478 builder.LineTo({10, 10});
479 builder.QuadraticCurveTo(quad.cp, quad.p2);
480 builder.ConicCurveTo(conic.cp, conic.p2, conic.weight);
481 builder.CubicCurveTo(cubic.cp1, cubic.cp2, cubic.p2);
482 builder.Close();
483 builder.MoveTo({500, 100});
484 flutter::DlPath path = builder.TakePath();
485
486 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
487 {
488 ::testing::InSequence sequence;
489
490 EXPECT_CALL(mock_receiver,
491 BeginContour(Point(0, 0), /*will_be_closed=*/true));
492 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
493 EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
494 EXPECT_CALL(mock_receiver,
495 RecordConic(conic.p1, conic.cp, conic.p2, conic.weight));
496 EXPECT_CALL(mock_receiver,
497 RecordCubic(cubic.p1, cubic.cp1, cubic.cp2, cubic.p2));
498 EXPECT_CALL(mock_receiver, RecordLine(cubic.p2, Point(0, 0)));
499 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
500 }
501 PathTessellator::PathToFilledSegments(path, mock_receiver);
502
503 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
504 EXPECT_EQ(points, 25u);
505 EXPECT_EQ(contours, 1u);
506
507 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
508 {
509 ::testing::InSequence sequence;
510
511 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
512 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
513 {
514 EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
515 EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
516 EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
517 EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
518 EXPECT_CALL(mock_writer, Write(quad.p2));
519 }
520 {
521 EXPECT_CALL(mock_writer, Write(conic.Solve(1 / 8.0f)));
522 EXPECT_CALL(mock_writer, Write(conic.Solve(2 / 8.0f)));
523 EXPECT_CALL(mock_writer, Write(conic.Solve(3 / 8.0f)));
524 EXPECT_CALL(mock_writer, Write(conic.Solve(4 / 8.0f)));
525 EXPECT_CALL(mock_writer, Write(conic.Solve(5 / 8.0f)));
526 EXPECT_CALL(mock_writer, Write(conic.Solve(6 / 8.0f)));
527 EXPECT_CALL(mock_writer, Write(conic.Solve(7 / 8.0f)));
528 EXPECT_CALL(mock_writer, Write(conic.p2));
529 }
530 {
531 EXPECT_CALL(mock_writer, Write(cubic.Solve(1 / 9.0f)));
532 EXPECT_CALL(mock_writer, Write(cubic.Solve(2 / 9.0f)));
533 EXPECT_CALL(mock_writer, Write(cubic.Solve(3 / 9.0f)));
534 EXPECT_CALL(mock_writer, Write(cubic.Solve(4 / 9.0f)));
535 EXPECT_CALL(mock_writer, Write(cubic.Solve(5 / 9.0f)));
536 EXPECT_CALL(mock_writer, Write(cubic.Solve(6 / 9.0f)));
537 EXPECT_CALL(mock_writer, Write(cubic.Solve(7 / 9.0f)));
538 EXPECT_CALL(mock_writer, Write(cubic.Solve(8 / 9.0f)));
539 EXPECT_CALL(mock_writer, Write(cubic.p2));
540 }
541 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
542 EXPECT_CALL(mock_writer, EndContour());
543 }
544 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
545 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [289/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | ConicToLineToOptimization |
| ) |  |

Definition at line 269 of file path_tessellator_unittests.cc.

269 {
270 flutter::DlPathBuilder builder;
271 builder.MoveTo({0, 0});
272 // CP == P1
273 builder.ConicCurveTo({0, 0}, {10, 10}, 2.0f);
274 // CP == P2
275 builder.ConicCurveTo({20, 10}, {20, 10}, 2.0f);
276 // weight == 0
277 builder.ConicCurveTo({20, 0}, {10, 0}, 0.0f);
278 builder.Close();
279 flutter::DlPath path = builder.TakePath();
280
281 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
282 {
283 ::testing::InSequence sequence;
284
285 EXPECT_CALL(mock_receiver,
286 BeginContour(Point(0, 0), /*will_be_closed=*/true));
287 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
288 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(20, 10)));
289 EXPECT_CALL(mock_receiver, RecordLine(Point(20, 10), Point(10, 0)));
290 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 0), Point(0, 0)));
291 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
292 }
293 PathTessellator::PathToFilledSegments(path, mock_receiver);
294
295 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
296 EXPECT_EQ(points, 5u);
297 EXPECT_EQ(contours, 1u);
298
299 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
300 {
301 ::testing::InSequence sequence;
302
303 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
304 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
305 EXPECT_CALL(mock_writer, Write(Point(20, 10)));
306 EXPECT_CALL(mock_writer, Write(Point(10, 0)));
307 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
308 EXPECT_CALL(mock_writer, EndContour());
309 }
310 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
311 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [290/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | ConicToQuadToOptimization |
| ) |  |

Definition at line 313 of file path_tessellator_unittests.cc.

313 {
314 // The conic below will simplify to this quad
315 PathTessellator::Quad quad{{0, 0}, {10, 0}, {0, 10}};
316
317 flutter::DlPathBuilder builder;
318 builder.MoveTo(quad.p1);
319 // weight == 1
320 builder.ConicCurveTo(quad.cp, quad.p2, 1.0f);
321 builder.Close();
322 flutter::DlPath path = builder.TakePath();
323
324 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
325 {
326 ::testing::InSequence sequence;
327
328 EXPECT_CALL(mock_receiver, BeginContour(quad.p1, /*will_be_closed=*/true));
329 EXPECT_CALL(mock_receiver, RecordQuad(quad.p1, quad.cp, quad.p2));
330 EXPECT_CALL(mock_receiver, RecordLine(quad.p2, quad.p1));
331 EXPECT_CALL(mock_receiver, EndContour(quad.p1, /*with_close=*/true));
332 }
333 PathTessellator::PathToFilledSegments(path, mock_receiver);
334
335 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
336 EXPECT_EQ(points, 7u);
337 EXPECT_EQ(contours, 1u);
338
339 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
340 {
341 ::testing::InSequence sequence;
342
343 EXPECT_CALL(mock_writer, Write(quad.p1));
344 {
345 EXPECT_CALL(mock_writer, Write(quad.Solve(1 / 5.0f)));
346 EXPECT_CALL(mock_writer, Write(quad.Solve(2 / 5.0f)));
347 EXPECT_CALL(mock_writer, Write(quad.Solve(3 / 5.0f)));
348 EXPECT_CALL(mock_writer, Write(quad.Solve(4 / 5.0f)));
349 EXPECT_CALL(mock_writer, Write(quad.p2));
350 }
351 EXPECT_CALL(mock_writer, Write(quad.p1));
352 EXPECT_CALL(mock_writer, EndContour());
353 }
354 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
355 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [291/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | DegenerateSegmentsPath |
| ) |  |

Definition at line 191 of file path_tessellator_unittests.cc.

191 {
192 flutter::DlPathBuilder builder;
193 builder.MoveTo({0, 0});
194 builder.LineTo({0, 0});
195 builder.LineTo({0, 0});
196 builder.QuadraticCurveTo({0, 0}, {0, 0});
197 builder.QuadraticCurveTo({0, 0}, {0, 0});
198 builder.ConicCurveTo({0, 0}, {0, 0}, 12.0f);
199 builder.ConicCurveTo({0, 0}, {0, 0}, 12.0f);
200 builder.CubicCurveTo({0, 0}, {0, 0}, {0, 0});
201 builder.CubicCurveTo({0, 0}, {0, 0}, {0, 0});
202 builder.Close();
203 flutter::DlPath path = builder.TakePath();
204
205 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
206 {
207 ::testing::InSequence sequence;
208
209 EXPECT_CALL(mock_receiver,
210 BeginContour(Point(0, 0), /*will_be_closed=*/true));
211 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
212 }
213 PathTessellator::PathToFilledSegments(path, mock_receiver);
214
215 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
216 EXPECT_EQ(points, 1u);
217 EXPECT_EQ(contours, 1u);
218
219 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
220 {
221 ::testing::InSequence sequence;
222
223 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
224 EXPECT_CALL(mock_writer, EndContour());
225 }
226 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
227 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [292/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | EmptyPath |
| ) |  |

Definition at line 42 of file path_tessellator_unittests.cc.

42 {
43 flutter::DlPathBuilder builder;
44 builder.MoveTo({0, 0});
45 flutter::DlPath path = builder.TakePath();
46
47 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
48 PathTessellator::PathToFilledSegments(path, mock_receiver);
49
50 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
51 EXPECT_EQ(points, 0u);
52 EXPECT_EQ(contours, 0u);
53
54 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
55 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
56 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [293/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | EmptyPathMultipleMoveTo |
| ) |  |

Definition at line 58 of file path_tessellator_unittests.cc.

58 {
59 flutter::DlPathBuilder builder;
60 builder.MoveTo({0, 0});
61 builder.MoveTo({10, 10});
62 builder.MoveTo({20, 20});
63 flutter::DlPath path = builder.TakePath();
64
65 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
66 PathTessellator::PathToFilledSegments(path, mock_receiver);
67
68 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
69 EXPECT_EQ(points, 0u);
70 EXPECT_EQ(contours, 0u);
71
72 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
73 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
74 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [294/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | LinearConicToPointCount |
| ) |  |

Definition at line 559 of file path_tessellator_unittests.cc.

559 {
560 flutter::DlPathBuilder builder;
561 builder.MoveTo({316.3, 121.5});
562 builder.ConicCurveTo({316.4, 121.5}, {316.5, 121.5}, 2.0f);
563 builder.Close();
564 auto path = builder.TakePath();
565
566 auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
567 EXPECT_EQ(points, 3u);
568 EXPECT_EQ(contours, 1u);
569 }

References contours, impeller::PathTessellator::CountFillStorage(), and points.

## ◆ TEST() [295/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | LinearCubicToPointCount |
| ) |  |

Definition at line 571 of file path_tessellator_unittests.cc.

571 {
572 flutter::DlPathBuilder builder;
573 builder.MoveTo({316.3, 121.5});
574 builder.CubicCurveTo({316.4, 121.5}, {316.5, 121.5}, {316.6, 121.5});
575 builder.Close();
576 auto path = builder.TakePath();
577
578 auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
579 EXPECT_EQ(points, 3u);
580 EXPECT_EQ(contours, 1u);
581 }

References contours, impeller::PathTessellator::CountFillStorage(), and points.

## ◆ TEST() [296/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | LinearQuadToPointCount |
| ) |  |

Definition at line 547 of file path_tessellator_unittests.cc.

547 {
548 flutter::DlPathBuilder builder;
549 builder.MoveTo({316.3, 121.5});
550 builder.QuadraticCurveTo({316.4, 121.5}, {316.5, 121.5});
551 builder.Close();
552 auto path = builder.TakePath();
553
554 auto [points, contours] = PathTessellator::CountFillStorage(path, 2.0f);
555 EXPECT_EQ(points, 3u);
556 EXPECT_EQ(contours, 1u);
557 }

References contours, impeller::PathTessellator::CountFillStorage(), and points.

## ◆ TEST() [297/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | QuadToLineToOptimization |
| ) |  |

Definition at line 229 of file path_tessellator_unittests.cc.

229 {
230 flutter::DlPathBuilder builder;
231 builder.MoveTo({0, 0});
232 // CP == P1
233 builder.QuadraticCurveTo({0, 0}, {10, 10});
234 // CP == P2
235 builder.QuadraticCurveTo({20, 10}, {20, 10});
236 builder.Close();
237 flutter::DlPath path = builder.TakePath();
238
239 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
240 {
241 ::testing::InSequence sequence;
242
243 EXPECT_CALL(mock_receiver,
244 BeginContour(Point(0, 0), /*will_be_closed=*/true));
245 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
246 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(20, 10)));
247 EXPECT_CALL(mock_receiver, RecordLine(Point(20, 10), Point(0, 0)));
248 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
249 }
250 PathTessellator::PathToFilledSegments(path, mock_receiver);
251
252 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
253 EXPECT_EQ(points, 4u);
254 EXPECT_EQ(contours, 1u);
255
256 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
257 {
258 ::testing::InSequence sequence;
259
260 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
261 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
262 EXPECT_CALL(mock_writer, Write(Point(20, 10)));
263 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
264 EXPECT_CALL(mock_writer, EndContour());
265 }
266 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
267 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [298/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | SimpleClosedPath |
| ) |  |

Definition at line 76 of file path_tessellator_unittests.cc.

76 {
77 flutter::DlPathBuilder builder;
78 builder.MoveTo({0, 0});
79 builder.LineTo({10, 10});
80 builder.LineTo({0, 20});
81 builder.Close();
82 flutter::DlPath path = builder.TakePath();
83
84 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
85 {
86 ::testing::InSequence sequence;
87
88 EXPECT_CALL(mock_receiver,
89 BeginContour(Point(0, 0), /*will_be_closed=*/true));
90 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
91 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
92 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
93 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
94 }
95 PathTessellator::PathToFilledSegments(path, mock_receiver);
96
97 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
98 EXPECT_EQ(points, 4u);
99 EXPECT_EQ(contours, 1u);
100
101 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
102 {
103 ::testing::InSequence sequence;
104
105 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
106 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
107 EXPECT_CALL(mock_writer, Write(Point(0, 20)));
108 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
109 EXPECT_CALL(mock_writer, EndContour());
110 }
111 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
112 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [299/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | SimplePathMultipleMoveTo |
| ) |  |

Definition at line 357 of file path_tessellator_unittests.cc.

357 {
358 flutter::DlPathBuilder builder;
359 builder.MoveTo({500, 100});
360 builder.MoveTo({0, 0});
361 builder.LineTo({10, 10});
362 builder.LineTo({0, 20});
363 builder.Close();
364 flutter::DlPath path = builder.TakePath();
365
366 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
367 {
368 ::testing::InSequence sequence;
369
370 EXPECT_CALL(mock_receiver,
371 BeginContour(Point(0, 0), /*will_be_closed=*/true));
372 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
373 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
374 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
375 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
376 }
377 PathTessellator::PathToFilledSegments(path, mock_receiver);
378
379 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
380 EXPECT_EQ(points, 4u);
381 EXPECT_EQ(contours, 1u);
382
383 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
384 {
385 ::testing::InSequence sequence;
386
387 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
388 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
389 EXPECT_CALL(mock_writer, Write(Point(0, 20)));
390 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
391 EXPECT_CALL(mock_writer, EndContour());
392 }
393 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
394 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [300/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | SimplePathTrailingMoveTo |
| ) |  |

Definition at line 152 of file path_tessellator_unittests.cc.

152 {
153 flutter::DlPathBuilder builder;
154 builder.MoveTo({0, 0});
155 builder.LineTo({10, 10});
156 builder.LineTo({0, 20});
157 builder.Close();
158 builder.MoveTo({500, 100});
159 flutter::DlPath path = builder.TakePath();
160
161 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
162 {
163 ::testing::InSequence sequence;
164
165 EXPECT_CALL(mock_receiver,
166 BeginContour(Point(0, 0), /*will_be_closed=*/true));
167 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
168 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
169 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
170 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/true));
171 }
172 PathTessellator::PathToFilledSegments(path, mock_receiver);
173
174 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
175 EXPECT_EQ(points, 4u);
176 EXPECT_EQ(contours, 1u);
177
178 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
179 {
180 ::testing::InSequence sequence;
181
182 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
183 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
184 EXPECT_CALL(mock_writer, Write(Point(0, 20)));
185 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
186 EXPECT_CALL(mock_writer, EndContour());
187 }
188 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
189 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [301/574]

impeller::testing::TEST | ( | PathTessellatorTest | ,
|  | SimpleUnclosedPath |
| ) |  |

Definition at line 114 of file path_tessellator_unittests.cc.

114 {
115 flutter::DlPathBuilder builder;
116 builder.MoveTo({0, 0});
117 builder.LineTo({10, 10});
118 builder.LineTo({0, 20});
119 // Close not really needed for filled paths
120 flutter::DlPath path = builder.TakePath();
121
122 ::testing::StrictMock<MockSegmentReceiver> mock_receiver;
123 {
124 ::testing::InSequence sequence;
125
126 EXPECT_CALL(mock_receiver,
127 BeginContour(Point(0, 0), /*will_be_closed=*/false));
128 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 0), Point(10, 10)));
129 EXPECT_CALL(mock_receiver, RecordLine(Point(10, 10), Point(0, 20)));
130 EXPECT_CALL(mock_receiver, RecordLine(Point(0, 20), Point(0, 0)));
131 EXPECT_CALL(mock_receiver, EndContour(Point(0, 0), /*with_close=*/false));
132 }
133 PathTessellator::PathToFilledSegments(path, mock_receiver);
134
135 auto [points, contours] = PathTessellator::CountFillStorage(path, 1.0f);
136 EXPECT_EQ(points, 4u);
137 EXPECT_EQ(contours, 1u);
138
139 ::testing::StrictMock<MockPathVertexWriter> mock_writer;
140 {
141 ::testing::InSequence sequence;
142
143 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
144 EXPECT_CALL(mock_writer, Write(Point(10, 10)));
145 EXPECT_CALL(mock_writer, Write(Point(0, 20)));
146 EXPECT_CALL(mock_writer, Write(Point(0, 0)));
147 EXPECT_CALL(mock_writer, EndContour());
148 }
149 PathTessellator::PathToFilledVertices(path, mock_writer, 1.0f);
150 }

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [302/574]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanCreateFromDeviceProperties |
| ) |  |

Definition at line 77 of file pipeline_cache_data_vk_unittests.cc.

77 {
78 vk::PhysicalDeviceProperties props;
79 std::array<uint8_t, 16> uuid{
80 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
81 };
82 props.pipelineCacheUUID = uuid;
83 props.deviceID = 10;
84 props.vendorID = 11;
85 props.driverVersion = 12;
86 PipelineCacheHeaderVK header(props, 99);
87 EXPECT_EQ(uuid.size(), std::size(header.uuid));
88 EXPECT_EQ(props.deviceID, header.device_id);
89 EXPECT_EQ(props.vendorID, header.vendor_id);
90 EXPECT_EQ(props.driverVersion, header.driver_version);
91 for (size_t i = 0; i < uuid.size(); i++) {
92 EXPECT_EQ(header.uuid[i], uuid.at(i));
93 }
94 }

References impeller::PipelineCacheHeaderVK::device_id, impeller::PipelineCacheHeaderVK::driver_version, impeller::PipelineCacheHeaderVK::uuid, and impeller::PipelineCacheHeaderVK::vendor_id.

## ◆ TEST() [303/574]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanTestHeaderCompatibility |
| ) |  |

Definition at line 17 of file pipeline_cache_data_vk_unittests.cc.

17 {
18 {
19 PipelineCacheHeaderVK a;
20 PipelineCacheHeaderVK b;
21 EXPECT_EQ(a.abi, sizeof(void*));
22 #ifdef FML_ARCH_CPU_64_BITS
23 EXPECT_EQ(a.abi, 8u);
24 #elif FML_ARCH_CPU_32_BITS
25 EXPECT_EQ(a.abi, 4u);
26 #endif
27 EXPECT_TRUE(a.IsCompatibleWith(b));
28 }
29 // Different data sizes don't matter.
30 {
31 PipelineCacheHeaderVK a;
32 PipelineCacheHeaderVK b;
33 a.data_size = b.data_size + 100u;
34 EXPECT_TRUE(a.IsCompatibleWith(b));
35 }
36 // Magic, Driver, vendor, ABI, and UUID matter.
37 {
38 PipelineCacheHeaderVK a;
39 PipelineCacheHeaderVK b;
40 b.magic = 100;
41 EXPECT_FALSE(a.IsCompatibleWith(b));
42 }
43 {
44 PipelineCacheHeaderVK a;
45 PipelineCacheHeaderVK b;
46 b.driver_version = 100;
47 EXPECT_FALSE(a.IsCompatibleWith(b));
48 }
49 {
50 PipelineCacheHeaderVK a;
51 PipelineCacheHeaderVK b;
52 b.vendor_id = 100;
53 EXPECT_FALSE(a.IsCompatibleWith(b));
54 }
55 {
56 PipelineCacheHeaderVK a;
57 PipelineCacheHeaderVK b;
58 b.device_id = 100;
59 EXPECT_FALSE(a.IsCompatibleWith(b));
60 }
61 {
62 PipelineCacheHeaderVK a;
63 PipelineCacheHeaderVK b;
64 b.abi = a.abi / 2u;
65 EXPECT_FALSE(a.IsCompatibleWith(b));
66 }
67 {
68 PipelineCacheHeaderVK a;
69 PipelineCacheHeaderVK b;
70 for (size_t i = 0; i < VK_UUID_SIZE; i++) {
71 b.uuid[i] = a.uuid[i] + 1;
72 }
73 EXPECT_FALSE(a.IsCompatibleWith(b));
74 }
75 }

References impeller::PipelineCacheHeaderVK::abi, impeller::saturated::b, impeller::PipelineCacheHeaderVK::data_size, impeller::PipelineCacheHeaderVK::IsCompatibleWith(), and impeller::PipelineCacheHeaderVK::uuid.

## ◆ TEST() [304/574]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | WritesIncompleteCacheData |
| ) |  |

Definition at line 96 of file pipeline_cache_data_vk_unittests.cc.

96 {
97 fml::ScopedTemporaryDirectory temp_dir;
98 auto context = MockVulkanContextBuilder().Build();
99 auto cache = context->GetDevice().createPipelineCacheUnique({});
100 const auto& caps = CapabilitiesVK::Cast(*context->GetCapabilities());
101
102 ASSERT_TRUE(PipelineCacheDataPersist(
103 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
104
105 std::unique_ptr<fml::FileMapping> mapping = fml::FileMapping::CreateReadOnly(
106 temp_dir.fd(), "flutter.impeller.vkcache");
107 ASSERT_TRUE(mapping);
108 PipelineCacheHeaderVK header;
109 ASSERT_GE(mapping->GetSize(), sizeof(header));
110 std::memcpy(&header, mapping->GetMapping(), sizeof(header));
111 ASSERT_EQ(mapping->GetSize(), sizeof(header) + header.data_size);
112 }
impeller::PipelineCacheDataPersist
bool PipelineCacheDataPersist(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props, const vk::UniquePipelineCache &cache)
Persist the pipeline cache to a file in the given cache directory. This function performs integrity c...
Definition: pipeline_cache_data_vk.cc:16

References impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::PipelineCacheHeaderVK::data_size, and impeller::PipelineCacheDataPersist().

## ◆ TEST() [305/574]

impeller::testing::TEST | ( | PipelineDescriptorTest | ,
|  | PrimitiveTypeHashEquality |
| ) |  |

Definition at line 13 of file pipeline_descriptor_unittests.cc.

13 {
14 PipelineDescriptor descA;
15 PipelineDescriptor descB;
16
17 ASSERT_TRUE(descA.IsEqual(descB));
18 ASSERT_EQ(descA.GetHash(), descB.GetHash());
19
20 descA.SetPrimitiveType(PrimitiveType::kTriangleStrip);
21
22 ASSERT_FALSE(descA.IsEqual(descB));
23 ASSERT_NE(descA.GetHash(), descB.GetHash());
24 }

References impeller::PipelineDescriptor::GetHash(), impeller::PipelineDescriptor::IsEqual(), impeller::kTriangleStrip, and impeller::PipelineDescriptor::SetPrimitiveType().

## ◆ TEST() [306/574]

impeller::testing::TEST | ( | PointTest | ,
|  | CrossProductThreePoints |
| ) |  |

Definition at line 357 of file point_unittests.cc.

357 {
358 // Colinear
359 EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(1, 0)), 0);
360 EXPECT_FLOAT_EQ(Point::Cross(Point(1, 0), Point(0, 0), Point(-1, 0)), 0);
361
362 // Right turn
363 EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(0, 1)), 1);
364 EXPECT_FLOAT_EQ(Point::Cross(Point(-2, 0), Point(0, 0), Point(0, 2)), 4);
365
366 // Left turn
367 EXPECT_FLOAT_EQ(Point::Cross(Point(-1, 0), Point(0, 0), Point(0, -1)), -1);
368 EXPECT_FLOAT_EQ(Point::Cross(Point(-2, 0), Point(0, 0), Point(0, -2)), -4);
369
370 // Convenient values for a less obvious left turn.
371 // p1 - p0 == (0, 0) - (3, -4) == (-3, 4)
372 // p2 - p0 == (1, 2) - (3, -4) == (-2, 6)
373 // product of the magnitude of the 2 legs and the sin of their angle
374 // (||(-3, 4)||) * (||(-2, 6)||) * sin(angle)
375 // 5 * sqrt(40) * sin(angle)
376 // angle = arcsin(4 / 5) - arcsin(6 / sqrt(40)) ~= -18.4349
377 // sin(angle) ~= -0.316227766
378 // 5 * sqrt(40) * sin(angle) == -10
379 // The math is cleaner with the cross product:
380 // (-3 * 6) - (-2 * 4) == -18 - -8 == -10
381 EXPECT_FLOAT_EQ(Point::Cross(Point(3, -4), Point(0, 0), Point(1, 2)), -10);
382 }

References impeller::TPoint< Scalar >::Cross().

## ◆ TEST() [307/574]

impeller::testing::TEST | ( | PointTest | ,
|  | Distance |
| ) |  |

Definition at line 37 of file point_unittests.cc.

37 {
38 for (int j = 0; j < 21; j++) {
39 for (int i = 0; i < 21; i++) {
40 {
41 Scalar d = i - j;
42
43 EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(j, 0)), d * d)
44 << "i: " << i << ", j: " << j;
45 EXPECT_EQ(Point(0, i).GetDistanceSquared(Point(0, j)), d * d)
46 << "i: " << i << ", j: " << j;
47 EXPECT_EQ(Point(j, 0).GetDistanceSquared(Point(i, 0)), d * d)
48 << "i: " << i << ", j: " << j;
49 EXPECT_EQ(Point(0, j).GetDistanceSquared(Point(0, i)), d * d)
50 << "i: " << i << ", j: " << j;
51
52 EXPECT_EQ(Point(i, 0).GetDistance(Point(j, 0)), std::abs(d))
53 << "i: " << i << ", j: " << j;
54 EXPECT_EQ(Point(0, i).GetDistance(Point(0, j)), std::abs(d))
55 << "i: " << i << ", j: " << j;
56 EXPECT_EQ(Point(j, 0).GetDistance(Point(i, 0)), std::abs(d))
57 << "i: " << i << ", j: " << j;
58 EXPECT_EQ(Point(0, j).GetDistance(Point(0, i)), std::abs(d))
59 << "i: " << i << ", j: " << j;
60 }
61
62 {
63 Scalar d_squared = i * i + j * j;
64
65 EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(0, j)), d_squared)
66 << "i: " << i << ", j: " << j;
67 EXPECT_EQ(Point(-i, 0).GetDistanceSquared(Point(0, j)), d_squared)
68 << "i: " << i << ", j: " << j;
69 EXPECT_EQ(Point(i, 0).GetDistanceSquared(Point(0, -j)), d_squared)
70 << "i: " << i << ", j: " << j;
71 EXPECT_EQ(Point(-i, 0).GetDistanceSquared(Point(0, -j)), d_squared)
72 << "i: " << i << ", j: " << j;
73
74 Scalar d = std::sqrt(d_squared);
75
76 EXPECT_FLOAT_EQ(Point(i, 0).GetDistance(Point(0, j)), d)
77 << "i: " << i << ", j: " << j;
78 EXPECT_FLOAT_EQ(Point(-i, 0).GetDistance(Point(0, j)), d)
79 << "i: " << i << ", j: " << j;
80 EXPECT_FLOAT_EQ(Point(i, 0).GetDistance(Point(0, -j)), d)
81 << "i: " << i << ", j: " << j;
82 EXPECT_FLOAT_EQ(Point(-i, 0).GetDistance(Point(0, -j)), d)
83 << "i: " << i << ", j: " << j;
84 }
85 }
86 }
87 }

## ◆ TEST() [308/574]

impeller::testing::TEST | ( | PointTest | ,
|  | Length |
| ) |  |

Definition at line 13 of file point_unittests.cc.

13 {
14 for (int i = 0; i < 21; i++) {
15 EXPECT_EQ(Point(i, 0).GetLengthSquared(), i * i) << "i: " << i;
16 EXPECT_EQ(Point(0, i).GetLengthSquared(), i * i) << "i: " << i;
17 EXPECT_EQ(Point(-i, 0).GetLengthSquared(), i * i) << "i: " << i;
18 EXPECT_EQ(Point(0, -i).GetLengthSquared(), i * i) << "i: " << i;
19
20 EXPECT_EQ(Point(i, 0).GetLength(), i) << "i: " << i;
21 EXPECT_EQ(Point(0, i).GetLength(), i) << "i: " << i;
22 EXPECT_EQ(Point(-i, 0).GetLength(), i) << "i: " << i;
23 EXPECT_EQ(Point(0, -i).GetLength(), i) << "i: " << i;
24
25 EXPECT_EQ(Point(i, i).GetLengthSquared(), 2 * i * i) << "i: " << i;
26 EXPECT_EQ(Point(-i, i).GetLengthSquared(), 2 * i * i) << "i: " << i;
27 EXPECT_EQ(Point(i, -i).GetLengthSquared(), 2 * i * i) << "i: " << i;
28 EXPECT_EQ(Point(-i, -i).GetLengthSquared(), 2 * i * i) << "i: " << i;
29
30 EXPECT_FLOAT_EQ(Point(i, i).GetLength(), kSqrt2 * i) << "i: " << i;
31 EXPECT_FLOAT_EQ(Point(-i, i).GetLength(), kSqrt2 * i) << "i: " << i;
32 EXPECT_FLOAT_EQ(Point(i, -i).GetLength(), kSqrt2 * i) << "i: " << i;
33 EXPECT_FLOAT_EQ(Point(-i, -i).GetLength(), kSqrt2 * i) << "i: " << i;
34 }
35 }

References impeller::kSqrt2.

## ◆ TEST() [309/574]

impeller::testing::TEST | ( | PointTest | ,
|  | PerpendicularLeft |
| ) |  |

Definition at line 89 of file point_unittests.cc.

89 {
90 EXPECT_EQ(Point(1, 0).PerpendicularLeft(), Point(0, -1));
91 EXPECT_EQ(Point(0, 1).PerpendicularLeft(), Point(1, 0));
92 EXPECT_EQ(Point(-1, 0).PerpendicularLeft(), Point(0, 1));
93 EXPECT_EQ(Point(0, -1).PerpendicularLeft(), Point(-1, 0));
94
95 EXPECT_EQ(Point(1, 1).PerpendicularLeft(), Point(1, -1));
96 EXPECT_EQ(Point(-1, 1).PerpendicularLeft(), Point(1, 1));
97 EXPECT_EQ(Point(-1, -1).PerpendicularLeft(), Point(-1, 1));
98 EXPECT_EQ(Point(1, -1).PerpendicularLeft(), Point(-1, -1));
99 }

## ◆ TEST() [310/574]

impeller::testing::TEST | ( | PointTest | ,
|  | PerpendicularRight |
| ) |  |

Definition at line 101 of file point_unittests.cc.

101 {
102 EXPECT_EQ(Point(1, 0).PerpendicularRight(), Point(0, 1));
103 EXPECT_EQ(Point(0, 1).PerpendicularRight(), Point(-1, 0));
104 EXPECT_EQ(Point(-1, 0).PerpendicularRight(), Point(0, -1));
105 EXPECT_EQ(Point(0, -1).PerpendicularRight(), Point(1, 0));
106
107 EXPECT_EQ(Point(1, 1).PerpendicularRight(), Point(-1, 1));
108 EXPECT_EQ(Point(-1, 1).PerpendicularRight(), Point(-1, -1));
109 EXPECT_EQ(Point(-1, -1).PerpendicularRight(), Point(1, -1));
110 EXPECT_EQ(Point(1, -1).PerpendicularRight(), Point(1, 1));
111 }

## ◆ TEST() [311/574]

impeller::testing::TEST | ( | PointTest | ,
|  | PointToSegment |
| ) |  |

Definition at line 137 of file point_unittests.cc.

137 {
138 // Horizontal segment and points to the left of it on the same line.
139 TestPointToSegmentGroup(
140 // Segment
141 {10, 10}, {20, 10},
142 // Starting point, delta, count ({0,10} through {10,10})
143 {0, 10}, {1, 0}, 11,
144 // Distance computation
145 [](Point p) {
146 Scalar d = 10 - p.x;
147 return std::make_pair(d, d * d);
148 });
149
150 // Horizontal segment and points on the segment.
151 TestPointToSegmentGroup(
152 // Segment
153 {10, 10}, {20, 10},
154 // Starting point, delta, count ({11,10} through {19, 10})
155 {11, 10}, {1, 0}, 9,
156 // Distance computation
157 [](Point p) { //
158 return std::make_pair(0.0f, 0.0f);
159 });
160
161 // Horizontal segment and points to the right of it on the same line.
162 TestPointToSegmentGroup(
163 // Segment
164 {10, 10}, {20, 10},
165 // Starting point, delta, count ({20,10} through {30,10})
166 {20, 10}, {1, 0}, 11,
167 // Distance computation
168 [](Point p) {
169 Scalar d = p.x - 20;
170 return std::make_pair(d, d * d);
171 });
172
173 // Vertical segment and points above the top of it on the same line.
174 TestPointToSegmentGroup(
175 // Segment
176 {10, 10}, {10, 20},
177 // Starting point, delta, count ({10,0} through {10,10})
178 {10, 0}, {0, 1}, 11,
179 // Distance computation
180 [](Point p) {
181 Scalar d = 10 - p.y;
182 return std::make_pair(d, d * d);
183 });
184
185 // Vertical segment and points on the segment.
186 TestPointToSegmentGroup(
187 // Segment
188 {10, 10}, {10, 20},
189 // Starting point, delta, count ({10,11} through {10, 19})
190 {10, 11}, {0, 1}, 9,
191 // Distance computation
192 [](Point p) { //
193 return std::make_pair(0.0f, 0.0f);
194 });
195
196 // Vertical segment and points below the bottom of it on the same line.
197 TestPointToSegmentGroup(
198 // Segment
199 {10, 10}, {10, 20},
200 // Starting point, delta, count ({10,20} through {10,30})
201 {10, 20}, {0, 1}, 11,
202 // Distance computation
203 [](Point p) {
204 Scalar d = p.y - 20;
205 return std::make_pair(d, d * d);
206 });
207
208 // Horizontal segment and points 5 pixels above and to the left of it
209 // on the same line.
210 TestPointToSegmentGroup(
211 // Segment
212 {10, 10}, {20, 10},
213 // Starting point, delta, count ({0,5} through {10,5})
214 {0, 5}, {1, 0}, 11,
215 // Distance computation
216 [](Point p) {
217 Scalar d_sq = (10 - p.x) * (10 - p.x) + 25;
218 return std::make_pair(std::sqrt(d_sq), d_sq);
219 });
220
221 // Horizontal segment and points 5 pixels directly above the segment.
222 TestPointToSegmentGroup(
223 // Segment
224 {10, 10}, {20, 10},
225 // Starting point, delta, count ({11,5} through {19, 5})
226 {11, 5}, {1, 0}, 9,
227 // Distance computation
228 [](Point p) { //
229 return std::make_pair(5.0f, 25.0f);
230 });
231
232 // Horizontal segment and points 5 pixels above and to the right of it
233 // on the same line.
234 TestPointToSegmentGroup(
235 // Segment
236 {10, 10}, {20, 10},
237 // Starting point, delta, count ({20,5} through {30,5})
238 {20, 5}, {1, 0}, 11,
239 // Distance computation
240 [](Point p) {
241 Scalar d_sq = (p.x - 20) * (p.x - 20) + 25;
242 return std::make_pair(std::sqrt(d_sq), d_sq);
243 });
244
245 // Vertical segment and points 5 pixels to the left and above the segment
246 // on the same line.
247 TestPointToSegmentGroup(
248 // Segment
249 {10, 10}, {10, 20},
250 // Starting point, delta, count ({5,0} through {5,10})
251 {5, 0}, {0, 1}, 11,
252 // Distance computation
253 [](Point p) {
254 Scalar d_sq = 25 + (10 - p.y) * (10 - p.y);
255 return std::make_pair(std::sqrt(d_sq), d_sq);
256 });
257
258 // Vertical segment and points 5 pixels directly to the left of the segment.
259 TestPointToSegmentGroup(
260 // Segment
261 {10, 10}, {10, 20},
262 // Starting point, delta, count ({5,11} through {5,19,})
263 {5, 11}, {0, 1}, 9,
264 // Distance computation
265 [](Point p) { //
266 return std::make_pair(5.0f, 25.0f);
267 });
268
269 // Vertical segment and points 5 pixels to the left and below the segment
270 // on the same line.
271 TestPointToSegmentGroup(
272 // Segment
273 {10, 10}, {10, 20},
274 // Starting point, delta, count ({20,5} through {30,5})
275 {5, 20}, {0, 1}, 11,
276 // Distance computation
277 [](Point p) {
278 Scalar d_sq = 25 + (p.y - 20) * (p.y - 20);
279 return std::make_pair(std::sqrt(d_sq), d_sq);
280 });
281
282 // Diagonal segment and points up and to the right of the top of the segment.
283 TestPointToSegmentGroup(
284 // Segment
285 {10, 10}, {20, 20},
286 // Starting point, delta, count ({5,-5} through {15,5})
287 {5, -5}, {1, 1}, 11,
288 // Distance computation
289 [](Point p) {
290 Scalar d_sq = (p.x - 10) * (p.x - 10) + (p.y - 10) * (p.y - 10);
291 return std::make_pair(std::sqrt(d_sq), d_sq);
292 });
293
294 // Diagonal segment and points up and to the right of the segment itself.
295 TestPointToSegmentGroup(
296 // Segment
297 {10, 10}, {20, 20},
298 // Starting point, delta, count ({15,5} through {24,14})
299 {15, 5}, {1, 1}, 9,
300 // Distance computation
301 [](Point p) {
302 Scalar d_sq = 50.0f;
303 return std::make_pair(std::sqrt(d_sq), d_sq);
304 });
305
306 // Diagonal segment and points up and to the right of the bottom of the
307 // segment.
308 TestPointToSegmentGroup(
309 // Segment
310 {10, 10}, {20, 20},
311 // Starting point, delta, count ({25,15} through {35,25})
312 {25, 15}, {1, 1}, 11,
313 // Distance computation
314 [](Point p) {
315 Scalar d_sq = (p.x - 20) * (p.x - 20) + (p.y - 20) * (p.y - 20);
316 return std::make_pair(std::sqrt(d_sq), d_sq);
317 });
318
319 // Diagonal segment and points down and to the left of the top of the segment.
320 TestPointToSegmentGroup(
321 // Segment
322 {10, 10}, {20, 20},
323 // Starting point, delta, count ({-5,5} through {5,15})
324 {-5, 5}, {1, 1}, 11,
325 // Distance computation
326 [](Point p) {
327 Scalar d_sq = (p.x - 10) * (p.x - 10) + (p.y - 10) * (p.y - 10);
328 return std::make_pair(std::sqrt(d_sq), d_sq);
329 });
330
331 // Diagonal segment and points down and to the left of the segment itself.
332 TestPointToSegmentGroup(
333 // Segment
334 {10, 10}, {20, 20},
335 // Starting point, delta, count ({5,15} through {14,24})
336 {5, 15}, {1, 1}, 9,
337 // Distance computation
338 [](Point p) {
339 Scalar d_sq = 50.0f;
340 return std::make_pair(std::sqrt(d_sq), d_sq);
341 });
342
343 // Diagonal segment and points down and to the left of the bottom of the
344 // segment.
345 TestPointToSegmentGroup(
346 // Segment
347 {10, 10}, {20, 20},
348 // Starting point, delta, count ({15,25} through {25,35})
349 {15, 25}, {1, 1}, 11,
350 // Distance computation
351 [](Point p) {
352 Scalar d_sq = (p.x - 20) * (p.x - 20) + (p.y - 20) * (p.y - 20);
353 return std::make_pair(std::sqrt(d_sq), d_sq);
354 });
355 }

## ◆ TEST() [312/574]

impeller::testing::TEST | ( | PoolTest | ,
|  | Overload |
| ) |  |

Definition at line 47 of file pool_unittests.cc.

47 {
48 Pool<Foobar> pool(1'000);
49 {
50 std::vector<std::shared_ptr<Foobar>> values;
51 values.reserve(20);
52 for (int i = 0; i < 20; i++) {
53 values.push_back(pool.Grab());
54 }
55 for (const auto& value : values) {
56 value->SetSize(100);
57 pool.Recycle(value);
58 }
59 }
60 EXPECT_EQ(pool.GetSize(), 1'000u);
61 }

References impeller::Pool< T >::GetSize(), impeller::Pool< T >::Grab(), impeller::Pool< T >::Recycle(), and value.

## ◆ TEST() [313/574]

impeller::testing::TEST | ( | PoolTest | ,
|  | Simple |
| ) |  |

Definition at line 33 of file pool_unittests.cc.

33 {
34 Pool<Foobar> pool(1'000);
35 {
36 auto grabbed = pool.Grab();
37 grabbed->SetSize(123);
38 pool.Recycle(grabbed);
39 EXPECT_EQ(pool.GetSize(), 123u);
40 }
41 auto grabbed = pool.Grab();
42 EXPECT_EQ(grabbed->GetSize(), 123u);
43 EXPECT_TRUE(grabbed->GetIsReset());
44 EXPECT_EQ(pool.GetSize(), 0u);
45 }

References impeller::Pool< T >::GetSize(), impeller::Pool< T >::Grab(), and impeller::Pool< T >::Recycle().

## ◆ TEST() [314/574]

impeller::testing::TEST | ( | RectTest | ,
|  | ContainsFloatingPoint |
| ) |  |

Definition at line 1316 of file rect_unittests.cc.

1316 {
1317 auto rect1 =
1318 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1319 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1320 EXPECT_TRUE(rect1.Contains(rect2));
1321 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [315/574]

impeller::testing::TEST | ( | RectTest | ,
|  | EmptyIRectDoesNotIntersect |
| ) |  |

Definition at line 899 of file rect_unittests.cc.

899 {
900 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
901
902 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
903 const std::string& label) {
904 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
905 << label << " with Top/Bottom swapped";
906 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
907 << label << " with Left/Right swapped";
908 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
909 << label << " with all sides swapped";
910 };
911
912 test(20, 20, 30, 30, "Above and Left");
913 test(70, 20, 80, 30, "Above");
914 test(120, 20, 130, 30, "Above and Right");
915 test(120, 70, 130, 80, "Right");
916 test(120, 120, 130, 130, "Below and Right");
917 test(70, 120, 80, 130, "Below");
918 test(20, 120, 30, 130, "Below and Left");
919 test(20, 70, 30, 80, "Left");
920
921 test(70, 70, 80, 80, "Inside");
922
923 test(40, 70, 60, 80, "Straddling Left");
924 test(70, 40, 80, 60, "Straddling Top");
925 test(90, 70, 110, 80, "Straddling Right");
926 test(70, 90, 80, 110, "Straddling Bottom");
927 }
impeller::IRect
IRect64 IRect
Definition: rect.h:791

References impeller::saturated::b, and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [316/574]

impeller::testing::TEST | ( | RectTest | ,
|  | EmptyRectDoesNotIntersect |
| ) |  |

Definition at line 869 of file rect_unittests.cc.

869 {
870 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
871
872 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
873 const std::string& label) {
874 EXPECT_FALSE(Rect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
875 << label << " with Top/Bottom swapped";
876 EXPECT_FALSE(Rect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
877 << label << " with Left/Right swapped";
878 EXPECT_FALSE(Rect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
879 << label << " with all sides swapped";
880 };
881
882 test(20, 20, 30, 30, "Above and Left");
883 test(70, 20, 80, 30, "Above");
884 test(120, 20, 130, 30, "Above and Right");
885 test(120, 70, 130, 80, "Right");
886 test(120, 120, 130, 130, "Below and Right");
887 test(70, 120, 80, 130, "Below");
888 test(20, 120, 30, 130, "Below and Left");
889 test(20, 70, 30, 80, "Left");
890
891 test(70, 70, 80, 80, "Inside");
892
893 test(40, 70, 60, 80, "Straddling Left");
894 test(70, 40, 80, 60, "Straddling Top");
895 test(90, 70, 110, 80, "Straddling Right");
896 test(70, 90, 80, 110, "Straddling Bottom");
897 }

References impeller::saturated::b, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [317/574]

impeller::testing::TEST | ( | RectTest | ,
|  | GetCenter |
| ) |  |

Definition at line 1239 of file rect_unittests.cc.

1239 {
1240 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1241 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1242 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1243
1244 // Note that we expect a Point as the answer from an IRect
1245 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1246 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1247 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1248 }

References impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< T >::MakeMaximum(), impeller::TRect< T >::MakeXYWH(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [318/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectArea |
| ) |  |

Definition at line 1025 of file rect_unittests.cc.

1025 {
1026 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1027 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1028 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1029 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1030 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1031 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1032 }

References impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [319/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsInclusiveIPoint |
| ) |  |

Definition at line 2404 of file rect_unittests.cc.

2404 {
2405 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2406 const std::string& label) {
2407 ASSERT_FALSE(rect.IsEmpty());
2408
2409 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2410 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2411 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2412 };
2413
2414 auto test_inside = [&check_empty_flips](const IRect& rect,
2415 const IPoint& point) {
2416 ASSERT_FALSE(rect.IsEmpty()) << rect;
2417
2418 std::stringstream stream;
2419 stream << rect << " contains " << point;
2420 auto label = stream.str();
2421
2422 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2423 check_empty_flips(rect, point, label);
2424 };
2425
2426 auto test_outside = [&check_empty_flips](const IRect& rect,
2427 const IPoint& point) {
2428 ASSERT_FALSE(rect.IsEmpty()) << rect;
2429
2430 std::stringstream stream;
2431 stream << rect << " contains " << point;
2432 auto label = stream.str();
2433
2434 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2435 check_empty_flips(rect, point, label);
2436 };
2437
2438 {
2439 // Origin is inclusive
2440 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2441 auto p = IPoint(100, 100);
2442
2443 test_inside(r, p);
2444 }
2445 {
2446 // Size is inclusive
2447 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2448 auto p = IPoint(200, 200);
2449
2450 test_inside(r, p);
2451 }
2452 {
2453 // Size + "epsilon" is exclusive
2454 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2455 auto p = IPoint(201, 201);
2456
2457 test_outside(r, p);
2458 }
2459 {
2460 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2461 auto p = IPoint(99, 99);
2462
2463 test_outside(r, p);
2464 }
2465 {
2466 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2467 auto p = IPoint(199, 199);
2468
2469 test_inside(r, p);
2470 }
2471
2472 {
2473 auto r = IRect::MakeMaximum();
2474 auto p = IPoint(199, 199);
2475
2476 test_inside(r, p);
2477 }
2478 }
impeller::testing::flip_lrtb
static constexpr R flip_lrtb(R rect)
Definition: rect_unittests.cc:1336

References impeller::TRect< T >::ContainsInclusive(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [320/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsIPoint |
| ) |  |

Definition at line 2242 of file rect_unittests.cc.

2242 {
2243 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2244 const std::string& label) {
2245 ASSERT_FALSE(rect.IsEmpty());
2246
2247 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2248 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2249 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2250 };
2251
2252 auto test_inside = [&check_empty_flips](const IRect& rect,
2253 const IPoint& point) {
2254 ASSERT_FALSE(rect.IsEmpty()) << rect;
2255
2256 std::stringstream stream;
2257 stream << rect << " contains " << point;
2258 auto label = stream.str();
2259
2260 EXPECT_TRUE(rect.Contains(point)) << label;
2261 check_empty_flips(rect, point, label);
2262 };
2263
2264 auto test_outside = [&check_empty_flips](const IRect& rect,
2265 const IPoint& point) {
2266 ASSERT_FALSE(rect.IsEmpty()) << rect;
2267
2268 std::stringstream stream;
2269 stream << rect << " contains " << point;
2270 auto label = stream.str();
2271
2272 EXPECT_FALSE(rect.Contains(point)) << label;
2273 check_empty_flips(rect, point, label);
2274 };
2275
2276 {
2277 // Origin is inclusive
2278 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2279 auto p = IPoint(100, 100);
2280
2281 test_inside(r, p);
2282 }
2283 {
2284 // Size is exclusive
2285 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2286 auto p = IPoint(200, 200);
2287
2288 test_outside(r, p);
2289 }
2290 {
2291 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2292 auto p = IPoint(99, 99);
2293
2294 test_outside(r, p);
2295 }
2296 {
2297 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2298 auto p = IPoint(199, 199);
2299
2300 test_inside(r, p);
2301 }
2302
2303 {
2304 auto r = IRect::MakeMaximum();
2305 auto p = IPoint(199, 199);
2306
2307 test_inside(r, p);
2308 }
2309 }

References impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [321/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsIRect |
| ) |  |

Definition at line 2595 of file rect_unittests.cc.

2595 {
2596 auto check_empty_flips = [](const IRect& a, const IRect& b,
2597 const std::string& label) {
2598 ASSERT_FALSE(a.IsEmpty());
2599 // test b rects are allowed to have 0 w/h, but not be backwards
2600 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2601
2602 // unflipped a vs flipped (empty) b yields true
2603 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2604 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2605 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2606
2607 // flipped (empty) a vs unflipped b yields false
2608 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2609 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2610 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2611
2612 // flipped (empty) a vs flipped (empty) b yields empty
2613 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2614 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2615 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2616 };
2617
2618 auto test_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2619 ASSERT_FALSE(a.IsEmpty()) << a;
2620 // test b rects are allowed to have 0 w/h, but not be backwards
2621 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2622
2623 std::stringstream stream;
2624 stream << a << " contains " << b;
2625 auto label = stream.str();
2626
2627 EXPECT_TRUE(a.Contains(b)) << label;
2628 check_empty_flips(a, b, label);
2629 };
2630
2631 auto test_not_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2632 ASSERT_FALSE(a.IsEmpty()) << a;
2633 // If b was empty, it would be contained and should not be tested with
2634 // this function - use |test_inside| instead.
2635 ASSERT_FALSE(b.IsEmpty()) << b;
2636
2637 std::stringstream stream;
2638 stream << a << " contains " << b;
2639 auto label = stream.str();
2640
2641 EXPECT_FALSE(a.Contains(b)) << label;
2642 check_empty_flips(a, b, label);
2643 };
2644
2645 {
2646 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2647
2648 test_inside(a, a);
2649 }
2650 {
2651 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2652 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2653
2654 test_inside(a, b);
2655 }
2656 {
2657 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2658 auto b = IRect::MakeXYWH(150, 150, 20, 20);
2659
2660 test_inside(a, b);
2661 }
2662 {
2663 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2664 auto b = IRect::MakeXYWH(150, 150, 100, 100);
2665
2666 test_not_inside(a, b);
2667 }
2668 {
2669 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2670 auto b = IRect::MakeXYWH(50, 50, 100, 100);
2671
2672 test_not_inside(a, b);
2673 }
2674 {
2675 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2676 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2677
2678 test_not_inside(a, b);
2679 }
2680 {
2681 auto a = IRect::MakeMaximum();
2682 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2683
2684 test_inside(a, b);
2685 }
2686 }

References impeller::saturated::b, impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [322/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectCopy |
| ) |  |

Definition at line 686 of file rect_unittests.cc.

686 {
687 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
688 IRect copy = rect;
689
690 EXPECT_EQ(rect, copy);
691 EXPECT_EQ(copy.GetLeft(), 5);
692 EXPECT_EQ(copy.GetTop(), 10);
693 EXPECT_EQ(copy.GetRight(), 20);
694 EXPECT_EQ(copy.GetBottom(), 25);
695 EXPECT_EQ(copy.GetX(), 5);
696 EXPECT_EQ(copy.GetY(), 10);
697 EXPECT_EQ(copy.GetWidth(), 15);
698 EXPECT_EQ(copy.GetHeight(), 15);
699 EXPECT_FALSE(copy.IsEmpty());
700 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [323/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectCutOut |
| ) |  |

Definition at line 2840 of file rect_unittests.cc.

2840 {
2841 IRect cull_rect = IRect::MakeLTRB(20, 20, 40, 40);
2842
2843 auto check_empty_flips = [&cull_rect](const IRect& diff_rect,
2844 const std::string& label) {
2845 EXPECT_FALSE(diff_rect.IsEmpty());
2846 EXPECT_FALSE(cull_rect.IsEmpty());
2847
2848 // unflipped cull_rect vs flipped(empty) diff_rect
2849 // == cull_rect
2850 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2851 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2852 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2853 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2854 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2855 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2856
2857 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2858 // == empty
2859 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2860 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2861 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2862 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2863 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2864 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2865
2866 // flipped(empty) cull_rect vs unflipped diff_rect
2867 // == empty
2868 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2869 << label;
2870 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), IRect())
2871 << label;
2872 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2873 << label;
2874 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), IRect())
2875 << label;
2876 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2877 << label;
2878 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), IRect())
2879 << label;
2880 };
2881
2882 auto non_reducing = [&cull_rect, &check_empty_flips](
2883 const IRect& diff_rect, const std::string& label) {
2884 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2885 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2886 check_empty_flips(diff_rect, label);
2887 };
2888
2889 auto reducing = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2890 const IRect& result_rect,
2891 const std::string& label) {
2892 EXPECT_TRUE(!result_rect.IsEmpty());
2893 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2894 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2895 check_empty_flips(diff_rect, label);
2896 };
2897
2898 auto emptying = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2899 const std::string& label) {
2900 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2901 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), IRect()) << label;
2902 check_empty_flips(diff_rect, label);
2903 };
2904
2905 // Skim the corners and edge
2906 non_reducing(IRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2907 non_reducing(IRect::MakeLTRB(20, 10, 40, 20), "Above");
2908 non_reducing(IRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2909 non_reducing(IRect::MakeLTRB(40, 20, 50, 40), "Right");
2910 non_reducing(IRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2911 non_reducing(IRect::MakeLTRB(20, 40, 40, 50), "Below");
2912 non_reducing(IRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2913 non_reducing(IRect::MakeLTRB(10, 20, 20, 40), "Left");
2914
2915 // Overlap corners
2916 non_reducing(IRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2917 non_reducing(IRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2918 non_reducing(IRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2919 non_reducing(IRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2920
2921 // Overlap edges, but not across an entire side
2922 non_reducing(IRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2923 non_reducing(IRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2924 non_reducing(IRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2925 non_reducing(IRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2926 non_reducing(IRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2927 non_reducing(IRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2928 non_reducing(IRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2929 non_reducing(IRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2930
2931 // Slice all the way through the middle
2932 non_reducing(IRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2933 non_reducing(IRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2934
2935 // Slice off each edge
2936 reducing(IRect::MakeLTRB(20, 15, 40, 25), //
2937 IRect::MakeLTRB(20, 25, 40, 40), //
2938 "Slice off top");
2939 reducing(IRect::MakeLTRB(35, 20, 45, 40), //
2940 IRect::MakeLTRB(20, 20, 35, 40), //
2941 "Slice off right");
2942 reducing(IRect::MakeLTRB(20, 35, 40, 45), //
2943 IRect::MakeLTRB(20, 20, 40, 35), //
2944 "Slice off bottom");
2945 reducing(IRect::MakeLTRB(15, 20, 25, 40), //
2946 IRect::MakeLTRB(25, 20, 40, 40), //
2947 "Slice off left");
2948
2949 // cull rect contains diff rect
2950 non_reducing(IRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2951
2952 // cull rect equals diff rect
2953 emptying(cull_rect, "Perfectly covering");
2954
2955 // diff rect contains cull rect
2956 emptying(IRect::MakeLTRB(15, 15, 45, 45), "Smothering");
2957 }

References impeller::TRect< T >::Cutout(), impeller::TRect< T >::CutoutOrEmpty(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [324/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectDefaultConstructor |
| ) |  |

Definition at line 59 of file rect_unittests.cc.

59 {
60 IRect rect = IRect();
61
62 EXPECT_EQ(rect.GetLeft(), 0);
63 EXPECT_EQ(rect.GetTop(), 0);
64 EXPECT_EQ(rect.GetRight(), 0);
65 EXPECT_EQ(rect.GetBottom(), 0);
66 EXPECT_EQ(rect.GetX(), 0);
67 EXPECT_EQ(rect.GetY(), 0);
68 EXPECT_EQ(rect.GetWidth(), 0);
69 EXPECT_EQ(rect.GetHeight(), 0);
70 EXPECT_TRUE(rect.IsEmpty());
71 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), and impeller::TRect< T >::IsEmpty().

## ◆ TEST() [325/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectDoesNotIntersectEmpty |
| ) |  |

Definition at line 839 of file rect_unittests.cc.

839 {
840 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
841
842 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
843 const std::string& label) {
844 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(l, b, r, t)))
845 << label << " with Top/Bottom swapped";
846 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, b, l, t)))
847 << label << " with Left/Right swapped";
848 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, t, l, b)))
849 << label << " with all sides swapped";
850 };
851
852 test(20, 20, 30, 30, "Above and Left");
853 test(70, 20, 80, 30, "Above");
854 test(120, 20, 130, 30, "Above and Right");
855 test(120, 70, 130, 80, "Right");
856 test(120, 120, 130, 130, "Below and Right");
857 test(70, 120, 80, 130, "Below");
858 test(20, 120, 30, 130, "Below and Left");
859 test(20, 70, 30, 80, "Left");
860
861 test(70, 70, 80, 80, "Inside");
862
863 test(40, 70, 60, 80, "Straddling Left");
864 test(70, 40, 80, 60, "Straddling Top");
865 test(90, 70, 110, 80, "Straddling Right");
866 test(70, 90, 80, 110, "Straddling Bottom");
867 }

References impeller::saturated::b, impeller::TRect< T >::IntersectsWithRect(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [326/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectEmptyDeclaration |
| ) |  |

Definition at line 29 of file rect_unittests.cc.

29 {
30 IRect rect;
31
32 EXPECT_EQ(rect.GetLeft(), 0);
33 EXPECT_EQ(rect.GetTop(), 0);
34 EXPECT_EQ(rect.GetRight(), 0);
35 EXPECT_EQ(rect.GetBottom(), 0);
36 EXPECT_EQ(rect.GetX(), 0);
37 EXPECT_EQ(rect.GetY(), 0);
38 EXPECT_EQ(rect.GetWidth(), 0);
39 EXPECT_EQ(rect.GetHeight(), 0);
40 EXPECT_TRUE(rect.IsEmpty());
41 // EXPECT_TRUE(rect.IsFinite()); // should fail to compile
42 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), and impeller::TRect< T >::IsEmpty().

## ◆ TEST() [327/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectExpand |
| ) |  |

Definition at line 1283 of file rect_unittests.cc.

1283 {
1284 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1285
1286 // Expand(T amount)
1287 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1288 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1289
1290 // Expand(amount, amount)
1291 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1292 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1293 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1294 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1295
1296 // Expand(amount, amount, amount, amount)
1297 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1298 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1299 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1300 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1301 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1302
1303 // Expand(IPoint amount)
1304 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1305 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1306 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1307 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1308
1309 // Expand(ISize amount)
1310 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1311 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1312 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1313 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1314 }

References impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [328/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectFromIRect |
| ) |  |

Definition at line 661 of file rect_unittests.cc.

661 {
662 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
663 IRect::MakeXYWH(2, 3, 7, 15));
664 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
665 IRect::MakeLTRB(2, 3, 7, 15));
666 }

References impeller::TRect< T >::MakeLTRB(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [329/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectGetNormalizingTransform |
| ) |  |

Definition at line 1122 of file rect_unittests.cc.

1122 {
1123 {
1124 // Checks for expected matrix values
1125
1126 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1127
1128 EXPECT_EQ(r.GetNormalizingTransform(),
1129 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1130 Matrix::MakeTranslation({-100, -200}));
1131 }
1132
1133 {
1134 // Checks for expected transform of points relative to the rect
1135
1136 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1137 auto m = r.GetNormalizingTransform();
1138
1139 // The 4 corners of the rect => (0, 0) to (1, 1)
1140 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1141 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1142 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1143 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1144
1145 // The center => (0.5, 0.5)
1146 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1147
1148 // Outside the 4 corners => (-1, -1) to (2, 2)
1149 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1150 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1151 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1152 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1153 }
1154
1155 {
1156 // Checks for behavior with empty rects
1157
1158 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1159
1160 // Empty for width and/or height == 0
1161 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1162 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1163 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1164
1165 // Empty for width and/or height < 0
1166 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1167 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1168 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1169 }
1170 }

References impeller::TRect< T >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [330/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectIntersection |
| ) |  |

Definition at line 1800 of file rect_unittests.cc.

1800 {
1801 auto check_empty_flips = [](const IRect& a, const IRect& b,
1802 const std::string& label) {
1803 ASSERT_FALSE(a.IsEmpty());
1804 // b is allowed to be empty
1805
1806 // unflipped a vs flipped (empty) b yields a
1807 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1808 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1809 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1810
1811 // flipped (empty) a vs unflipped b yields b
1812 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1813 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1814 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1815
1816 // flipped (empty) a vs flipped (empty) b yields empty
1817 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1818 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1819 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1820 };
1821
1822 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b,
1823 const IRect& result) {
1824 ASSERT_FALSE(a.IsEmpty()) << a;
1825 // b is allowed to be empty
1826
1827 std::stringstream stream;
1828 stream << a << " union " << b;
1829 auto label = stream.str();
1830
1831 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1832 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1833 EXPECT_EQ(a.Intersection(b), result) << label;
1834 EXPECT_EQ(b.Intersection(a), result) << label;
1835 check_empty_flips(a, b, label);
1836 };
1837
1838 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
1839 ASSERT_FALSE(a.IsEmpty()) << a;
1840 // b is allowed to be empty
1841
1842 std::stringstream stream;
1843 stream << a << " union " << b;
1844 auto label = stream.str();
1845
1846 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1847 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1848 check_empty_flips(a, b, label);
1849 };
1850
1851 {
1852 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1853 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1854
1855 test_empty(a, b);
1856 }
1857
1858 {
1859 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1860 auto b = IRect::MakeXYWH(10, 10, 0, 0);
1861
1862 test_empty(a, b);
1863 }
1864
1865 {
1866 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1867 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1868 auto expected = IRect::MakeXYWH(10, 10, 90, 90);
1869
1870 test_non_empty(a, b, expected);
1871 }
1872
1873 {
1874 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1875 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1876
1877 test_empty(a, b);
1878 }
1879
1880 {
1881 auto a = IRect::MakeMaximum();
1882 auto b = IRect::MakeXYWH(10, 10, 300, 300);
1883
1884 test_non_empty(a, b, b);
1885 }
1886
1887 {
1888 auto a = IRect::MakeMaximum();
1889 auto b = IRect::MakeMaximum();
1890
1891 test_non_empty(a, b, IRect::MakeMaximum());
1892 }
1893 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [331/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectIntersectsWithRect |
| ) |  |

Definition at line 2065 of file rect_unittests.cc.

2065 {
2066 auto check_empty_flips = [](const IRect& a, const IRect& b,
2067 const std::string& label) {
2068 ASSERT_FALSE(a.IsEmpty());
2069 // b is allowed to be empty
2070
2071 // unflipped a vs flipped (empty) b yields a
2072 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
2073 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
2074 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
2075
2076 // flipped (empty) a vs unflipped b yields b
2077 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
2078 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
2079 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
2080
2081 // flipped (empty) a vs flipped (empty) b yields empty
2082 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
2083 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
2084 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
2085 };
2086
2087 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2088 ASSERT_FALSE(a.IsEmpty()) << a;
2089 // b is allowed to be empty
2090
2091 std::stringstream stream;
2092 stream << a << " union " << b;
2093 auto label = stream.str();
2094
2095 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2096 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2097 check_empty_flips(a, b, label);
2098 };
2099
2100 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2101 ASSERT_FALSE(a.IsEmpty()) << a;
2102 // b is allowed to be empty
2103
2104 std::stringstream stream;
2105 stream << a << " union " << b;
2106 auto label = stream.str();
2107
2108 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2109 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2110 check_empty_flips(a, b, label);
2111 };
2112
2113 {
2114 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2115 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2116
2117 test_empty(a, b);
2118 }
2119
2120 {
2121 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2122 auto b = IRect::MakeXYWH(10, 10, 0, 0);
2123
2124 test_empty(a, b);
2125 }
2126
2127 {
2128 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2129 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2130
2131 test_non_empty(a, b);
2132 }
2133
2134 {
2135 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2136 auto b = IRect::MakeXYWH(100, 100, 100, 100);
2137
2138 test_empty(a, b);
2139 }
2140
2141 {
2142 auto a = IRect::MakeMaximum();
2143 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2144
2145 test_non_empty(a, b);
2146 }
2147
2148 {
2149 auto a = IRect::MakeMaximum();
2150 auto b = IRect::MakeMaximum();
2151
2152 test_non_empty(a, b);
2153 }
2154 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IntersectsWithRect(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [332/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectMakeMaximum |
| ) |  |

Definition at line 638 of file rect_unittests.cc.

638 {
639 IRect rect = IRect::MakeMaximum();
640 auto min = std::numeric_limits<int64_t>::min();
641 auto max = std::numeric_limits<int64_t>::max();
642
643 EXPECT_EQ(rect.GetLeft(), min);
644 EXPECT_EQ(rect.GetTop(), min);
645 EXPECT_EQ(rect.GetRight(), max);
646 EXPECT_EQ(rect.GetBottom(), max);
647 EXPECT_EQ(rect.GetX(), min);
648 EXPECT_EQ(rect.GetY(), min);
649 EXPECT_EQ(rect.GetWidth(), max);
650 EXPECT_EQ(rect.GetHeight(), max);
651 EXPECT_FALSE(rect.IsEmpty());
652 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeMaximum().

## ◆ TEST() [333/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOriginSizeXYWHGetters |
| ) |  |

Definition at line 728 of file rect_unittests.cc.

728 {
729 {
730 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
731 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
732 EXPECT_EQ(r.GetSize(), ISize(50, 40));
733 EXPECT_EQ(r.GetX(), 10);
734 EXPECT_EQ(r.GetY(), 20);
735 EXPECT_EQ(r.GetWidth(), 50);
736 EXPECT_EQ(r.GetHeight(), 40);
737 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
738 EXPECT_EQ(r.GetXYWH(), expected_array);
739 }
740
741 {
742 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
743 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
744 EXPECT_EQ(r.GetSize(), ISize(40, 20));
745 EXPECT_EQ(r.GetX(), 10);
746 EXPECT_EQ(r.GetY(), 20);
747 EXPECT_EQ(r.GetWidth(), 40);
748 EXPECT_EQ(r.GetHeight(), 20);
749 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
750 EXPECT_EQ(r.GetXYWH(), expected_array);
751 }
752 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetXYWH(), impeller::TRect< T >::GetY(), impeller::TRect< T >::MakeLTRB(), and impeller::TRect< T >::MakeOriginSize().

## ◆ TEST() [334/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOverflowLTRB |
| ) |  |

Definition at line 523 of file rect_unittests.cc.

523 {
524 auto min = std::numeric_limits<int64_t>::min();
525 auto max = std::numeric_limits<int64_t>::max();
526
527 // 4 cases
528 // negative l, r near max takes width past max
529 // positive l, r near min takes width below min
530 // negative t, b near max takes width past max
531 // positive t, b near min takes width below min
532
533 {
534 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
535
536 EXPECT_EQ(rect.GetLeft(), -10);
537 EXPECT_EQ(rect.GetTop(), 10);
538 EXPECT_EQ(rect.GetRight(), max - 5);
539 EXPECT_EQ(rect.GetBottom(), 26);
540 EXPECT_EQ(rect.GetX(), -10);
541 EXPECT_EQ(rect.GetY(), 10);
542 EXPECT_EQ(rect.GetWidth(), max);
543 EXPECT_EQ(rect.GetHeight(), 16);
544 EXPECT_FALSE(rect.IsEmpty());
545 }
546
547 {
548 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
549
550 EXPECT_EQ(rect.GetLeft(), 10);
551 EXPECT_EQ(rect.GetTop(), 10);
552 EXPECT_EQ(rect.GetRight(), min + 5);
553 EXPECT_EQ(rect.GetBottom(), 26);
554 EXPECT_EQ(rect.GetX(), 10);
555 EXPECT_EQ(rect.GetY(), 10);
556 EXPECT_EQ(rect.GetWidth(), min);
557 EXPECT_EQ(rect.GetHeight(), 16);
558 EXPECT_TRUE(rect.IsEmpty());
559 }
560
561 {
562 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 5);
563
564 EXPECT_EQ(rect.GetLeft(), 5);
565 EXPECT_EQ(rect.GetTop(), -10);
566 EXPECT_EQ(rect.GetRight(), 15);
567 EXPECT_EQ(rect.GetBottom(), max - 5);
568 EXPECT_EQ(rect.GetX(), 5);
569 EXPECT_EQ(rect.GetY(), -10);
570 EXPECT_EQ(rect.GetWidth(), 10);
571 EXPECT_EQ(rect.GetHeight(), max);
572 EXPECT_FALSE(rect.IsEmpty());
573 }
574
575 {
576 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
577
578 EXPECT_EQ(rect.GetLeft(), 5);
579 EXPECT_EQ(rect.GetTop(), 10);
580 EXPECT_EQ(rect.GetRight(), 15);
581 EXPECT_EQ(rect.GetBottom(), min + 5);
582 EXPECT_EQ(rect.GetX(), 5);
583 EXPECT_EQ(rect.GetY(), 10);
584 EXPECT_EQ(rect.GetWidth(), 10);
585 EXPECT_EQ(rect.GetHeight(), min);
586 EXPECT_TRUE(rect.IsEmpty());
587 }
588 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [335/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOverflowXYWH |
| ) |  |

Definition at line 317 of file rect_unittests.cc.

317 {
318 auto min = std::numeric_limits<int64_t>::min();
319 auto max = std::numeric_limits<int64_t>::max();
320
321 // 4 cases
322 // x near max, positive w takes it past max
323 // x near min, negative w takes it below min
324 // y near max, positive h takes it past max
325 // y near min, negative h takes it below min
326
327 {
328 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
329
330 EXPECT_EQ(rect.GetLeft(), max - 5);
331 EXPECT_EQ(rect.GetTop(), 10);
332 EXPECT_EQ(rect.GetRight(), max);
333 EXPECT_EQ(rect.GetBottom(), 26);
334 EXPECT_EQ(rect.GetX(), max - 5);
335 EXPECT_EQ(rect.GetY(), 10);
336 EXPECT_EQ(rect.GetWidth(), 5);
337 EXPECT_EQ(rect.GetHeight(), 16);
338 EXPECT_FALSE(rect.IsEmpty());
339 }
340
341 {
342 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
343
344 EXPECT_EQ(rect.GetLeft(), min + 5);
345 EXPECT_EQ(rect.GetTop(), 10);
346 EXPECT_EQ(rect.GetRight(), min);
347 EXPECT_EQ(rect.GetBottom(), 26);
348 EXPECT_EQ(rect.GetX(), min + 5);
349 EXPECT_EQ(rect.GetY(), 10);
350 EXPECT_EQ(rect.GetWidth(), -5);
351 EXPECT_EQ(rect.GetHeight(), 16);
352 EXPECT_TRUE(rect.IsEmpty());
353 }
354
355 {
356 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
357
358 EXPECT_EQ(rect.GetLeft(), 5);
359 EXPECT_EQ(rect.GetTop(), max - 10);
360 EXPECT_EQ(rect.GetRight(), 15);
361 EXPECT_EQ(rect.GetBottom(), max);
362 EXPECT_EQ(rect.GetX(), 5);
363 EXPECT_EQ(rect.GetY(), max - 10);
364 EXPECT_EQ(rect.GetWidth(), 10);
365 EXPECT_EQ(rect.GetHeight(), 10);
366 EXPECT_FALSE(rect.IsEmpty());
367 }
368
369 {
370 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
371
372 EXPECT_EQ(rect.GetLeft(), 5);
373 EXPECT_EQ(rect.GetTop(), min + 10);
374 EXPECT_EQ(rect.GetRight(), 15);
375 EXPECT_EQ(rect.GetBottom(), min);
376 EXPECT_EQ(rect.GetX(), 5);
377 EXPECT_EQ(rect.GetY(), min + 10);
378 EXPECT_EQ(rect.GetWidth(), 10);
379 EXPECT_EQ(rect.GetHeight(), -10);
380 EXPECT_TRUE(rect.IsEmpty());
381 }
382 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [336/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectRound |
| ) |  |

Definition at line 3098 of file rect_unittests.cc.

3098 {
3099 {
3100 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3101 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3102 EXPECT_EQ(IRect::Round(r), ir);
3103 }
3104 {
3105 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3106 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3107 EXPECT_EQ(IRect::Round(r), ir);
3108 }
3109 {
3110 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3111 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3112 EXPECT_EQ(IRect::Round(r), ir);
3113 }
3114 }

References impeller::TRect< T >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::Round().

## ◆ TEST() [337/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectRoundOut |
| ) |  |

Definition at line 3070 of file rect_unittests.cc.

3070 {
3071 {
3072 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3073 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3074 EXPECT_EQ(IRect::RoundOut(r), ir);
3075 }
3076 {
3077 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3078 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3079 EXPECT_EQ(IRect::RoundOut(r), ir);
3080 }
3081 }

References impeller::TRect< T >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::RoundOut().

## ◆ TEST() [338/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectScale |
| ) |  |

Definition at line 974 of file rect_unittests.cc.

974 {
975 auto test1 = [](IRect rect, int64_t scale) {
976 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
977 rect.GetY() * scale, //
978 rect.GetWidth() * scale, //
979 rect.GetHeight() * scale);
980
981 EXPECT_EQ(rect.Scale(scale), expected) //
982 << rect << " * " << scale;
983 EXPECT_EQ(rect.Scale(scale, scale), expected) //
984 << rect << " * " << scale;
985 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
986 << rect << " * " << scale;
987 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
988 << rect << " * " << scale;
989 };
990
991 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
992 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
993 rect.GetY() * scale_y, //
994 rect.GetWidth() * scale_x, //
995 rect.GetHeight() * scale_y);
996
997 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
998 << rect << " * " << scale_x << ", " << scale_y;
999 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
1000 << rect << " * " << scale_x << ", " << scale_y;
1001 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
1002 << rect << " * " << scale_x << ", " << scale_y;
1003
1004 test1(rect, scale_x);
1005 test1(rect, scale_y);
1006 };
1007
1008 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
1009 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
1010 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
1011 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
1012 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
1013 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
1014 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::MakeLTRB(), impeller::TRect< T >::MakeXYWH(), and impeller::TRect< T >::Scale().

## ◆ TEST() [339/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectSimpleLTRB |
| ) |  |

Definition at line 89 of file rect_unittests.cc.

89 {
90 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
91
92 EXPECT_EQ(rect.GetLeft(), 5);
93 EXPECT_EQ(rect.GetTop(), 10);
94 EXPECT_EQ(rect.GetRight(), 20);
95 EXPECT_EQ(rect.GetBottom(), 25);
96 EXPECT_EQ(rect.GetX(), 5);
97 EXPECT_EQ(rect.GetY(), 10);
98 EXPECT_EQ(rect.GetWidth(), 15);
99 EXPECT_EQ(rect.GetHeight(), 15);
100 EXPECT_FALSE(rect.IsEmpty());
101 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [340/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectSimpleWH |
| ) |  |

Definition at line 149 of file rect_unittests.cc.

149 {
150 // Using fractional-power-of-2 friendly values for equality tests
151 IRect rect = IRect::MakeWH(15, 25);
152
153 EXPECT_EQ(rect.GetLeft(), 0);
154 EXPECT_EQ(rect.GetTop(), 0);
155 EXPECT_EQ(rect.GetRight(), 15);
156 EXPECT_EQ(rect.GetBottom(), 25);
157 EXPECT_EQ(rect.GetX(), 0);
158 EXPECT_EQ(rect.GetY(), 0);
159 EXPECT_EQ(rect.GetWidth(), 15);
160 EXPECT_EQ(rect.GetHeight(), 25);
161 EXPECT_FALSE(rect.IsEmpty());
162 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeWH().

## ◆ TEST() [341/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectSimpleXYWH |
| ) |  |

Definition at line 119 of file rect_unittests.cc.

119 {
120 IRect rect = IRect::MakeXYWH(5, 10, 15, 16);
121
122 EXPECT_EQ(rect.GetLeft(), 5);
123 EXPECT_EQ(rect.GetTop(), 10);
124 EXPECT_EQ(rect.GetRight(), 20);
125 EXPECT_EQ(rect.GetBottom(), 26);
126 EXPECT_EQ(rect.GetX(), 5);
127 EXPECT_EQ(rect.GetY(), 10);
128 EXPECT_EQ(rect.GetWidth(), 15);
129 EXPECT_EQ(rect.GetHeight(), 16);
130 EXPECT_FALSE(rect.IsEmpty());
131 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [342/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectUnion |
| ) |  |

Definition at line 1497 of file rect_unittests.cc.

1497 {
1498 auto check_empty_flips = [](const IRect& a, const IRect& b,
1499 const std::string& label) {
1500 ASSERT_FALSE(a.IsEmpty());
1501 // b is allowed to be empty
1502
1503 // unflipped a vs flipped (empty) b yields a
1504 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1505 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1506 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1507
1508 // flipped (empty) a vs unflipped b yields b
1509 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1510 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1511 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1512
1513 // flipped (empty) a vs flipped (empty) b yields empty
1514 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1515 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1516 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1517 };
1518
1519 auto test = [&check_empty_flips](const IRect& a, const IRect& b,
1520 const IRect& result) {
1521 ASSERT_FALSE(a.IsEmpty()) << a;
1522 // b is allowed to be empty
1523
1524 std::stringstream stream;
1525 stream << a << " union " << b;
1526 auto label = stream.str();
1527
1528 EXPECT_EQ(a.Union(b), result) << label;
1529 EXPECT_EQ(b.Union(a), result) << label;
1530 check_empty_flips(a, b, label);
1531 };
1532
1533 {
1534 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1535 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1536 auto expected = IRect::MakeXYWH(100, 100, 100, 100);
1537 test(a, b, expected);
1538 }
1539
1540 {
1541 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1542 auto b = IRect::MakeXYWH(0, 0, 1, 1);
1543 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1544 test(a, b, expected);
1545 }
1546
1547 {
1548 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1549 auto b = IRect::MakeXYWH(10, 10, 1, 1);
1550 auto expected = IRect::MakeXYWH(10, 10, 190, 190);
1551 test(a, b, expected);
1552 }
1553
1554 {
1555 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1556 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1557 auto expected = IRect::MakeXYWH(0, 0, 110, 110);
1558 test(a, b, expected);
1559 }
1560
1561 {
1562 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1563 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1564 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1565 test(a, b, expected);
1566 }
1567 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeXYWH(), and impeller::TRect< T >::Union().

## ◆ TEST() [343/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectXYWHIsEmpty |
| ) |  |

Definition at line 1196 of file rect_unittests.cc.

1196 {
1197 // Non-empty
1198 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1199
1200 // Empty both width and height both 0 or negative, in all combinations
1201 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1202 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1203 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1204 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1205
1206 // Empty for 0 or negative width or height (but not both at the same time)
1207 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1208 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1209 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1210 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1211 }

References impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [344/574]

impeller::testing::TEST | ( | RectTest | ,
|  | IsSquare |
| ) |  |

Definition at line 1227 of file rect_unittests.cc.

1227 {
1228 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1229 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1230 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1231 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1232
1233 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1234 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1235 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1236 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1237 }

References impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< T >::MakeMaximum(), impeller::TRect< T >::MakeXYWH(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [345/574]

impeller::testing::TEST | ( | RectTest | ,
|  | MakePointBoundsQuad |
| ) |  |

Definition at line 1213 of file rect_unittests.cc.

1213 {
1214 Quad quad = {
1215 Point(10, 10),
1216 Point(20, 10),
1217 Point(10, 20),
1218 Point(20, 20),
1219 };
1220 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1221 EXPECT_TRUE(bounds.has_value());
1222 if (bounds.has_value()) {
1223 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1224 }
1225 }
RectNear
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
Definition: geometry_asserts.h:89

References impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakePointBounds(), and RectNear().

## ◆ TEST() [346/574]

impeller::testing::TEST | ( | RectTest | ,
|  | OptIRectIntersection |
| ) |  |

Definition at line 1895 of file rect_unittests.cc.

1895 {
1896 auto a = IRect::MakeLTRB(0, 0, 110, 110);
1897 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1898 auto c = IRect::MakeLTRB(100, 0, 200, 110);
1899
1900 // NullOpt, NullOpt
1901 EXPECT_FALSE(IRect::Intersection(std::nullopt, std::nullopt).has_value());
1902 EXPECT_EQ(IRect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1903
1904 auto test1 = [](const IRect& r) {
1905 // Rect, NullOpt
1906 EXPECT_TRUE(IRect::Intersection(r, std::nullopt).has_value());
1907 EXPECT_EQ(IRect::Intersection(r, std::nullopt).value(), r);
1908
1909 // OptRect, NullOpt
1910 EXPECT_TRUE(
1911 IRect::Intersection(std::optional(r), std::nullopt).has_value());
1912 EXPECT_EQ(IRect::Intersection(std::optional(r), std::nullopt).value(), r);
1913
1914 // NullOpt, Rect
1915 EXPECT_TRUE(IRect::Intersection(std::nullopt, r).has_value());
1916 EXPECT_EQ(IRect::Intersection(std::nullopt, r).value(), r);
1917
1918 // NullOpt, OptRect
1919 EXPECT_TRUE(
1920 IRect::Intersection(std::nullopt, std::optional(r)).has_value());
1921 EXPECT_EQ(IRect::Intersection(std::nullopt, std::optional(r)).value(), r);
1922 };
1923
1924 test1(a);
1925 test1(b);
1926 test1(c);
1927
1928 auto test2 = [](const IRect& a, const IRect& b, const IRect& i) {
1929 ASSERT_EQ(a.Intersection(b), i);
1930
1931 // Rect, OptRect
1932 EXPECT_TRUE(IRect::Intersection(a, std::optional(b)).has_value());
1933 EXPECT_EQ(IRect::Intersection(a, std::optional(b)).value(), i);
1934
1935 // OptRect, Rect
1936 EXPECT_TRUE(IRect::Intersection(std::optional(a), b).has_value());
1937 EXPECT_EQ(IRect::Intersection(std::optional(a), b).value(), i);
1938
1939 // OptRect, OptRect
1940 EXPECT_TRUE(
1941 IRect::Intersection(std::optional(a), std::optional(b)).has_value());
1942 EXPECT_EQ(IRect::Intersection(std::optional(a), std::optional(b)).value(),
1943 i);
1944 };
1945
1946 test2(a, b, IRect::MakeLTRB(100, 100, 110, 110));
1947 test2(a, c, IRect::MakeLTRB(100, 0, 110, 110));
1948 test2(b, c, IRect::MakeLTRB(100, 100, 200, 110));
1949 }

References impeller::saturated::b, c, impeller::TRect< T >::Intersection(), impeller::TRect< T >::MakeLTRB(), and value.

## ◆ TEST() [347/574]

impeller::testing::TEST | ( | RectTest | ,
|  | OptIRectUnion |
| ) |  |

Definition at line 1569 of file rect_unittests.cc.

1569 {
1570 auto a = IRect::MakeLTRB(0, 0, 100, 100);
1571 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1572 auto c = IRect::MakeLTRB(100, 0, 200, 100);
1573
1574 // NullOpt, NullOpt
1575 EXPECT_FALSE(IRect::Union(std::nullopt, std::nullopt).has_value());
1576 EXPECT_EQ(IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1577
1578 auto test1 = [](const IRect& r) {
1579 // Rect, NullOpt
1580 EXPECT_EQ(IRect::Union(r, std::nullopt), r);
1581
1582 // OptRect, NullOpt
1583 EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
1584 EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
1585
1586 // NullOpt, Rect
1587 EXPECT_EQ(IRect::Union(std::nullopt, r), r);
1588
1589 // NullOpt, OptRect
1590 EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
1591 EXPECT_EQ(IRect::Union(std::nullopt, std::optional(r)).value(), r);
1592 };
1593
1594 test1(a);
1595 test1(b);
1596 test1(c);
1597
1598 auto test2 = [](const IRect& a, const IRect& b, const IRect& u) {
1599 ASSERT_EQ(a.Union(b), u);
1600
1601 // Rect, OptRect
1602 EXPECT_EQ(IRect::Union(a, std::optional(b)), u);
1603
1604 // OptRect, Rect
1605 EXPECT_EQ(IRect::Union(std::optional(a), b), u);
1606
1607 // OptRect, OptRect
1608 EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
1609 EXPECT_EQ(IRect::Union(std::optional(a), std::optional(b)).value(), u);
1610 };
1611
1612 test2(a, b, IRect::MakeLTRB(0, 0, 200, 200));
1613 test2(a, c, IRect::MakeLTRB(0, 0, 200, 100));
1614 test2(b, c, IRect::MakeLTRB(100, 0, 200, 200));
1615 }

References impeller::saturated::b, c, impeller::TRect< T >::MakeLTRB(), impeller::TRect< T >::Union(), and value.

## ◆ TEST() [348/574]

impeller::testing::TEST | ( | RectTest | ,
|  | OptRectIntersection |
| ) |  |

Definition at line 1746 of file rect_unittests.cc.

1746 {
1747 auto a = Rect::MakeLTRB(0, 0, 110, 110);
1748 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1749 auto c = Rect::MakeLTRB(100, 0, 200, 110);
1750
1751 // NullOpt, NullOpt
1752 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1753 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1754
1755 auto test1 = [](const Rect& r) {
1756 // Rect, NullOpt
1757 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1758 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1759
1760 // OptRect, NullOpt
1761 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1762 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1763
1764 // NullOpt, Rect
1765 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1766 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1767
1768 // NullOpt, OptRect
1769 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1770 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1771 };
1772
1773 test1(a);
1774 test1(b);
1775 test1(c);
1776
1777 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1778 ASSERT_EQ(a.Intersection(b), i);
1779
1780 // Rect, OptRect
1781 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1782 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1783
1784 // OptRect, Rect
1785 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1786 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1787
1788 // OptRect, OptRect
1789 EXPECT_TRUE(
1790 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1791 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1792 i);
1793 };
1794
1795 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1796 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1797 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1798 }

References impeller::saturated::b, c, impeller::TRect< T >::Intersection(), impeller::TRect< Scalar >::Intersection(), impeller::TRect< Scalar >::MakeLTRB(), and value.

## ◆ TEST() [349/574]

impeller::testing::TEST | ( | RectTest | ,
|  | OptRectUnion |
| ) |  |

Definition at line 1449 of file rect_unittests.cc.

1449 {
1450 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1451 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1452 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1453
1454 // NullOpt, NullOpt
1455 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1456 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1457
1458 auto test1 = [](const Rect& r) {
1459 // Rect, NullOpt
1460 EXPECT_EQ(Rect::Union(r, std::nullopt), r);
1461
1462 // OptRect, NullOpt
1463 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1464 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1465
1466 // NullOpt, Rect
1467 EXPECT_EQ(Rect::Union(std::nullopt, r), r);
1468
1469 // NullOpt, OptRect
1470 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1471 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1472 };
1473
1474 test1(a);
1475 test1(b);
1476 test1(c);
1477
1478 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1479 ASSERT_EQ(a.Union(b), u);
1480
1481 // Rect, OptRect
1482 EXPECT_EQ(Rect::Union(a, std::optional(b)), u);
1483
1484 // OptRect, Rect
1485 EXPECT_EQ(Rect::Union(std::optional(a), b), u);
1486
1487 // OptRect, OptRect
1488 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1489 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1490 };
1491
1492 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1493 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1494 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1495 }

References impeller::saturated::b, c, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::Union(), impeller::TRect< Scalar >::Union(), and value.

## ◆ TEST() [350/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectArea |
| ) |  |

Definition at line 1016 of file rect_unittests.cc.

1016 {
1017 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
1018 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
1019 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
1020 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
1021 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
1022 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
1023 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [351/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectContainsInclusivePoint |
| ) |  |

Definition at line 2311 of file rect_unittests.cc.

2311 {
2312 auto check_nans = [](const Rect& rect, const Point& point,
2313 const std::string& label) {
2314 ASSERT_TRUE(rect.IsFinite()) << label;
2315 ASSERT_TRUE(point.IsFinite()) << label;
2316
2317 for (int i = 1; i < 16; i++) {
2318 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(point))
2319 << label << ", index = " << i;
2320 for (int j = 1; j < 4; j++) {
2321 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(swap_nan(point, j)))
2322 << label << ", indices = " << i << ", " << j;
2323 }
2324 }
2325 };
2326
2327 auto check_empty_flips = [](const Rect& rect, const Point& point,
2328 const std::string& label) {
2329 ASSERT_FALSE(rect.IsEmpty());
2330
2331 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2332 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2333 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2334 };
2335
2336 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2337 const Point& point) {
2338 ASSERT_FALSE(rect.IsEmpty()) << rect;
2339
2340 std::stringstream stream;
2341 stream << rect << " contains " << point;
2342 auto label = stream.str();
2343
2344 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2345 check_empty_flips(rect, point, label);
2346 check_nans(rect, point, label);
2347 };
2348
2349 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2350 const Point& point) {
2351 ASSERT_FALSE(rect.IsEmpty()) << rect;
2352
2353 std::stringstream stream;
2354 stream << rect << " contains " << point;
2355 auto label = stream.str();
2356
2357 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2358 check_empty_flips(rect, point, label);
2359 check_nans(rect, point, label);
2360 };
2361
2362 {
2363 // Origin is inclusive
2364 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2365 auto p = Point(100, 100);
2366
2367 test_inside(r, p);
2368 }
2369 {
2370 // Size is inclusive
2371 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2372 auto p = Point(200, 200);
2373
2374 test_inside(r, p);
2375 }
2376 {
2377 // Size + epsilon is exclusive
2378 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2379 auto p = Point(200 + kEhCloseEnough, 200 + kEhCloseEnough);
2380
2381 test_outside(r, p);
2382 }
2383 {
2384 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2385 auto p = Point(99, 99);
2386
2387 test_outside(r, p);
2388 }
2389 {
2390 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2391 auto p = Point(199, 199);
2392
2393 test_inside(r, p);
2394 }
2395
2396 {
2397 auto r = Rect::MakeMaximum();
2398 auto p = Point(199, 199);
2399
2400 test_inside(r, p);
2401 }
2402 }
impeller::testing::swap_nan
static constexpr Point swap_nan(const Point &point, int index)
Definition: rect_unittests.cc:1350

References impeller::TRect< T >::ContainsInclusive(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::kEhCloseEnough, impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [352/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectContainsPoint |
| ) |  |

Definition at line 2156 of file rect_unittests.cc.

2156 {
2157 auto check_nans = [](const Rect& rect, const Point& point,
2158 const std::string& label) {
2159 ASSERT_TRUE(rect.IsFinite()) << label;
2160 ASSERT_TRUE(point.IsFinite()) << label;
2161
2162 for (int i = 1; i < 16; i++) {
2163 EXPECT_FALSE(swap_nan(rect, i).Contains(point))
2164 << label << ", index = " << i;
2165 for (int j = 1; j < 4; j++) {
2166 EXPECT_FALSE(swap_nan(rect, i).Contains(swap_nan(point, j)))
2167 << label << ", indices = " << i << ", " << j;
2168 }
2169 }
2170 };
2171
2172 auto check_empty_flips = [](const Rect& rect, const Point& point,
2173 const std::string& label) {
2174 ASSERT_FALSE(rect.IsEmpty());
2175
2176 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2177 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2178 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2179 };
2180
2181 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2182 const Point& point) {
2183 ASSERT_FALSE(rect.IsEmpty()) << rect;
2184
2185 std::stringstream stream;
2186 stream << rect << " contains " << point;
2187 auto label = stream.str();
2188
2189 EXPECT_TRUE(rect.Contains(point)) << label;
2190 check_empty_flips(rect, point, label);
2191 check_nans(rect, point, label);
2192 };
2193
2194 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2195 const Point& point) {
2196 ASSERT_FALSE(rect.IsEmpty()) << rect;
2197
2198 std::stringstream stream;
2199 stream << rect << " contains " << point;
2200 auto label = stream.str();
2201
2202 EXPECT_FALSE(rect.Contains(point)) << label;
2203 check_empty_flips(rect, point, label);
2204 check_nans(rect, point, label);
2205 };
2206
2207 {
2208 // Origin is inclusive
2209 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2210 auto p = Point(100, 100);
2211
2212 test_inside(r, p);
2213 }
2214 {
2215 // Size is exclusive
2216 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2217 auto p = Point(200, 200);
2218
2219 test_outside(r, p);
2220 }
2221 {
2222 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2223 auto p = Point(99, 99);
2224
2225 test_outside(r, p);
2226 }
2227 {
2228 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2229 auto p = Point(199, 199);
2230
2231 test_inside(r, p);
2232 }
2233
2234 {
2235 auto r = Rect::MakeMaximum();
2236 auto p = Point(199, 199);
2237
2238 test_inside(r, p);
2239 }
2240 }

References impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [353/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectContainsRect |
| ) |  |

Definition at line 2480 of file rect_unittests.cc.

2480 {
2481 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
2482 ASSERT_TRUE(a.IsFinite()) << label;
2483 ASSERT_TRUE(b.IsFinite()) << label;
2484 ASSERT_FALSE(a.IsEmpty());
2485
2486 for (int i = 1; i < 16; i++) {
2487 // NaN in a produces false
2488 EXPECT_FALSE(swap_nan(a, i).Contains(b)) << label << ", index = " << i;
2489 // NaN in b produces false
2490 EXPECT_TRUE(a.Contains(swap_nan(b, i))) << label << ", index = " << i;
2491 // NaN in both is false
2492 for (int j = 1; j < 16; j++) {
2493 EXPECT_FALSE(swap_nan(a, i).Contains(swap_nan(b, j)))
2494 << label << ", indices = " << i << ", " << j;
2495 }
2496 }
2497 };
2498
2499 auto check_empty_flips = [](const Rect& a, const Rect& b,
2500 const std::string& label) {
2501 ASSERT_FALSE(a.IsEmpty());
2502 // test b rects are allowed to have 0 w/h, but not be backwards
2503 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2504
2505 // unflipped a vs flipped (empty) b yields false
2506 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2507 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2508 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2509
2510 // flipped (empty) a vs unflipped b yields false
2511 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2512 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2513 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2514
2515 // flipped (empty) a vs flipped (empty) b yields empty
2516 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2517 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2518 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2519 };
2520
2521 auto test_inside = [&check_nans, &check_empty_flips](const Rect& a,
2522 const Rect& b) {
2523 ASSERT_FALSE(a.IsEmpty()) << a;
2524 // test b rects are allowed to have 0 w/h, but not be backwards
2525 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2526
2527 std::stringstream stream;
2528 stream << a << " contains " << b;
2529 auto label = stream.str();
2530
2531 EXPECT_TRUE(a.Contains(b)) << label;
2532 check_empty_flips(a, b, label);
2533 check_nans(a, b, label);
2534 };
2535
2536 auto test_not_inside = [&check_nans, &check_empty_flips](const Rect& a,
2537 const Rect& b) {
2538 ASSERT_FALSE(a.IsEmpty()) << a;
2539 // If b was empty, it would be contained and should not be tested with
2540 // this function - use |test_inside| instead.
2541 ASSERT_FALSE(b.IsEmpty()) << b;
2542
2543 std::stringstream stream;
2544 stream << a << " contains " << b;
2545 auto label = stream.str();
2546
2547 EXPECT_FALSE(a.Contains(b)) << label;
2548 check_empty_flips(a, b, label);
2549 check_nans(a, b, label);
2550 };
2551
2552 {
2553 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2554
2555 test_inside(a, a);
2556 }
2557 {
2558 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2559 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2560
2561 test_inside(a, b);
2562 }
2563 {
2564 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2565 auto b = Rect::MakeXYWH(150, 150, 20, 20);
2566
2567 test_inside(a, b);
2568 }
2569 {
2570 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2571 auto b = Rect::MakeXYWH(150, 150, 100, 100);
2572
2573 test_not_inside(a, b);
2574 }
2575 {
2576 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2577 auto b = Rect::MakeXYWH(50, 50, 100, 100);
2578
2579 test_not_inside(a, b);
2580 }
2581 {
2582 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2583 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2584
2585 test_not_inside(a, b);
2586 }
2587 {
2588 auto a = Rect::MakeMaximum();
2589 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2590
2591 test_inside(a, b);
2592 }
2593 }

References impeller::saturated::b, impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [354/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectCopy |
| ) |  |

Definition at line 668 of file rect_unittests.cc.

668 {
669 // Using fractional-power-of-2 friendly values for equality tests
670 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
671 Rect copy = rect;
672
673 EXPECT_EQ(rect, copy);
674 EXPECT_EQ(copy.GetLeft(), 5.125f);
675 EXPECT_EQ(copy.GetTop(), 10.25f);
676 EXPECT_EQ(copy.GetRight(), 20.625f);
677 EXPECT_EQ(copy.GetBottom(), 25.375f);
678 EXPECT_EQ(copy.GetX(), 5.125f);
679 EXPECT_EQ(copy.GetY(), 10.25f);
680 EXPECT_EQ(copy.GetWidth(), 15.5f);
681 EXPECT_EQ(copy.GetHeight(), 15.125f);
682 EXPECT_FALSE(copy.IsEmpty());
683 EXPECT_TRUE(copy.IsFinite());
684 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [355/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectCutOut |
| ) |  |

Definition at line 2688 of file rect_unittests.cc.

2688 {
2689 Rect cull_rect = Rect::MakeLTRB(20, 20, 40, 40);
2690
2691 auto check_nans = [&cull_rect](const Rect& diff_rect,
2692 const std::string& label) {
2693 EXPECT_TRUE(cull_rect.IsFinite()) << label;
2694 EXPECT_TRUE(diff_rect.IsFinite()) << label;
2695
2696 for (int i = 1; i < 16; i++) {
2697 // NaN in cull_rect produces empty
2698 EXPECT_FALSE(swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2699 << label << ", index " << i;
2700 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect), Rect())
2701 << label << ", index " << i;
2702
2703 // NaN in diff_rect is nop
2704 EXPECT_TRUE(cull_rect.Cutout(swap_nan(diff_rect, i)).has_value())
2705 << label << ", index " << i;
2706 EXPECT_EQ(cull_rect.CutoutOrEmpty(swap_nan(diff_rect, i)), cull_rect)
2707 << label << ", index " << i;
2708
2709 for (int j = 1; j < 16; j++) {
2710 // NaN in both is also empty
2711 EXPECT_FALSE(
2712 swap_nan(cull_rect, i).Cutout(swap_nan(diff_rect, j)).has_value())
2713 << label << ", indices " << i << ", " << j;
2714 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(swap_nan(diff_rect, j)),
2715 Rect())
2716 << label << ", indices " << i << ", " << j;
2717 }
2718 }
2719 };
2720
2721 auto check_empty_flips = [&cull_rect](const Rect& diff_rect,
2722 const std::string& label) {
2723 EXPECT_FALSE(cull_rect.IsEmpty()) << label;
2724 EXPECT_FALSE(diff_rect.IsEmpty()) << label;
2725
2726 // unflipped cull_rect vs flipped(empty) diff_rect
2727 // == cull_rect
2728 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2729 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2730 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2731 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2732 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2733 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2734
2735 // flipped(empty) cull_rect vs unflipped diff_rect
2736 // == empty
2737 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2738 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2739 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2740 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2741 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2742 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2743
2744 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2745 // == empty
2746 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2747 << label;
2748 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), Rect())
2749 << label;
2750 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2751 << label;
2752 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), Rect())
2753 << label;
2754 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2755 << label;
2756 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), Rect())
2757 << label;
2758 };
2759
2760 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2761 const Rect& diff_rect, const std::string& label) {
2762 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2763 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2764 check_empty_flips(diff_rect, label);
2765 check_nans(diff_rect, label);
2766 };
2767
2768 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2769 const Rect& diff_rect, const Rect& result_rect,
2770 const std::string& label) {
2771 EXPECT_TRUE(!result_rect.IsEmpty());
2772 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2773 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2774 check_empty_flips(diff_rect, label);
2775 check_nans(diff_rect, label);
2776 };
2777
2778 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2779 const Rect& diff_rect, const std::string& label) {
2780 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2781 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), Rect()) << label;
2782 check_empty_flips(diff_rect, label);
2783 check_nans(diff_rect, label);
2784 };
2785
2786 // Skim the corners and edge
2787 non_reducing(Rect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2788 non_reducing(Rect::MakeLTRB(20, 10, 40, 20), "Above");
2789 non_reducing(Rect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2790 non_reducing(Rect::MakeLTRB(40, 20, 50, 40), "Right");
2791 non_reducing(Rect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2792 non_reducing(Rect::MakeLTRB(20, 40, 40, 50), "Below");
2793 non_reducing(Rect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2794 non_reducing(Rect::MakeLTRB(10, 20, 20, 40), "Left");
2795
2796 // Overlap corners
2797 non_reducing(Rect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2798 non_reducing(Rect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2799 non_reducing(Rect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2800 non_reducing(Rect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2801
2802 // Overlap edges, but not across an entire side
2803 non_reducing(Rect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2804 non_reducing(Rect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2805 non_reducing(Rect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2806 non_reducing(Rect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2807 non_reducing(Rect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2808 non_reducing(Rect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2809 non_reducing(Rect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2810 non_reducing(Rect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2811
2812 // Slice all the way through the middle
2813 non_reducing(Rect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2814 non_reducing(Rect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2815
2816 // Slice off each edge
2817 reducing(Rect::MakeLTRB(20, 15, 40, 25), //
2818 Rect::MakeLTRB(20, 25, 40, 40), //
2819 "Slice off top");
2820 reducing(Rect::MakeLTRB(35, 20, 45, 40), //
2821 Rect::MakeLTRB(20, 20, 35, 40), //
2822 "Slice off right");
2823 reducing(Rect::MakeLTRB(20, 35, 40, 45), //
2824 Rect::MakeLTRB(20, 20, 40, 35), //
2825 "Slice off bottom");
2826 reducing(Rect::MakeLTRB(15, 20, 25, 40), //
2827 Rect::MakeLTRB(25, 20, 40, 40), //
2828 "Slice off left");
2829
2830 // cull rect contains diff rect
2831 non_reducing(Rect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2832
2833 // cull rect equals diff rect
2834 emptying(cull_rect, "Perfectly covering");
2835
2836 // diff rect contains cull rect
2837 emptying(Rect::MakeLTRB(15, 15, 45, 45), "Smothering");
2838 }

References impeller::TRect< T >::Cutout(), impeller::TRect< T >::CutoutOrEmpty(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeLTRB(), and swap_nan().

## ◆ TEST() [356/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectDefaultConstructor |
| ) |  |

Definition at line 44 of file rect_unittests.cc.

44 {
45 Rect rect = Rect();
46
47 EXPECT_EQ(rect.GetLeft(), 0.0f);
48 EXPECT_EQ(rect.GetTop(), 0.0f);
49 EXPECT_EQ(rect.GetRight(), 0.0f);
50 EXPECT_EQ(rect.GetBottom(), 0.0f);
51 EXPECT_EQ(rect.GetX(), 0.0f);
52 EXPECT_EQ(rect.GetY(), 0.0f);
53 EXPECT_EQ(rect.GetWidth(), 0.0f);
54 EXPECT_EQ(rect.GetHeight(), 0.0f);
55 EXPECT_TRUE(rect.IsEmpty());
56 EXPECT_TRUE(rect.IsFinite());
57 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::IsFinite().

## ◆ TEST() [357/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectDirections |
| ) |  |

Definition at line 3030 of file rect_unittests.cc.

3030 {
3031 auto r = Rect::MakeLTRB(1, 2, 3, 4);
3032
3033 EXPECT_EQ(r.GetLeft(), 1);
3034 EXPECT_EQ(r.GetTop(), 2);
3035 EXPECT_EQ(r.GetRight(), 3);
3036 EXPECT_EQ(r.GetBottom(), 4);
3037
3038 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
3039 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
3040 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
3041 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
3042 }

References EXPECT_POINT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [358/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectDoesNotIntersectEmpty |
| ) |  |

Definition at line 809 of file rect_unittests.cc.

809 {
810 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
811
812 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
813 const std::string& label) {
814 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(l, b, r, t)))
815 << label << " with Top/Bottom swapped";
816 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, b, l, t)))
817 << label << " with Left/Right swapped";
818 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, t, l, b)))
819 << label << " with all sides swapped";
820 };
821
822 test(20, 20, 30, 30, "Above and Left");
823 test(70, 20, 80, 30, "Above");
824 test(120, 20, 130, 30, "Above and Right");
825 test(120, 70, 130, 80, "Right");
826 test(120, 120, 130, 130, "Below and Right");
827 test(70, 120, 80, 130, "Below");
828 test(20, 120, 30, 130, "Below and Left");
829 test(20, 70, 30, 80, "Left");
830
831 test(70, 70, 80, 80, "Inside");
832
833 test(40, 70, 60, 80, "Straddling Left");
834 test(70, 40, 80, 60, "Straddling Top");
835 test(90, 70, 110, 80, "Straddling Right");
836 test(70, 90, 80, 110, "Straddling Bottom");
837 }

References impeller::saturated::b, impeller::TRect< T >::IntersectsWithRect(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [359/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectEmptyDeclaration |
| ) |  |

Definition at line 14 of file rect_unittests.cc.

14 {
15 Rect rect;
16
17 EXPECT_EQ(rect.GetLeft(), 0.0f);
18 EXPECT_EQ(rect.GetTop(), 0.0f);
19 EXPECT_EQ(rect.GetRight(), 0.0f);
20 EXPECT_EQ(rect.GetBottom(), 0.0f);
21 EXPECT_EQ(rect.GetX(), 0.0f);
22 EXPECT_EQ(rect.GetY(), 0.0f);
23 EXPECT_EQ(rect.GetWidth(), 0.0f);
24 EXPECT_EQ(rect.GetHeight(), 0.0f);
25 EXPECT_TRUE(rect.IsEmpty());
26 EXPECT_TRUE(rect.IsFinite());
27 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::IsFinite().

## ◆ TEST() [360/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectExpand |
| ) |  |

Definition at line 1250 of file rect_unittests.cc.

1250 {
1251 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
1252
1253 // Expand(T amount)
1254 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
1255 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
1256
1257 // Expand(amount, amount)
1258 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
1259 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
1260 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
1261 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
1262
1263 // Expand(amount, amount, amount, amount)
1264 EXPECT_EQ(rect.Expand(10, 20, 30, 40), Rect::MakeLTRB(90, 80, 230, 240));
1265 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), Rect::MakeLTRB(110, 80, 230, 240));
1266 EXPECT_EQ(rect.Expand(10, -20, 30, 40), Rect::MakeLTRB(90, 120, 230, 240));
1267 EXPECT_EQ(rect.Expand(10, 20, -30, 40), Rect::MakeLTRB(90, 80, 170, 240));
1268 EXPECT_EQ(rect.Expand(10, 20, 30, -40), Rect::MakeLTRB(90, 80, 230, 160));
1269
1270 // Expand(Point amount)
1271 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1272 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1273 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1274 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1275
1276 // Expand(Size amount)
1277 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1278 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1279 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1280 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1281 }

References impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [361/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectFromIRect |
| ) |  |

Definition at line 164 of file rect_unittests.cc.

164 {
165 IRect irect = IRect::MakeLTRB(10, 20, 30, 40);
166 Rect rect = Rect::Make(irect);
167
168 EXPECT_EQ(rect.GetLeft(), 10);
169 EXPECT_EQ(rect.GetTop(), 20);
170 EXPECT_EQ(rect.GetRight(), 30);
171 EXPECT_EQ(rect.GetBottom(), 40);
172
173 // The following do not compile
174 // IRect irect2 = IRect::Make(rect);
175 // IRect irect2 = IRect::Make(irect);
176 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< Scalar >::Make(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [362/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectFromRect |
| ) |  |

Definition at line 654 of file rect_unittests.cc.

654 {
655 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
656 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
657 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
658 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
659 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [363/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectGetNormalizingTransform |
| ) |  |

Definition at line 1034 of file rect_unittests.cc.

1034 {
1035 {
1036 // Checks for expected matrix values
1037
1038 auto r = Rect::MakeXYWH(100, 200, 200, 400);
1039
1040 EXPECT_EQ(r.GetNormalizingTransform(),
1041 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1042 Matrix::MakeTranslation({-100, -200}));
1043 }
1044
1045 {
1046 // Checks for expected transform of points relative to the rect
1047
1048 auto r = Rect::MakeLTRB(300, 500, 400, 700);
1049 auto m = r.GetNormalizingTransform();
1050
1051 // The 4 corners of the rect => (0, 0) to (1, 1)
1052 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1053 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1054 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1055 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1056
1057 // The center => (0.5, 0.5)
1058 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1059
1060 // Outside the 4 corners => (-1, -1) to (2, 2)
1061 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1062 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1063 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1064 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1065 }
1066
1067 {
1068 // Checks for behavior with empty rects
1069
1070 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1071
1072 // Empty for width and/or height == 0
1073 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1074 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1075 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1076
1077 // Empty for width and/or height < 0
1078 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1079 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1080 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1081 }
1082
1083 {
1084 // Checks for behavior with non-finite rects
1085
1086 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
1087 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1088 auto inf = std::numeric_limits<Scalar>::infinity();
1089
1090 // Non-finite for width and/or height == nan
1091 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1092 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1093 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1094
1095 // Non-finite for width and/or height == inf
1096 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1097 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1098 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1099
1100 // Non-finite for width and/or height == -inf
1101 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1102 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1103 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1104
1105 // Non-finite for origin X and/or Y == nan
1106 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1107 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1108 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1109
1110 // Non-finite for origin X and/or Y == inf
1111 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1112 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1113 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1114
1115 // Non-finite for origin X and/or Y == -inf
1116 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1117 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1118 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1119 }
1120 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [364/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectGetPoints |
| ) |  |

Definition at line 2959 of file rect_unittests.cc.

2959 {
2960 {
2961 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2962 auto points = r.GetPoints();
2963 EXPECT_POINT_NEAR(points[0], Point(100, 200));
2964 EXPECT_POINT_NEAR(points[1], Point(400, 200));
2965 EXPECT_POINT_NEAR(points[2], Point(100, 600));
2966 EXPECT_POINT_NEAR(points[3], Point(400, 600));
2967 }
2968
2969 {
2970 Rect r = Rect::MakeMaximum();
2971 auto points = r.GetPoints();
2972 EXPECT_EQ(points[0], Point(std::numeric_limits<float>::lowest(),
2973 std::numeric_limits<float>::lowest()));
2974 EXPECT_EQ(points[1], Point(std::numeric_limits<float>::max(),
2975 std::numeric_limits<float>::lowest()));
2976 EXPECT_EQ(points[2], Point(std::numeric_limits<float>::lowest(),
2977 std::numeric_limits<float>::max()));
2978 EXPECT_EQ(points[3], Point(std::numeric_limits<float>::max(),
2979 std::numeric_limits<float>::max()));
2980 }
2981 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetPoints(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and points.

## ◆ TEST() [365/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectGetPositive |
| ) |  |

Definition at line 3016 of file rect_unittests.cc.

3016 {
3017 {
3018 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
3019 auto actual = r.GetPositive();
3020 EXPECT_RECT_NEAR(r, actual);
3021 }
3022 {
3023 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
3024 auto actual = r.GetPositive();
3025 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
3026 EXPECT_RECT_NEAR(expected, actual);
3027 }
3028 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::GetPositive(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [366/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectGetTransformedPoints |
| ) |  |

Definition at line 2990 of file rect_unittests.cc.

2990 {
2991 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2992 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2993 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2994 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2995 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2996 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2997 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and points.

## ◆ TEST() [367/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectIntersection |
| ) |  |

Definition at line 1617 of file rect_unittests.cc.

1617 {
1618 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1619 ASSERT_TRUE(a.IsFinite()) << label;
1620 ASSERT_TRUE(b.IsFinite()) << label;
1621
1622 for (int i = 1; i < 16; i++) {
1623 // NaN in a produces empty
1624 EXPECT_FALSE(swap_nan(a, i).Intersection(b).has_value())
1625 << label << ", index = " << i;
1626 // NaN in b produces empty
1627 EXPECT_FALSE(a.Intersection(swap_nan(b, i)).has_value())
1628 << label << ", index = " << i;
1629 // NaN in both is empty
1630 for (int j = 1; j < 16; j++) {
1631 EXPECT_FALSE(swap_nan(a, i).Intersection(swap_nan(b, j)).has_value())
1632 << label << ", indices = " << i << ", " << j;
1633 }
1634 }
1635 };
1636
1637 auto check_empty_flips = [](const Rect& a, const Rect& b,
1638 const std::string& label) {
1639 ASSERT_FALSE(a.IsEmpty());
1640 // b is allowed to be empty
1641
1642 // unflipped a vs flipped (empty) b yields a
1643 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1644 EXPECT_TRUE(a.IntersectionOrEmpty(flip_lr(b)).IsEmpty()) << label;
1645 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1646 EXPECT_TRUE(a.IntersectionOrEmpty(flip_tb(b)).IsEmpty()) << label;
1647 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1648 EXPECT_TRUE(a.IntersectionOrEmpty(flip_lrtb(b)).IsEmpty()) << label;
1649
1650 // flipped (empty) a vs unflipped b yields b
1651 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1652 EXPECT_TRUE(flip_lr(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1653 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1654 EXPECT_TRUE(flip_tb(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1655 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1656 EXPECT_TRUE(flip_lrtb(a).IntersectionOrEmpty(b).IsEmpty()) << label;
1657
1658 // flipped (empty) a vs flipped (empty) b yields empty
1659 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1660 EXPECT_TRUE(flip_lr(a).IntersectionOrEmpty(flip_lr(b)).IsEmpty()) << label;
1661 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1662 EXPECT_TRUE(flip_tb(a).IntersectionOrEmpty(flip_tb(b)).IsEmpty()) << label;
1663 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1664 EXPECT_TRUE(flip_lrtb(a).IntersectionOrEmpty(flip_lrtb(b)).IsEmpty())
1665 << label;
1666 };
1667
1668 auto test_non_empty = [&check_nans, &check_empty_flips](
1669 const Rect& a, const Rect& b, const Rect& result) {
1670 ASSERT_FALSE(a.IsEmpty()) << a;
1671 // b is allowed to be empty
1672
1673 std::stringstream stream;
1674 stream << a << " union " << b;
1675 auto label = stream.str();
1676
1677 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1678 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1679 EXPECT_EQ(a.Intersection(b), result) << label;
1680 EXPECT_EQ(b.Intersection(a), result) << label;
1681 check_empty_flips(a, b, label);
1682 check_nans(a, b, label);
1683 };
1684
1685 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1686 const Rect& b) {
1687 ASSERT_FALSE(a.IsEmpty()) << a;
1688 // b is allowed to be empty
1689
1690 std::stringstream stream;
1691 stream << a << " union " << b;
1692 auto label = stream.str();
1693
1694 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1695 EXPECT_TRUE(a.IntersectionOrEmpty(b).IsEmpty()) << label;
1696 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1697 EXPECT_TRUE(b.IntersectionOrEmpty(a).IsEmpty()) << label;
1698 check_empty_flips(a, b, label);
1699 check_nans(a, b, label);
1700 };
1701
1702 {
1703 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1704 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1705
1706 test_empty(a, b);
1707 }
1708
1709 {
1710 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1711 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1712
1713 test_empty(a, b);
1714 }
1715
1716 {
1717 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1718 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1719 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1720
1721 test_non_empty(a, b, expected);
1722 }
1723
1724 {
1725 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1726 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1727
1728 test_empty(a, b);
1729 }
1730
1731 {
1732 auto a = Rect::MakeMaximum();
1733 auto b = Rect::MakeXYWH(10, 10, 300, 300);
1734
1735 test_non_empty(a, b, b);
1736 }
1737
1738 {
1739 auto a = Rect::MakeMaximum();
1740 auto b = Rect::MakeMaximum();
1741
1742 test_non_empty(a, b, Rect::MakeMaximum());
1743 }
1744 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IntersectionOrEmpty(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [368/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectIntersectsWithRect |
| ) |  |

Definition at line 1951 of file rect_unittests.cc.

1951 {
1952 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1953 ASSERT_TRUE(a.IsFinite()) << label;
1954 ASSERT_TRUE(b.IsFinite()) << label;
1955
1956 for (int i = 1; i < 16; i++) {
1957 // NaN in a produces b
1958 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(b))
1959 << label << ", index = " << i;
1960 // NaN in b produces a
1961 EXPECT_FALSE(a.IntersectsWithRect(swap_nan(b, i)))
1962 << label << ", index = " << i;
1963 // NaN in both is empty
1964 for (int j = 1; j < 16; j++) {
1965 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(swap_nan(b, j)))
1966 << label << ", indices = " << i << ", " << j;
1967 }
1968 }
1969 };
1970
1971 auto check_empty_flips = [](const Rect& a, const Rect& b,
1972 const std::string& label) {
1973 ASSERT_FALSE(a.IsEmpty());
1974 // b is allowed to be empty
1975
1976 // unflipped a vs flipped (empty) b yields a
1977 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
1978 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
1979 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
1980
1981 // flipped (empty) a vs unflipped b yields b
1982 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
1983 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
1984 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
1985
1986 // flipped (empty) a vs flipped (empty) b yields empty
1987 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
1988 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
1989 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
1990 };
1991
1992 auto test_non_empty = [&check_nans, &check_empty_flips](const Rect& a,
1993 const Rect& b) {
1994 ASSERT_FALSE(a.IsEmpty()) << a;
1995 // b is allowed to be empty
1996
1997 std::stringstream stream;
1998 stream << a << " union " << b;
1999 auto label = stream.str();
2000
2001 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2002 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2003 check_empty_flips(a, b, label);
2004 check_nans(a, b, label);
2005 };
2006
2007 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
2008 const Rect& b) {
2009 ASSERT_FALSE(a.IsEmpty()) << a;
2010 // b is allowed to be empty
2011
2012 std::stringstream stream;
2013 stream << a << " union " << b;
2014 auto label = stream.str();
2015
2016 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2017 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2018 check_empty_flips(a, b, label);
2019 check_nans(a, b, label);
2020 };
2021
2022 {
2023 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2024 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2025
2026 test_empty(a, b);
2027 }
2028
2029 {
2030 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2031 auto b = Rect::MakeXYWH(10, 10, 0, 0);
2032
2033 test_empty(a, b);
2034 }
2035
2036 {
2037 auto a = Rect::MakeXYWH(0, 0, 100, 100);
2038 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2039
2040 test_non_empty(a, b);
2041 }
2042
2043 {
2044 auto a = Rect::MakeXYWH(0, 0, 100, 100);
2045 auto b = Rect::MakeXYWH(100, 100, 100, 100);
2046
2047 test_empty(a, b);
2048 }
2049
2050 {
2051 auto a = Rect::MakeMaximum();
2052 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2053
2054 test_non_empty(a, b);
2055 }
2056
2057 {
2058 auto a = Rect::MakeMaximum();
2059 auto b = Rect::MakeMaximum();
2060
2061 test_non_empty(a, b);
2062 }
2063 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IntersectsWithRect(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [369/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectMakeMaximum |
| ) |  |

Definition at line 620 of file rect_unittests.cc.

620 {
621 Rect rect = Rect::MakeMaximum();
622 auto inf = std::numeric_limits<Scalar>::infinity();
623 auto min = std::numeric_limits<Scalar>::lowest();
624 auto max = std::numeric_limits<Scalar>::max();
625
626 EXPECT_EQ(rect.GetLeft(), min);
627 EXPECT_EQ(rect.GetTop(), min);
628 EXPECT_EQ(rect.GetRight(), max);
629 EXPECT_EQ(rect.GetBottom(), max);
630 EXPECT_EQ(rect.GetX(), min);
631 EXPECT_EQ(rect.GetY(), min);
632 EXPECT_EQ(rect.GetWidth(), inf);
633 EXPECT_EQ(rect.GetHeight(), inf);
634 EXPECT_FALSE(rect.IsEmpty());
635 EXPECT_TRUE(rect.IsFinite());
636 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [370/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectMakePointBounds |
| ) |  |

Definition at line 2999 of file rect_unittests.cc.

2999 {
3000 {
3001 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
3002 auto r = Rect::MakePointBounds(points.begin(), points.end());
3003 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
3004 EXPECT_TRUE(r.has_value());
3005 if (r.has_value()) {
3006 EXPECT_RECT_NEAR(r.value(), expected);
3007 }
3008 }
3009 {
3010 std::vector<Point> points;
3011 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
3012 EXPECT_FALSE(r.has_value());
3013 }
3014 }

References EXPECT_RECT_NEAR, impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeXYWH(), and points.

## ◆ TEST() [371/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectMakeSize |
| ) |  |

Definition at line 590 of file rect_unittests.cc.

590 {
591 {
592 Size s(100, 200);
593 Rect r = Rect::MakeSize(s);
594 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
595 EXPECT_RECT_NEAR(r, expected);
596 }
597
598 {
599 ISize s(100, 200);
600 Rect r = Rect::MakeSize(s);
601 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
602 EXPECT_RECT_NEAR(r, expected);
603 }
604
605 {
606 Size s(100, 200);
607 IRect r = IRect::MakeSize(s);
608 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
609 EXPECT_EQ(r, expected);
610 }
611
612 {
613 ISize s(100, 200);
614 IRect r = IRect::MakeSize(s);
615 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
616 EXPECT_EQ(r, expected);
617 }
618 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::MakeSize(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST() [372/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOriginSizeXYWHGetters |
| ) |  |

Definition at line 702 of file rect_unittests.cc.

702 {
703 {
704 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
705 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
706 EXPECT_EQ(r.GetSize(), Size(50, 40));
707 EXPECT_EQ(r.GetX(), 10);
708 EXPECT_EQ(r.GetY(), 20);
709 EXPECT_EQ(r.GetWidth(), 50);
710 EXPECT_EQ(r.GetHeight(), 40);
711 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
712 EXPECT_EQ(r.GetXYWH(), expected_array);
713 }
714
715 {
716 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
717 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
718 EXPECT_EQ(r.GetSize(), Size(40, 20));
719 EXPECT_EQ(r.GetX(), 10);
720 EXPECT_EQ(r.GetY(), 20);
721 EXPECT_EQ(r.GetWidth(), 40);
722 EXPECT_EQ(r.GetHeight(), 20);
723 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
724 EXPECT_EQ(r.GetXYWH(), expected_array);
725 }
726 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetXYWH(), impeller::TRect< T >::GetY(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeOriginSize().

## ◆ TEST() [373/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOverflowLTRB |
| ) |  |

Definition at line 384 of file rect_unittests.cc.

384 {
385 auto min = std::numeric_limits<Scalar>::lowest();
386 auto max = std::numeric_limits<Scalar>::max();
387 auto inf = std::numeric_limits<Scalar>::infinity();
388
389 // 8 cases:
390 // finite negative X, max W
391 // ~min X, ~max W
392 // finite negative Y, max H
393 // ~min Y, ~max H
394 // finite positive X, min W
395 // ~min X, ~min W
396 // finite positive Y, min H
397 // ~min Y, ~min H
398
399 // a small finite value subtracted from a max value will remain max
400 // a very large finite value (like min) subtracted from max will go to inf
401
402 {
403 Rect rect = Rect::MakeLTRB(-5.0f, 10.0f, max, 25.0f);
404
405 EXPECT_EQ(rect.GetLeft(), -5.0f);
406 EXPECT_EQ(rect.GetTop(), 10.0f);
407 EXPECT_EQ(rect.GetRight(), max);
408 EXPECT_EQ(rect.GetBottom(), 25.0f);
409 EXPECT_EQ(rect.GetX(), -5.0f);
410 EXPECT_EQ(rect.GetY(), 10.0f);
411 EXPECT_EQ(rect.GetWidth(), max);
412 EXPECT_EQ(rect.GetHeight(), 15.0f);
413 EXPECT_FALSE(rect.IsEmpty());
414 EXPECT_TRUE(rect.IsFinite());
415 }
416
417 {
418 Rect rect = Rect::MakeLTRB(min + 5.0f, 10.0f, max - 5.0f, 25.0f);
419
420 EXPECT_EQ(rect.GetLeft(), min + 5.0f);
421 EXPECT_EQ(rect.GetTop(), 10.0f);
422 EXPECT_EQ(rect.GetRight(), max - 5.0f);
423 EXPECT_EQ(rect.GetBottom(), 25.0f);
424 EXPECT_EQ(rect.GetX(), min + 5.0f);
425 EXPECT_EQ(rect.GetY(), 10.0f);
426 EXPECT_EQ(rect.GetWidth(), inf);
427 EXPECT_EQ(rect.GetHeight(), 15.0f);
428 EXPECT_FALSE(rect.IsEmpty());
429 EXPECT_TRUE(rect.IsFinite());
430 }
431
432 {
433 Rect rect = Rect::MakeLTRB(5.0f, -10.0f, 20.0f, max);
434
435 EXPECT_EQ(rect.GetLeft(), 5.0f);
436 EXPECT_EQ(rect.GetTop(), -10.0f);
437 EXPECT_EQ(rect.GetRight(), 20.0f);
438 EXPECT_EQ(rect.GetBottom(), max);
439 EXPECT_EQ(rect.GetX(), 5.0f);
440 EXPECT_EQ(rect.GetY(), -10.0f);
441 EXPECT_EQ(rect.GetWidth(), 15.0f);
442 EXPECT_EQ(rect.GetHeight(), max);
443 EXPECT_FALSE(rect.IsEmpty());
444 EXPECT_TRUE(rect.IsFinite());
445 }
446
447 {
448 Rect rect = Rect::MakeLTRB(5.0f, min + 10.0f, 20.0f, max - 15.0f);
449
450 EXPECT_EQ(rect.GetLeft(), 5.0f);
451 EXPECT_EQ(rect.GetTop(), min + 10.0f);
452 EXPECT_EQ(rect.GetRight(), 20.0f);
453 EXPECT_EQ(rect.GetBottom(), max - 15.0f);
454 EXPECT_EQ(rect.GetX(), 5.0f);
455 EXPECT_EQ(rect.GetY(), min + 10.0f);
456 EXPECT_EQ(rect.GetWidth(), 15.0f);
457 EXPECT_EQ(rect.GetHeight(), inf);
458 EXPECT_FALSE(rect.IsEmpty());
459 EXPECT_TRUE(rect.IsFinite());
460 }
461
462 {
463 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, min, 25.0f);
464
465 EXPECT_EQ(rect.GetLeft(), 5.0f);
466 EXPECT_EQ(rect.GetTop(), 10.0f);
467 EXPECT_EQ(rect.GetRight(), min);
468 EXPECT_EQ(rect.GetBottom(), 25.0f);
469 EXPECT_EQ(rect.GetX(), 5.0f);
470 EXPECT_EQ(rect.GetY(), 10.0f);
471 EXPECT_EQ(rect.GetWidth(), min);
472 EXPECT_EQ(rect.GetHeight(), 15.0f);
473 EXPECT_TRUE(rect.IsEmpty());
474 EXPECT_TRUE(rect.IsFinite());
475 }
476
477 {
478 Rect rect = Rect::MakeLTRB(max - 5.0f, 10.0f, min + 10.0f, 25.0f);
479
480 EXPECT_EQ(rect.GetLeft(), max - 5.0f);
481 EXPECT_EQ(rect.GetTop(), 10.0f);
482 EXPECT_EQ(rect.GetRight(), min + 10.0f);
483 EXPECT_EQ(rect.GetBottom(), 25.0f);
484 EXPECT_EQ(rect.GetX(), max - 5.0f);
485 EXPECT_EQ(rect.GetY(), 10.0f);
486 EXPECT_EQ(rect.GetWidth(), -inf);
487 EXPECT_EQ(rect.GetHeight(), 15.0f);
488 EXPECT_TRUE(rect.IsEmpty());
489 EXPECT_TRUE(rect.IsFinite());
490 }
491
492 {
493 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, 20.0f, min);
494
495 EXPECT_EQ(rect.GetLeft(), 5.0f);
496 EXPECT_EQ(rect.GetTop(), 10.0f);
497 EXPECT_EQ(rect.GetRight(), 20.0f);
498 EXPECT_EQ(rect.GetBottom(), min);
499 EXPECT_EQ(rect.GetX(), 5.0f);
500 EXPECT_EQ(rect.GetY(), 10.0f);
501 EXPECT_EQ(rect.GetWidth(), 15.0f);
502 EXPECT_EQ(rect.GetHeight(), min);
503 EXPECT_TRUE(rect.IsEmpty());
504 EXPECT_TRUE(rect.IsFinite());
505 }
506
507 {
508 Rect rect = Rect::MakeLTRB(5.0f, max - 5.0f, 20.0f, min + 10.0f);
509
510 EXPECT_EQ(rect.GetLeft(), 5.0f);
511 EXPECT_EQ(rect.GetTop(), max - 5.0f);
512 EXPECT_EQ(rect.GetRight(), 20.0f);
513 EXPECT_EQ(rect.GetBottom(), min + 10.0f);
514 EXPECT_EQ(rect.GetX(), 5.0f);
515 EXPECT_EQ(rect.GetY(), max - 5.0f);
516 EXPECT_EQ(rect.GetWidth(), 15.0f);
517 EXPECT_EQ(rect.GetHeight(), -inf);
518 EXPECT_TRUE(rect.IsEmpty());
519 EXPECT_TRUE(rect.IsFinite());
520 }
521 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [374/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOverflowXYWH |
| ) |  |

Definition at line 178 of file rect_unittests.cc.

178 {
179 auto min = std::numeric_limits<Scalar>::lowest();
180 auto max = std::numeric_limits<Scalar>::max();
181 auto inf = std::numeric_limits<Scalar>::infinity();
182
183 // 8 cases:
184 // finite X, max W
185 // max X, max W
186 // finite Y, max H
187 // max Y, max H
188 // finite X, min W
189 // min X, min W
190 // finite Y, min H
191 // min Y, min H
192
193 // a small finite value added to a max value will remain max
194 // a very large finite value (like max) added to max will go to infinity
195
196 {
197 Rect rect = Rect::MakeXYWH(5.0, 10.0f, max, 15.0f);
198
199 EXPECT_EQ(rect.GetLeft(), 5.0f);
200 EXPECT_EQ(rect.GetTop(), 10.0f);
201 EXPECT_EQ(rect.GetRight(), max);
202 EXPECT_EQ(rect.GetBottom(), 25.0f);
203 EXPECT_EQ(rect.GetX(), 5.0f);
204 EXPECT_EQ(rect.GetY(), 10.0f);
205 EXPECT_EQ(rect.GetWidth(), max);
206 EXPECT_EQ(rect.GetHeight(), 15.0f);
207 EXPECT_FALSE(rect.IsEmpty());
208 EXPECT_TRUE(rect.IsFinite());
209 }
210
211 {
212 Rect rect = Rect::MakeXYWH(max, 10.0f, max, 15.0f);
213
214 EXPECT_EQ(rect.GetLeft(), max);
215 EXPECT_EQ(rect.GetTop(), 10.0f);
216 EXPECT_EQ(rect.GetRight(), inf);
217 EXPECT_EQ(rect.GetBottom(), 25.0f);
218 EXPECT_EQ(rect.GetX(), max);
219 EXPECT_EQ(rect.GetY(), 10.0f);
220 EXPECT_EQ(rect.GetWidth(), inf);
221 EXPECT_EQ(rect.GetHeight(), 15.0f);
222 EXPECT_FALSE(rect.IsEmpty());
223 EXPECT_FALSE(rect.IsFinite());
224 }
225
226 {
227 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, max);
228
229 EXPECT_EQ(rect.GetLeft(), 5.0f);
230 EXPECT_EQ(rect.GetTop(), 10.0f);
231 EXPECT_EQ(rect.GetRight(), 25.0f);
232 EXPECT_EQ(rect.GetBottom(), max);
233 EXPECT_EQ(rect.GetX(), 5.0f);
234 EXPECT_EQ(rect.GetY(), 10.0f);
235 EXPECT_EQ(rect.GetWidth(), 20.0f);
236 EXPECT_EQ(rect.GetHeight(), max);
237 EXPECT_FALSE(rect.IsEmpty());
238 EXPECT_TRUE(rect.IsFinite());
239 }
240
241 {
242 Rect rect = Rect::MakeXYWH(5.0f, max, 20.0f, max);
243
244 EXPECT_EQ(rect.GetLeft(), 5.0f);
245 EXPECT_EQ(rect.GetTop(), max);
246 EXPECT_EQ(rect.GetRight(), 25.0f);
247 EXPECT_EQ(rect.GetBottom(), inf);
248 EXPECT_EQ(rect.GetX(), 5.0f);
249 EXPECT_EQ(rect.GetY(), max);
250 EXPECT_EQ(rect.GetWidth(), 20.0f);
251 EXPECT_EQ(rect.GetHeight(), inf);
252 EXPECT_FALSE(rect.IsEmpty());
253 EXPECT_FALSE(rect.IsFinite());
254 }
255
256 {
257 Rect rect = Rect::MakeXYWH(5.0, 10.0f, min, 15.0f);
258
259 EXPECT_EQ(rect.GetLeft(), 5.0f);
260 EXPECT_EQ(rect.GetTop(), 10.0f);
261 EXPECT_EQ(rect.GetRight(), min);
262 EXPECT_EQ(rect.GetBottom(), 25.0f);
263 EXPECT_EQ(rect.GetX(), 5.0f);
264 EXPECT_EQ(rect.GetY(), 10.0f);
265 EXPECT_EQ(rect.GetWidth(), min);
266 EXPECT_EQ(rect.GetHeight(), 15.0f);
267 EXPECT_TRUE(rect.IsEmpty());
268 EXPECT_TRUE(rect.IsFinite());
269 }
270
271 {
272 Rect rect = Rect::MakeXYWH(min, 10.0f, min, 15.0f);
273
274 EXPECT_EQ(rect.GetLeft(), min);
275 EXPECT_EQ(rect.GetTop(), 10.0f);
276 EXPECT_EQ(rect.GetRight(), -inf);
277 EXPECT_EQ(rect.GetBottom(), 25.0f);
278 EXPECT_EQ(rect.GetX(), min);
279 EXPECT_EQ(rect.GetY(), 10.0f);
280 EXPECT_EQ(rect.GetWidth(), -inf);
281 EXPECT_EQ(rect.GetHeight(), 15.0f);
282 EXPECT_TRUE(rect.IsEmpty());
283 EXPECT_FALSE(rect.IsFinite());
284 }
285
286 {
287 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, min);
288
289 EXPECT_EQ(rect.GetLeft(), 5.0f);
290 EXPECT_EQ(rect.GetTop(), 10.0f);
291 EXPECT_EQ(rect.GetRight(), 25.0f);
292 EXPECT_EQ(rect.GetBottom(), min);
293 EXPECT_EQ(rect.GetX(), 5.0f);
294 EXPECT_EQ(rect.GetY(), 10.0f);
295 EXPECT_EQ(rect.GetWidth(), 20.0f);
296 EXPECT_EQ(rect.GetHeight(), min);
297 EXPECT_TRUE(rect.IsEmpty());
298 EXPECT_TRUE(rect.IsFinite());
299 }
300
301 {
302 Rect rect = Rect::MakeXYWH(5.0f, min, 20.0f, min);
303
304 EXPECT_EQ(rect.GetLeft(), 5.0f);
305 EXPECT_EQ(rect.GetTop(), min);
306 EXPECT_EQ(rect.GetRight(), 25.0f);
307 EXPECT_EQ(rect.GetBottom(), -inf);
308 EXPECT_EQ(rect.GetX(), 5.0f);
309 EXPECT_EQ(rect.GetY(), min);
310 EXPECT_EQ(rect.GetWidth(), 20.0f);
311 EXPECT_EQ(rect.GetHeight(), -inf);
312 EXPECT_TRUE(rect.IsEmpty());
313 EXPECT_FALSE(rect.IsFinite());
314 }
315 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [375/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectProject |
| ) |  |

Definition at line 3044 of file rect_unittests.cc.

3044 {
3045 {
3046 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3047 auto actual = r.Project(r);
3048 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
3049 EXPECT_RECT_NEAR(expected, actual);
3050 }
3051 {
3052 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3053 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
3054 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
3055 EXPECT_RECT_NEAR(expected, actual);
3056 }
3057 }

References EXPECT_RECT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [376/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRound |
| ) |  |

Definition at line 3083 of file rect_unittests.cc.

3083 {
3084 {
3085 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3086 EXPECT_EQ(Rect::Round(r), r);
3087 }
3088 {
3089 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3090 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-100, -200, 300, 400));
3091 }
3092 {
3093 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3094 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-101, -201, 301, 401));
3095 }
3096 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::Round().

## ◆ TEST() [377/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOut |
| ) |  |

Definition at line 3059 of file rect_unittests.cc.

3059 {
3060 {
3061 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3062 EXPECT_EQ(Rect::RoundOut(r), r);
3063 }
3064 {
3065 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3066 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -201, 301, 401));
3067 }
3068 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::RoundOut().

## ◆ TEST() [378/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutEmpty |
| ) |  |

Definition at line 754 of file rect_unittests.cc.

754 {
755 Rect rect;
756
757 EXPECT_EQ(Rect::RoundOut(rect), Rect());
758
759 EXPECT_EQ(IRect::RoundOut(rect), IRect());
760 }

References impeller::TRect< T >::RoundOut(), and impeller::TRect< Scalar >::RoundOut().

## ◆ TEST() [379/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutSimple |
| ) |  |

Definition at line 762 of file rect_unittests.cc.

762 {
763 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
764
765 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
766
767 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
768 }

References impeller::TRect< T >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::RoundOut(), and impeller::TRect< Scalar >::RoundOut().

## ◆ TEST() [380/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutToIRectHuge |
| ) |  |

Definition at line 770 of file rect_unittests.cc.

770 {
771 auto test = [](int corners) {
772 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
773 Scalar l, t, r, b;
774 int64_t il, it, ir, ib;
775 l = il = 50;
776 t = it = 50;
777 r = ir = 80;
778 b = ib = 80;
779 if ((corners & (1 << 0)) != 0) {
780 l = -1E20;
781 il = std::numeric_limits<int64_t>::min();
782 }
783 if ((corners & (1 << 1)) != 0) {
784 t = -1E20;
785 it = std::numeric_limits<int64_t>::min();
786 }
787 if ((corners & (1 << 2)) != 0) {
788 r = +1E20;
789 ir = std::numeric_limits<int64_t>::max();
790 }
791 if ((corners & (1 << 3)) != 0) {
792 b = +1E20;
793 ib = std::numeric_limits<int64_t>::max();
794 }
795
796 Rect rect = Rect::MakeLTRB(l, t, r, b);
797 IRect irect = IRect::RoundOut(rect);
798 EXPECT_EQ(irect.GetLeft(), il) << corners;
799 EXPECT_EQ(irect.GetTop(), it) << corners;
800 EXPECT_EQ(irect.GetRight(), ir) << corners;
801 EXPECT_EQ(irect.GetBottom(), ib) << corners;
802 };
803
804 for (int corners = 0; corners <= 15; corners++) {
805 test(corners);
806 }
807 }

References impeller::saturated::b, impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::RoundOut().

## ◆ TEST() [381/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectScale |
| ) |  |

Definition at line 929 of file rect_unittests.cc.

929 {
930 auto test1 = [](Rect rect, Scalar scale) {
931 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
932 rect.GetY() * scale, //
933 rect.GetWidth() * scale, //
934 rect.GetHeight() * scale);
935
936 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
937 << rect << " * " << scale;
938 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
939 << rect << " * " << scale;
940 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
941 << rect << " * " << scale;
942 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
943 << rect << " * " << scale;
944 };
945
946 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
947 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
948 rect.GetY() * scale_y, //
949 rect.GetWidth() * scale_x, //
950 rect.GetHeight() * scale_y);
951
952 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
953 << rect << " * " << scale_x << ", " << scale_y;
954 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
955 << rect << " * " << scale_x << ", " << scale_y;
956 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
957 << rect << " * " << scale_x << ", " << scale_y;
958
959 test1(rect, scale_x);
960 test1(rect, scale_y);
961 };
962
963 test2(Rect::MakeLTRB(10, 15, 100, 150), 1.0, 0.0);
964 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 1.0);
965 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 0.0);
966 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
967 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
968 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
969 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
970 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
971 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
972 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::TRect< T >::Scale().

## ◆ TEST() [382/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectShift |
| ) |  |

Definition at line 2983 of file rect_unittests.cc.

2983 {
2984 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2985
2986 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2987 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2988 }

References impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [383/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectSimpleLTRB |
| ) |  |

Definition at line 73 of file rect_unittests.cc.

73 {
74 // Using fractional-power-of-2 friendly values for equality tests
75 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
76
77 EXPECT_EQ(rect.GetLeft(), 5.125f);
78 EXPECT_EQ(rect.GetTop(), 10.25f);
79 EXPECT_EQ(rect.GetRight(), 20.625f);
80 EXPECT_EQ(rect.GetBottom(), 25.375f);
81 EXPECT_EQ(rect.GetX(), 5.125f);
82 EXPECT_EQ(rect.GetY(), 10.25f);
83 EXPECT_EQ(rect.GetWidth(), 15.5f);
84 EXPECT_EQ(rect.GetHeight(), 15.125f);
85 EXPECT_FALSE(rect.IsEmpty());
86 EXPECT_TRUE(rect.IsFinite());
87 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [384/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectSimpleWH |
| ) |  |

Definition at line 133 of file rect_unittests.cc.

133 {
134 // Using fractional-power-of-2 friendly values for equality tests
135 Rect rect = Rect::MakeWH(15.5f, 15.125f);
136
137 EXPECT_EQ(rect.GetLeft(), 0.0f);
138 EXPECT_EQ(rect.GetTop(), 0.0f);
139 EXPECT_EQ(rect.GetRight(), 15.5f);
140 EXPECT_EQ(rect.GetBottom(), 15.125f);
141 EXPECT_EQ(rect.GetX(), 0.0f);
142 EXPECT_EQ(rect.GetY(), 0.0f);
143 EXPECT_EQ(rect.GetWidth(), 15.5f);
144 EXPECT_EQ(rect.GetHeight(), 15.125f);
145 EXPECT_FALSE(rect.IsEmpty());
146 EXPECT_TRUE(rect.IsFinite());
147 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeWH().

## ◆ TEST() [385/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectSimpleXYWH |
| ) |  |

Definition at line 103 of file rect_unittests.cc.

103 {
104 // Using fractional-power-of-2 friendly values for equality tests
105 Rect rect = Rect::MakeXYWH(5.125f, 10.25f, 15.5f, 15.125f);
106
107 EXPECT_EQ(rect.GetLeft(), 5.125f);
108 EXPECT_EQ(rect.GetTop(), 10.25f);
109 EXPECT_EQ(rect.GetRight(), 20.625f);
110 EXPECT_EQ(rect.GetBottom(), 25.375f);
111 EXPECT_EQ(rect.GetX(), 5.125f);
112 EXPECT_EQ(rect.GetY(), 10.25f);
113 EXPECT_EQ(rect.GetWidth(), 15.5f);
114 EXPECT_EQ(rect.GetHeight(), 15.125f);
115 EXPECT_FALSE(rect.IsEmpty());
116 EXPECT_TRUE(rect.IsFinite());
117 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [386/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectUnion |
| ) |  |

Definition at line 1358 of file rect_unittests.cc.

1358 {
1359 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1360 ASSERT_TRUE(a.IsFinite()) << label;
1361 ASSERT_TRUE(b.IsFinite()) << label;
1362 ASSERT_FALSE(a.Union(b).IsEmpty());
1363
1364 for (int i = 1; i < 16; i++) {
1365 // NaN in a produces b
1366 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1367 // NaN in b produces a
1368 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1369 // NaN in both is empty
1370 for (int j = 1; j < 16; j++) {
1371 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1372 << label << ", indices = " << i << ", " << j;
1373 }
1374 }
1375 };
1376
1377 auto check_empty_flips = [](const Rect& a, const Rect& b,
1378 const std::string& label) {
1379 ASSERT_FALSE(a.IsEmpty());
1380 // b is allowed to be empty
1381
1382 // unflipped a vs flipped (empty) b yields a
1383 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1384 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1385 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1386
1387 // flipped (empty) a vs unflipped b yields b
1388 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1389 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1390 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1391
1392 // flipped (empty) a vs flipped (empty) b yields empty
1393 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1394 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1395 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1396 };
1397
1398 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1399 const Rect& result) {
1400 ASSERT_FALSE(a.IsEmpty()) << a;
1401 // b is allowed to be empty
1402
1403 std::stringstream stream;
1404 stream << a << " union " << b;
1405 auto label = stream.str();
1406
1407 EXPECT_EQ(a.Union(b), result) << label;
1408 EXPECT_EQ(b.Union(a), result) << label;
1409 check_empty_flips(a, b, label);
1410 check_nans(a, b, label);
1411 };
1412
1413 {
1414 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1415 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1416 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1417 test(a, b, expected);
1418 }
1419
1420 {
1421 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1422 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1423 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1424 test(a, b, expected);
1425 }
1426
1427 {
1428 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1429 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1430 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1431 test(a, b, expected);
1432 }
1433
1434 {
1435 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1436 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1437 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1438 test(a, b, expected);
1439 }
1440
1441 {
1442 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1443 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1444 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1445 test(a, b, expected);
1446 }
1447 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeXYWH(), swap_nan(), and impeller::TRect< T >::Union().

## ◆ TEST() [387/574]

impeller::testing::TEST | ( | RectTest | ,
|  | RectXYWHIsEmpty |
| ) |  |

Definition at line 1172 of file rect_unittests.cc.

1172 {
1173 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1174
1175 // Non-empty
1176 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1177
1178 // Empty both width and height both 0 or negative, in all combinations
1179 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1180 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1181 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1182 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1183
1184 // Empty for 0 or negative width or height (but not both at the same time)
1185 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1186 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1187 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1188 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1189
1190 // Empty for NaN in width or height or both
1191 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1192 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1193 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1194 }

References impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [388/574]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBoundsAllFourCornersClipped |
| ) |  |

Definition at line 3318 of file rect_unittests.cc.

3318 {
3319 // This matrix should clip all four corners.
3320 auto matrix = impeller::Matrix::MakeColumn(
3321 // clang-format off
3322 2.0f, 0.0f, 0.0f, -.025f,
3323 0.0f, 2.0f, 0.0f, -.006f,
3324 0.0f, 0.0f, 1.0f, 0.0f,
3325 0.0f, 0.0f, 0.0f, 3.0f
3326 // clang-format on
3327 );
3328 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3329
3330 // All of these should have a W<0
3331 //
3332 // When W<0 we interpolate the point back towards the adjacent points
3333 // that have W>0 to a location just greater than the W=0 half-plane.
3334 // We interpolate them to W=epsilon where epsilon == 2^-14.
3335
3336 // In this case, none of the homogenous results are in bounds (W > 0)
3337 // so we can perform no interpolation - the operation is not visible.
3338
3339 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3340 Vector3(200.0f, 200.0f, -0.1f));
3341 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3342 Vector3(400.0f, 200.0f, -2.6f));
3343 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3344 Vector3(200.0f, 400.0f, -0.7f));
3345 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3346 Vector3(400.0f, 400.0f, -3.2f));
3347
3348 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3349 }
impeller::Matrix::MakeColumn
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:69

References EXPECT_VECTOR3_NEAR, impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [389/574]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBoundsNoCornersClipped |
| ) |  |

Definition at line 3116 of file rect_unittests.cc.

3116 {
3117 // This matrix should clip no corners.
3118 auto matrix = impeller::Matrix::MakeColumn(
3119 // clang-format off
3120 2.0f, 0.0f, 0.0f, 0.0f,
3121 0.0f, 4.0f, 0.0f, 0.0f,
3122 0.0f, 0.0f, 1.0f, 0.0f,
3123 0.0f, 0.0f, 0.0f, 8.0f
3124 // clang-format on
3125 );
3126 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3127
3128 // None of these should have a W<0
3129
3130 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
3131 Vector3(200.0f, 400.0f, 8.0f));
3132 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
3133 Vector3(400.0f, 400.0f, 8.0f));
3134 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
3135 Vector3(200.0f, 800.0f, 8.0f));
3136 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
3137 Vector3(400.0f, 800.0f, 8.0f));
3138
3139 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
3140 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3141 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
3142 }

References impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [390/574]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBoundsOneCornerClipped |
| ) |  |

Definition at line 3144 of file rect_unittests.cc.

3144 {
3145 // This matrix should clip one corner.
3146 auto matrix = impeller::Matrix::MakeColumn(
3147 // clang-format off
3148 2.0f, 0.0f, 0.0f, -0.01f,
3149 0.0f, 2.0f, 0.0f, -0.006f,
3150 0.0f, 0.0f, 1.0f, 0.0f,
3151 0.0f, 0.0f, 0.0f, 3.0f
3152 // clang-format on
3153 );
3154 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3155
3156 // Exactly one of these should have a W<0
3157 //
3158 // When W<0 we interpolate the point back towards the adjacent points
3159 // that have W>0 to a location just greater than the W=0 half-plane.
3160 // We interpolate them to W=epsilon where epsilon == 2^-14.
3161
3162 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3163 Vector3(200.0f, 200.0f, 1.4f));
3164 // Contributes (200, 200) / 1.4 == (142.85714, 142.85714)
3165
3166 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3167 Vector3(400.0f, 200.0f, 0.4f));
3168 // Contributes (400, 200) / 0.4 == (1000, 500)
3169
3170 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3171 Vector3(200.0f, 400.0f, 0.8f));
3172 // Contributes (200, 400) / 0.8 == (250, 500)
3173
3174 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3175 Vector3(400.0f, 400.0f, -0.2f));
3176 // Interpolates at epsilon against RightTop to produce:
3177 // t = (epsilon - -.2) / (.4 - -.2)
3178 // = (epsilon + .2) / .6
3179 // = 0.333435
3180 // Lerp(RightBottom, RightTop, 0.333435) = (400, 333.313, epsilon)
3181 // = (6553600, 5461000)
3182 //
3183 // It also interpolates at epsilon against LeftBottom to produce:
3184 // t = (epsilon - -.2) / (.8 - -.2)
3185 // = (epsilon + .2) / 1
3186 // = 0.200061
3187 // Lerp(RightBottom, LeftBottom, 0.200061) = (359.988, 400, epsilon)
3188 // = (5898040, 6553600)
3189
3190 // Min/Max X and Y of all the points generated above are:
3191 // Min X == 142.85714
3192 // Min Y == 142.85714
3193 // Max X == 6553600
3194 // Max Y == 6553600
3195
3196 Rect expect = Rect::MakeLTRB(142.85714f, 142.85714f, 6553600.f, 6553600.f);
3197 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3198 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3199 }

References EXPECT_RECT_NEAR, EXPECT_VECTOR3_NEAR, impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [391/574]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBoundsThreeCornersClipped |
| ) |  |

Definition at line 3259 of file rect_unittests.cc.

3259 {
3260 // This matrix should clip three corners.
3261 auto matrix = impeller::Matrix::MakeColumn(
3262 // clang-format off
3263 2.0f, 0.0f, 0.0f, -.02f,
3264 0.0f, 2.0f, 0.0f, -.006f,
3265 0.0f, 0.0f, 1.0f, 0.0f,
3266 0.0f, 0.0f, 0.0f, 3.0f
3267 // clang-format on
3268 );
3269 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3270
3271 // Exactly three of these homogenous results should have a W<0
3272 //
3273 // When W<0 we interpolate the point back towards the adjacent points
3274 // that have W>0 to a location just greater than the W=0 half-plane.
3275 // We interpolate them to W=epsilon where epsilon == 2^-14.
3276
3277 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3278 Vector3(200.0f, 200.0f, 0.4f));
3279 // Contributes (200, 200) / 0.4 == (500, 500) to bounds
3280
3281 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3282 Vector3(400.0f, 200.0f, -1.6f));
3283 // Interpolates at epsilon against LeftTop to produce:
3284 // t = (epsilon - -1.6) / (.4 - -1.6)
3285 // = (epsilon + 1.6) / 2
3286 // = 0.8000305
3287 // Lerp(RightTop, LeftTop, 0.8000305) = (239.9939, 200, epsilon)
3288 // = (3932060, 3276800)
3289 // Cannot interpolate against RightBottom because it also has W<0
3290
3291 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3292 Vector3(200.0f, 400.0f, -0.2f));
3293 // Interpolates against LeftTop to produce:
3294 // t = (epsilon - -.2) / (.4 - -.2)
3295 // = (epsilon + .2) / .6
3296 // = 0.333435
3297 // Lerp(LeftBottom, LeftTop, .333435) = (200, 333.31299, epsilon)
3298 // = (3276800, 5461000)
3299 // Cannot interpolate against RightBottom because it also has W<0
3300
3301 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3302 Vector3(400.0f, 400.0f, -2.2f));
3303 // Cannot interpolate against either RightTop or LeftBottom because
3304 // both of those adjacent points transformed to a W<0 homogenous point.
3305
3306 // Min/Max X and Y of all the points generated above are:
3307 // Min X == 500
3308 // Min Y == 500
3309 // Max X == 3932060
3310 // Max Y == 5461000
3311
3312 Rect expect = Rect::MakeLTRB(500.0f, 500.0f, 3932060.f, 5461000.f);
3313
3314 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3315 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3316 }

References EXPECT_RECT_NEAR, EXPECT_VECTOR3_NEAR, impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [392/574]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBoundsTwoCornersClipped |
| ) |  |

Definition at line 3201 of file rect_unittests.cc.

3201 {
3202 // This matrix should clip two corners.
3203 auto matrix = impeller::Matrix::MakeColumn(
3204 // clang-format off
3205 2.0f, 0.0f, 0.0f, -.015f,
3206 0.0f, 2.0f, 0.0f, -.006f,
3207 0.0f, 0.0f, 1.0f, 0.0f,
3208 0.0f, 0.0f, 0.0f, 3.0f
3209 // clang-format on
3210 );
3211 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3212
3213 // Exactly two of these homogenous results should have a W<0
3214 //
3215 // When W<0 we interpolate the point back towards the adjacent points
3216 // that have W>0 to a location just greater than the W=0 half-plane.
3217 // We interpolate them to W=epsilon where epsilon == 2^-14.
3218
3219 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3220 Vector3(200.0f, 200.0f, 0.9f));
3221 // Contributes (200, 200) / 0.9 == (222.2222, 222.2222) to bounds
3222
3223 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3224 Vector3(400.0f, 200.0f, -0.6f));
3225 // Interpolates at epsilon against LeftTop to produce:
3226 // t = (epsilon - -.6) / (.9 - -.6)
3227 // = (epsilon + .6) / 1.5
3228 // = 0.4000407
3229 // Lerp(RightTop, LeftTop, 0.4000407) = (319.9919, 200, epsilon)
3230 // = (5242747, 3276800)
3231 // Cannot interpolate against RightBottom because it also has W<0
3232
3233 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3234 Vector3(200.0f, 400.0f, 0.3f));
3235 // Contributes (200, 400) / 0.3 == (666.6667, 1333.3333) to bounds
3236
3237 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3238 Vector3(400.0f, 400.0f, -1.2f));
3239 // Interpolates at epsilon against LeftBottom to produce:
3240 // t = (epsilon - -1.2) / (.3 - -1.2)
3241 // = (epsilon + 1.2) / 1.5
3242 // = 0.8000407
3243 // Lerp(RightBottom, LeftBottom, 0.8000407) = (239.9919, 400, epsilon)
3244 // = (3932026.667, 6553600)
3245 // Cannot interpolate against RightTop because it also has W<0
3246
3247 // Min/Max X and Y of all the points generated above are:
3248 // Min X == 222.2222
3249 // Min Y == 222.2222
3250 // Max X == 5242747
3251 // Max Y == 6553600
3252
3253 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5242747.f, 6553600.f);
3254
3255 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3256 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3257 }

References EXPECT_RECT_NEAR, EXPECT_VECTOR3_NEAR, impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [393/574]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesMSAAResolveWithCorrectStore |
| ) |  |

Definition at line 133 of file render_pass_builder_vk_unittests.cc.

133 {
134 RenderPassBuilderVK builder = RenderPassBuilderVK();
135 auto const context = MockVulkanContextBuilder().Build();
136
137 // Create an MSAA color attachment.
138 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
139 SampleCount::kCount4, LoadAction::kClear,
140 StoreAction::kMultisampleResolve);
141
142 auto render_pass = builder.Build(context->GetDevice());
143
144 EXPECT_TRUE(!!render_pass);
145
146 auto maybe_color = builder.GetColor0();
147 ASSERT_TRUE(maybe_color.has_value());
148 if (!maybe_color.has_value()) {
149 return;
150 }
151 vk::AttachmentDescription color = maybe_color.value();
152
153 // MSAA Texture.
154 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eUndefined);
155 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
156 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
157 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
158
159 auto maybe_resolve = builder.GetColor0Resolve();
160 ASSERT_TRUE(maybe_resolve.has_value());
161 if (!maybe_resolve.has_value()) {
162 return;
163 }
164 vk::AttachmentDescription resolve = maybe_resolve.value();
165
166 // MSAA Resolve Texture.
167 EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eUndefined);
168 EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eShaderReadOnlyOptimal);
169 EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
170 EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
171 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::RenderPassBuilderVK::GetColor0Resolve(), impeller::kClear, impeller::kCount4, impeller::kMultisampleResolve, impeller::kR8G8B8A8UNormInt, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [394/574]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithCombinedDepthStencil |
| ) |  |

Definition at line 56 of file render_pass_builder_vk_unittests.cc.

56 {
57 RenderPassBuilderVK builder = RenderPassBuilderVK();
58 auto const context = MockVulkanContextBuilder().Build();
59
60 // Create a single color attachment with a transient depth stencil.
61 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
62 SampleCount::kCount1, LoadAction::kClear,
63 StoreAction::kStore, vk::ImageLayout::eGeneral);
64 builder.SetDepthStencilAttachment(PixelFormat::kD24UnormS8Uint,
65 SampleCount::kCount1, LoadAction::kDontCare,
66 StoreAction::kDontCare);
67
68 auto render_pass = builder.Build(context->GetDevice());
69
70 EXPECT_TRUE(!!render_pass);
71
72 std::optional<vk::AttachmentDescription> maybe_color = builder.GetColor0();
73 ASSERT_TRUE(maybe_color.has_value());
74 if (!maybe_color.has_value()) {
75 return;
76 }
77 vk::AttachmentDescription color = maybe_color.value();
78
79 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eUndefined);
80 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eShaderReadOnlyOptimal);
81 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
82 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
83
84 std::optional<vk::AttachmentDescription> maybe_depth_stencil =
85 builder.GetDepthStencil();
86 ASSERT_TRUE(maybe_depth_stencil.has_value());
87 if (!maybe_depth_stencil.has_value()) {
88 return;
89 }
90 vk::AttachmentDescription depth_stencil = maybe_depth_stencil.value();
91
92 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
93 EXPECT_EQ(depth_stencil.finalLayout,
94 vk::ImageLayout::eDepthStencilAttachmentOptimal);
95 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
96 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
97 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
98 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
99 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kD24UnormS8Uint, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetDepthStencilAttachment().

## ◆ TEST() [395/574]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithNoDepthStencil |
| ) |  |

Definition at line 15 of file render_pass_builder_vk_unittests.cc.

15 {
16 RenderPassBuilderVK builder = RenderPassBuilderVK();
17 auto const context = MockVulkanContextBuilder().Build();
18
19 // Create a single color attachment with a transient depth stencil.
20 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
21 SampleCount::kCount1, LoadAction::kClear,
22 StoreAction::kStore);
23
24 auto render_pass = builder.Build(context->GetDevice());
25
26 EXPECT_TRUE(!!render_pass);
27 EXPECT_FALSE(builder.GetDepthStencil().has_value());
28 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kR8G8B8A8UNormInt, impeller::kStore, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [396/574]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithOnlyStencil |
| ) |  |

Definition at line 101 of file render_pass_builder_vk_unittests.cc.

101 {
102 RenderPassBuilderVK builder = RenderPassBuilderVK();
103 auto const context = MockVulkanContextBuilder().Build();
104
105 // Create a single color attachment with a transient depth stencil.
106 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
107 SampleCount::kCount1, LoadAction::kClear,
108 StoreAction::kStore);
109 builder.SetStencilAttachment(PixelFormat::kS8UInt, SampleCount::kCount1,
110 LoadAction::kDontCare, StoreAction::kDontCare);
111
112 auto render_pass = builder.Build(context->GetDevice());
113
114 EXPECT_TRUE(!!render_pass);
115
116 std::optional<vk::AttachmentDescription> maybe_depth_stencil =
117 builder.GetDepthStencil();
118 ASSERT_TRUE(maybe_depth_stencil.has_value());
119 if (!maybe_depth_stencil.has_value()) {
120 return;
121 }
122 vk::AttachmentDescription depth_stencil = maybe_depth_stencil.value();
123
124 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
125 EXPECT_EQ(depth_stencil.finalLayout,
126 vk::ImageLayout::eDepthStencilAttachmentOptimal);
127 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
128 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
129 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
130 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
131 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kS8UInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetStencilAttachment().

## ◆ TEST() [397/574]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | RenderPassWithLoadOpUsesCurrentLayout |
| ) |  |

Definition at line 30 of file render_pass_builder_vk_unittests.cc.

30 {
31 RenderPassBuilderVK builder = RenderPassBuilderVK();
32 auto const context = MockVulkanContextBuilder().Build();
33
34 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
35 SampleCount::kCount1, LoadAction::kLoad,
36 StoreAction::kStore,
37 vk::ImageLayout::eColorAttachmentOptimal);
38
39 auto render_pass = builder.Build(context->GetDevice());
40
41 EXPECT_TRUE(!!render_pass);
42
43 std::optional<vk::AttachmentDescription> maybe_color = builder.GetColor0();
44 ASSERT_TRUE(maybe_color.has_value());
45 if (!maybe_color.has_value()) {
46 return;
47 }
48 vk::AttachmentDescription color = maybe_color.value();
49
50 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eColorAttachmentOptimal);
51 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eShaderReadOnlyOptimal);
52 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eLoad);
53 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
54 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetColor0(), impeller::kCount1, impeller::kLoad, impeller::kR8G8B8A8UNormInt, impeller::kStore, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [398/574]

impeller::testing::TEST | ( | RenderPassVK | ,
|  | DoesNotRedundantlySetStencil |
| ) |  |

Definition at line 17 of file render_pass_vk_unittests.cc.

17 {
18 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
19 std::shared_ptr<Context> copy = context;
20 auto cmd_buffer = context->CreateCommandBuffer();
21
22 RenderTargetAllocator allocator(context->GetResourceAllocator());
23 RenderTarget target = allocator.CreateOffscreenMSAA(*copy.get(), {1, 1}, 1);
24
25 std::shared_ptr<RenderPass> render_pass =
26 cmd_buffer->CreateRenderPass(target);
27
28 // Stencil reference set once at buffer start.
29 auto called_functions = GetMockVulkanFunctions(context->GetDevice());
30 EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
31 "vkCmdSetStencilReference"),
32 1);
33
34 // Duplicate stencil ref is not replaced.
35 render_pass->SetStencilReference(0);
36 render_pass->SetStencilReference(0);
37 render_pass->SetStencilReference(0);
38
39 called_functions = GetMockVulkanFunctions(context->GetDevice());
40 EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
41 "vkCmdSetStencilReference"),
42 1);
43
44 // Different stencil value is updated.
45 render_pass->SetStencilReference(1);
46 called_functions = GetMockVulkanFunctions(context->GetDevice());
47 EXPECT_EQ(std::count(called_functions->begin(), called_functions->end(),
48 "vkCmdSetStencilReference"),
49 2);
50 }

References impeller::RenderTargetAllocator::CreateOffscreenMSAA().

## ◆ TEST() [399/574]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | CreatesANewInstance |
| ) |  |

Definition at line 18 of file resource_manager_vk_unittests.cc.

18 {
19 auto const a = ResourceManagerVK::Create();
20 auto const b = ResourceManagerVK::Create();
21 EXPECT_NE(a, b);
22 }
impeller::interop::Create
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:161

References impeller::saturated::b, and impeller::ResourceManagerVK::Create().

## ◆ TEST() [400/574]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | IsThreadSafe |
| ) |  |

Definition at line 58 of file resource_manager_vk_unittests.cc.

58 {
59 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
60 // threads.
61 //
62 // This test ensures that the ResourceManagerVK is thread-safe.
63 std::weak_ptr<ResourceManagerVK> manager;
64
65 {
66 auto const manager = ResourceManagerVK::Create();
67
68 // Spawn two threads, and have them both put resources into the manager.
69 struct MockResource {};
70
71 std::thread thread1([&manager]() {
72 UniqueResourceVKT<MockResource>(manager, MockResource{});
73 });
74
75 std::thread thread2([&manager]() {
76 UniqueResourceVKT<MockResource>(manager, MockResource{});
77 });
78
79 thread1.join();
80 thread2.join();
81 }
82
83 // The thread should have terminated.
84 EXPECT_EQ(manager.lock(), nullptr);
85 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [401/574]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | ReclaimMovesAResourceAndDestroysIt |
| ) |  |

Definition at line 24 of file resource_manager_vk_unittests.cc.

24 {
25 auto const manager = ResourceManagerVK::Create();
26
27 auto waiter = fml::AutoResetWaitableEvent();
28 auto dead = false;
29 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
30
31 // Not killed immediately.
32 EXPECT_FALSE(waiter.IsSignaledForTest());
33
34 {
35 auto resource = UniqueResourceVKT<fml::ScopedCleanupClosure>(
36 manager, std::move(rattle));
37 }
38
39 waiter.Wait();
40 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [402/574]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | TerminatesWhenOutOfScope |
| ) |  |

Definition at line 43 of file resource_manager_vk_unittests.cc.

43 {
44 // Originally, this shared_ptr was never destroyed, and the thread never
45 // terminated. This test ensures that the thread terminates when the
46 // ResourceManagerVK is out of scope.
47 std::weak_ptr<ResourceManagerVK> manager;
48
49 {
50 auto shared = ResourceManagerVK::Create();
51 manager = shared;
52 }
53
54 // The thread should have terminated.
55 EXPECT_EQ(manager.lock(), nullptr);
56 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [403/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiCornersSameTolerance |
| ) |  |

Definition at line 268 of file rounding_radii_unittests.cc.

268 {
269 RoundingRadii radii{
270 .top_left = {10, 20},
271 .top_right = {10.01, 20.01},
272 .bottom_left = {9.99, 19.99},
273 .bottom_right = {9.99, 20.01},
274 };
275
276 EXPECT_TRUE(radii.AreAllCornersSame(.02));
277
278 {
279 RoundingRadii different = radii;
280 different.top_left.width = 10.03;
281 EXPECT_FALSE(different.AreAllCornersSame(.02));
282 }
283 {
284 RoundingRadii different = radii;
285 different.top_left.height = 20.03;
286 EXPECT_FALSE(different.AreAllCornersSame(.02));
287 }
288 {
289 RoundingRadii different = radii;
290 different.top_right.width = 10.03;
291 EXPECT_FALSE(different.AreAllCornersSame(.02));
292 }
293 {
294 RoundingRadii different = radii;
295 different.top_right.height = 20.03;
296 EXPECT_FALSE(different.AreAllCornersSame(.02));
297 }
298 {
299 RoundingRadii different = radii;
300 different.bottom_left.width = 9.97;
301 EXPECT_FALSE(different.AreAllCornersSame(.02));
302 }
303 {
304 RoundingRadii different = radii;
305 different.bottom_left.height = 19.97;
306 EXPECT_FALSE(different.AreAllCornersSame(.02));
307 }
308 {
309 RoundingRadii different = radii;
310 different.bottom_right.width = 9.97;
311 EXPECT_FALSE(different.AreAllCornersSame(.02));
312 }
313 {
314 RoundingRadii different = radii;
315 different.bottom_right.height = 20.03;
316 EXPECT_FALSE(different.AreAllCornersSame(.02));
317 }
318 }

References impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [404/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiDefaultConstructor |
| ) |  |

Definition at line 34 of file rounding_radii_unittests.cc.

34 {
35 RoundingRadii radii = RoundingRadii();
36
37 EXPECT_TRUE(radii.AreAllCornersEmpty());
38 EXPECT_TRUE(radii.AreAllCornersSame());
39 EXPECT_TRUE(radii.IsFinite());
40 EXPECT_EQ(radii.top_left, Size());
41 EXPECT_EQ(radii.top_right, Size());
42 EXPECT_EQ(radii.bottom_left, Size());
43 EXPECT_EQ(radii.bottom_right, Size());
44 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [405/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiEmptyDeclaration |
| ) |  |

Definition at line 14 of file rounding_radii_unittests.cc.

14 {
15 RoundingRadii radii;
16
17 EXPECT_TRUE(radii.AreAllCornersEmpty());
18 EXPECT_TRUE(radii.AreAllCornersSame());
19 EXPECT_TRUE(radii.IsFinite());
20 EXPECT_EQ(radii.top_left, Size());
21 EXPECT_EQ(radii.top_right, Size());
22 EXPECT_EQ(radii.bottom_left, Size());
23 EXPECT_EQ(radii.bottom_right, Size());
24 EXPECT_EQ(radii.top_left.width, 0.0f);
25 EXPECT_EQ(radii.top_left.height, 0.0f);
26 EXPECT_EQ(radii.top_right.width, 0.0f);
27 EXPECT_EQ(radii.top_right.height, 0.0f);
28 EXPECT_EQ(radii.bottom_left.width, 0.0f);
29 EXPECT_EQ(radii.bottom_left.height, 0.0f);
30 EXPECT_EQ(radii.bottom_right.width, 0.0f);
31 EXPECT_EQ(radii.bottom_right.height, 0.0f);
32 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [406/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiEmptyScalarConstructor |
| ) |  |

Definition at line 58 of file rounding_radii_unittests.cc.

58 {
59 RoundingRadii radii = RoundingRadii::MakeRadius(-5.0f);
60
61 EXPECT_TRUE(radii.AreAllCornersEmpty());
62 EXPECT_TRUE(radii.AreAllCornersSame());
63 EXPECT_TRUE(radii.IsFinite());
64 EXPECT_EQ(radii.top_left, Size(-5.0f, -5.0f));
65 EXPECT_EQ(radii.top_right, Size(-5.0f, -5.0f));
66 EXPECT_EQ(radii.bottom_left, Size(-5.0f, -5.0f));
67 EXPECT_EQ(radii.bottom_right, Size(-5.0f, -5.0f));
68 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [407/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiEmptySizeConstructor |
| ) |  |

Definition at line 82 of file rounding_radii_unittests.cc.

82 {
83 {
84 RoundingRadii radii = RoundingRadii::MakeRadii(Size(-5.0f, 6.0f));
85
86 EXPECT_TRUE(radii.AreAllCornersEmpty());
87 EXPECT_TRUE(radii.AreAllCornersSame());
88 EXPECT_TRUE(radii.IsFinite());
89 EXPECT_EQ(radii.top_left, Size(-5.0f, 6.0f));
90 EXPECT_EQ(radii.top_right, Size(-5.0f, 6.0f));
91 EXPECT_EQ(radii.bottom_left, Size(-5.0f, 6.0f));
92 EXPECT_EQ(radii.bottom_right, Size(-5.0f, 6.0f));
93 }
94
95 {
96 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, -6.0f));
97
98 EXPECT_TRUE(radii.AreAllCornersEmpty());
99 EXPECT_TRUE(radii.AreAllCornersSame());
100 EXPECT_TRUE(radii.IsFinite());
101 EXPECT_EQ(radii.top_left, Size(5.0f, -6.0f));
102 EXPECT_EQ(radii.top_right, Size(5.0f, -6.0f));
103 EXPECT_EQ(radii.bottom_left, Size(5.0f, -6.0f));
104 EXPECT_EQ(radii.bottom_right, Size(5.0f, -6.0f));
105 }
106 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [408/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiEquals |
| ) |  |

Definition at line 201 of file rounding_radii_unittests.cc.

201 {
202 RoundingRadii radii = {
203 .top_left = Size(5.0f, 5.5f),
204 .top_right = Size(6.0f, 6.5f),
205 .bottom_left = Size(7.0f, 7.5f),
206 .bottom_right = Size(8.0f, 8.5f),
207 };
208 RoundingRadii other = {
209 .top_left = Size(5.0f, 5.5f),
210 .top_right = Size(6.0f, 6.5f),
211 .bottom_left = Size(7.0f, 7.5f),
212 .bottom_right = Size(8.0f, 8.5f),
213 };
214
215 EXPECT_EQ(radii, other);
216 }

References impeller::RoundingRadii::top_left.

## ◆ TEST() [409/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiMultiply |
| ) |  |

Definition at line 183 of file rounding_radii_unittests.cc.

183 {
184 RoundingRadii radii = {
185 .top_left = Size(5.0f, 5.5f),
186 .top_right = Size(6.0f, 6.5f),
187 .bottom_left = Size(7.0f, 7.5f),
188 .bottom_right = Size(8.0f, 8.5f),
189 };
190 RoundingRadii doubled = radii * 2.0f;
191
192 EXPECT_FALSE(doubled.AreAllCornersEmpty());
193 EXPECT_FALSE(doubled.AreAllCornersSame());
194 EXPECT_TRUE(doubled.IsFinite());
195 EXPECT_EQ(doubled.top_left, Size(10.0f, 11.0f));
196 EXPECT_EQ(doubled.top_right, Size(12.0f, 13.0f));
197 EXPECT_EQ(doubled.bottom_left, Size(14.0f, 15.0f));
198 EXPECT_EQ(doubled.bottom_right, Size(16.0f, 17.0f));
199 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [410/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiNamedSizesConstructor |
| ) |  |

Definition at line 108 of file rounding_radii_unittests.cc.

108 {
109 RoundingRadii radii = {
110 .top_left = Size(5.0f, 5.5f),
111 .top_right = Size(6.0f, 6.5f),
112 .bottom_left = Size(7.0f, 7.5f),
113 .bottom_right = Size(8.0f, 8.5f),
114 };
115
116 EXPECT_FALSE(radii.AreAllCornersEmpty());
117 EXPECT_FALSE(radii.AreAllCornersSame());
118 EXPECT_TRUE(radii.IsFinite());
119 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
120 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
121 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
122 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
123 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [411/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiNotEquals |
| ) |  |

Definition at line 218 of file rounding_radii_unittests.cc.

218 {
219 const RoundingRadii radii = {
220 .top_left = Size(5.0f, 5.5f),
221 .top_right = Size(6.0f, 6.5f),
222 .bottom_left = Size(7.0f, 7.5f),
223 .bottom_right = Size(8.0f, 8.5f),
224 };
225
226 {
227 RoundingRadii different = radii;
228 different.top_left.width = 100.0f;
229 EXPECT_NE(different, radii);
230 }
231 {
232 RoundingRadii different = radii;
233 different.top_left.height = 100.0f;
234 EXPECT_NE(different, radii);
235 }
236 {
237 RoundingRadii different = radii;
238 different.top_right.width = 100.0f;
239 EXPECT_NE(different, radii);
240 }
241 {
242 RoundingRadii different = radii;
243 different.top_right.height = 100.0f;
244 EXPECT_NE(different, radii);
245 }
246 {
247 RoundingRadii different = radii;
248 different.bottom_left.width = 100.0f;
249 EXPECT_NE(different, radii);
250 }
251 {
252 RoundingRadii different = radii;
253 different.bottom_left.height = 100.0f;
254 EXPECT_NE(different, radii);
255 }
256 {
257 RoundingRadii different = radii;
258 different.bottom_right.width = 100.0f;
259 EXPECT_NE(different, radii);
260 }
261 {
262 RoundingRadii different = radii;
263 different.bottom_right.height = 100.0f;
264 EXPECT_NE(different, radii);
265 }
266 }
impeller::TSize::width
Type width
Definition: size.h:28

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TSize< T >::height, impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [412/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiPartialNamedSizesConstructor |
| ) |  |

Definition at line 125 of file rounding_radii_unittests.cc.

125 {
126 {
127 RoundingRadii radii = {
128 .top_left = Size(5.0f, 5.5f),
129 };
130
131 EXPECT_FALSE(radii.AreAllCornersEmpty());
132 EXPECT_FALSE(radii.AreAllCornersSame());
133 EXPECT_TRUE(radii.IsFinite());
134 EXPECT_EQ(radii.top_left, Size(5.0f, 5.5f));
135 EXPECT_EQ(radii.top_right, Size());
136 EXPECT_EQ(radii.bottom_left, Size());
137 EXPECT_EQ(radii.bottom_right, Size());
138 }
139
140 {
141 RoundingRadii radii = {
142 .top_right = Size(6.0f, 6.5f),
143 };
144
145 EXPECT_FALSE(radii.AreAllCornersEmpty());
146 EXPECT_FALSE(radii.AreAllCornersSame());
147 EXPECT_TRUE(radii.IsFinite());
148 EXPECT_EQ(radii.top_left, Size());
149 EXPECT_EQ(radii.top_right, Size(6.0f, 6.5f));
150 EXPECT_EQ(radii.bottom_left, Size());
151 EXPECT_EQ(radii.bottom_right, Size());
152 }
153
154 {
155 RoundingRadii radii = {
156 .bottom_left = Size(7.0f, 7.5f),
157 };
158
159 EXPECT_FALSE(radii.AreAllCornersEmpty());
160 EXPECT_FALSE(radii.AreAllCornersSame());
161 EXPECT_TRUE(radii.IsFinite());
162 EXPECT_EQ(radii.top_left, Size());
163 EXPECT_EQ(radii.top_right, Size());
164 EXPECT_EQ(radii.bottom_left, Size(7.0f, 7.5f));
165 EXPECT_EQ(radii.bottom_right, Size());
166 }
167
168 {
169 RoundingRadii radii = {
170 .bottom_right = Size(8.0f, 8.5f),
171 };
172
173 EXPECT_FALSE(radii.AreAllCornersEmpty());
174 EXPECT_FALSE(radii.AreAllCornersSame());
175 EXPECT_TRUE(radii.IsFinite());
176 EXPECT_EQ(radii.top_left, Size());
177 EXPECT_EQ(radii.top_right, Size());
178 EXPECT_EQ(radii.bottom_left, Size());
179 EXPECT_EQ(radii.bottom_right, Size(8.0f, 8.5f));
180 }
181 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [413/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiScalarConstructor |
| ) |  |

Definition at line 46 of file rounding_radii_unittests.cc.

46 {
47 RoundingRadii radii = RoundingRadii::MakeRadius(5.0f);
48
49 EXPECT_FALSE(radii.AreAllCornersEmpty());
50 EXPECT_TRUE(radii.AreAllCornersSame());
51 EXPECT_TRUE(radii.IsFinite());
52 EXPECT_EQ(radii.top_left, Size(5.0f, 5.0f));
53 EXPECT_EQ(radii.top_right, Size(5.0f, 5.0f));
54 EXPECT_EQ(radii.bottom_left, Size(5.0f, 5.0f));
55 EXPECT_EQ(radii.bottom_right, Size(5.0f, 5.0f));
56 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [414/574]

impeller::testing::TEST | ( | RoudingRadiiTest | ,
|  | RoundingRadiiSizeConstructor |
| ) |  |

Definition at line 70 of file rounding_radii_unittests.cc.

70 {
71 RoundingRadii radii = RoundingRadii::MakeRadii(Size(5.0f, 6.0f));
72
73 EXPECT_FALSE(radii.AreAllCornersEmpty());
74 EXPECT_TRUE(radii.AreAllCornersSame());
75 EXPECT_TRUE(radii.IsFinite());
76 EXPECT_EQ(radii.top_left, Size(5.0f, 6.0f));
77 EXPECT_EQ(radii.top_right, Size(5.0f, 6.0f));
78 EXPECT_EQ(radii.bottom_left, Size(5.0f, 6.0f));
79 EXPECT_EQ(radii.bottom_right, Size(5.0f, 6.0f));
80 }

References impeller::RoundingRadii::AreAllCornersEmpty(), impeller::RoundingRadii::AreAllCornersSame(), impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundingRadii::IsFinite(), impeller::RoundingRadii::MakeRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [415/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractAndRequireRadiiAdjustment |
| ) |  |

Definition at line 496 of file round_rect_unittests.cc.

496 {
497 RoundRect round_rect =
498 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
499 {
500 .top_left = Size(1.0f, 2.0f),
501 .top_right = Size(3.0f, 4.0f),
502 .bottom_left = Size(5.0f, 6.0f),
503 .bottom_right = Size(7.0f, 8.0f),
504 });
505 RoundRect expanded = round_rect.Expand(-12.0);
506 // Largest sum of paired radii sizes are the bottom and right edges
507 // both of which sum to 12
508 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
509 // radii are scaled by half to avoid overflowing the contracted rect
510
511 EXPECT_FALSE(expanded.IsEmpty());
512 EXPECT_FALSE(expanded.IsRect());
513 EXPECT_FALSE(expanded.IsOval());
514 EXPECT_TRUE(expanded.IsFinite());
515 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
516 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
517 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
518 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
519 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
520 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
521
522 // In this test, the MakeRectRadii constructor will make the same
523 // adjustment to the radii that the Expand method applied.
524 EXPECT_EQ(expanded,
525 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
526 {
527 .top_left = Size(1.0f, 2.0f),
528 .top_right = Size(3.0f, 4.0f),
529 .bottom_left = Size(5.0f, 6.0f),
530 .bottom_right = Size(7.0f, 8.0f),
531 }));
532
533 // In this test, the arguments to the constructor supply the correctly
534 // adjusted radii (though there is no real way to tell other than
535 // the result is the same).
536 EXPECT_EQ(expanded,
537 RoundRect::MakeRectRadii(Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
538 {
539 .top_left = Size(0.5f, 1.0f),
540 .top_right = Size(1.5f, 2.0f),
541 .bottom_left = Size(2.5f, 3.0f),
542 .bottom_right = Size(3.5f, 4.0f),
543 }));
544 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [416/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractFourScalars |
| ) |  |

Definition at line 464 of file round_rect_unittests.cc.

464 {
465 RoundRect round_rect =
466 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
467 {
468 .top_left = Size(1.0f, 2.0f),
469 .top_right = Size(3.0f, 4.0f),
470 .bottom_left = Size(5.0f, 6.0f),
471 .bottom_right = Size(7.0f, 8.0f),
472 });
473 RoundRect expanded = round_rect.Expand(-1.0, -1.5, -2.0, -2.5);
474
475 EXPECT_FALSE(expanded.IsEmpty());
476 EXPECT_FALSE(expanded.IsRect());
477 EXPECT_FALSE(expanded.IsOval());
478 EXPECT_TRUE(expanded.IsFinite());
479 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
480 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
481 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
482 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
483 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
484 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
485
486 EXPECT_EQ(expanded,
487 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
488 {
489 .top_left = Size(1.0f, 2.0f),
490 .top_right = Size(3.0f, 4.0f),
491 .bottom_left = Size(5.0f, 6.0f),
492 .bottom_right = Size(7.0f, 8.0f),
493 }));
494 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [417/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractScalar |
| ) |  |

Definition at line 400 of file round_rect_unittests.cc.

400 {
401 RoundRect round_rect =
402 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
403 {
404 .top_left = Size(1.0f, 2.0f),
405 .top_right = Size(3.0f, 4.0f),
406 .bottom_left = Size(5.0f, 6.0f),
407 .bottom_right = Size(7.0f, 8.0f),
408 });
409 RoundRect expanded = round_rect.Expand(-2.0);
410
411 EXPECT_FALSE(expanded.IsEmpty());
412 EXPECT_FALSE(expanded.IsRect());
413 EXPECT_FALSE(expanded.IsOval());
414 EXPECT_TRUE(expanded.IsFinite());
415 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
416 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
417 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
418 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
419 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
420 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
421
422 EXPECT_EQ(expanded,
423 RoundRect::MakeRectRadii(Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
424 {
425 .top_left = Size(1.0f, 2.0f),
426 .top_right = Size(3.0f, 4.0f),
427 .bottom_left = Size(5.0f, 6.0f),
428 .bottom_right = Size(7.0f, 8.0f),
429 }));
430 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [418/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ContractTwoScalars |
| ) |  |

Definition at line 432 of file round_rect_unittests.cc.

432 {
433 RoundRect round_rect =
434 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
435 {
436 .top_left = Size(1.0f, 2.0f),
437 .top_right = Size(3.0f, 4.0f),
438 .bottom_left = Size(5.0f, 6.0f),
439 .bottom_right = Size(7.0f, 8.0f),
440 });
441 RoundRect expanded = round_rect.Expand(-1.0, -2.0);
442
443 EXPECT_FALSE(expanded.IsEmpty());
444 EXPECT_FALSE(expanded.IsRect());
445 EXPECT_FALSE(expanded.IsOval());
446 EXPECT_TRUE(expanded.IsFinite());
447 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
448 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
449 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
450 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
451 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
452 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
453
454 EXPECT_EQ(expanded,
455 RoundRect::MakeRectRadii(Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
456 {
457 .top_left = Size(1.0f, 2.0f),
458 .top_right = Size(3.0f, 4.0f),
459 .bottom_left = Size(5.0f, 6.0f),
460 .bottom_right = Size(7.0f, 8.0f),
461 }));
462 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [419/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | DefaultConstructor |
| ) |  |

Definition at line 41 of file round_rect_unittests.cc.

41 {
42 RoundRect round_rect = RoundRect();
43
44 EXPECT_TRUE(round_rect.IsEmpty());
45 EXPECT_FALSE(round_rect.IsRect());
46 EXPECT_FALSE(round_rect.IsOval());
47 EXPECT_TRUE(round_rect.IsFinite());
48 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
49 EXPECT_EQ(round_rect.GetBounds(), Rect());
50 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
51 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
52 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
53 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
54 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [420/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | DifferingCornersRoundRectContains |
| ) |  |

Definition at line 652 of file round_rect_unittests.cc.

652 {
653 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
654 auto round_rect =
655 RoundRect::MakeRectRadii(bounds, {
656 .top_left = Size(2.0, 3.0),
657 .top_right = Size(4.0, 5.0),
658 .bottom_left = Size(6.0, 7.0),
659 .bottom_right = Size(8.0, 9.0),
660 });
661
662 // For a corner with radii {A, B}, the "45 degree point" on the
663 // corner curve will be at an offset of:
664 //
665 // (A * sqrt(2) / 2, B * sqrt(2) / 2)
666 //
667 // And the center(s) of these corners are at:
668 //
669 // (+/-(50 - A), +/-(50 - B))
670 auto coord = [](Scalar radius) {
671 return 50 - radius + radius * kSqrt2 / 2.0f - kEhCloseEnough;
672 };
673 auto coord_in = [&coord](Scalar radius) {
674 return coord(radius) - kEhCloseEnough;
675 };
676 auto coord_out = [&coord](Scalar radius) {
677 // For some reason 1 kEhCloseEnough is not enough to put us outside
678 // in some of the cases, so we use 2x the epsilon.
679 return coord(radius) + 2 * kEhCloseEnough;
680 };
681 // Upper left corner (radii = {2.0, 3.0})
682 EXPECT_TRUE(round_rect.Contains({-coord_in(2.0), -coord_in(3.0)}));
683 EXPECT_FALSE(round_rect.Contains({-coord_out(2.0), -coord_out(3.0)}));
684 // Upper right corner (radii = {4.0, 5.0})
685 EXPECT_TRUE(round_rect.Contains({coord_in(4.0), -coord_in(5.0)}));
686 EXPECT_FALSE(round_rect.Contains({coord_out(4.0), -coord_out(5.0)}));
687 // Lower left corner (radii = {6.0, 7.0})
688 EXPECT_TRUE(round_rect.Contains({-coord_in(6.0), coord_in(7.0)}));
689 EXPECT_FALSE(round_rect.Contains({-coord_out(6.0), coord_out(7.0)}));
690 // Lower right corner (radii = {8.0, 9.0})
691 EXPECT_TRUE(round_rect.Contains({coord_in(8.0), coord_in(9.0)}));
692 EXPECT_FALSE(round_rect.Contains({coord_out(8.0), coord_out(9.0)}));
693 }

References impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectRadii().

## ◆ TEST() [421/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyDeclaration |
| ) |  |

Definition at line 14 of file round_rect_unittests.cc.

14 {
15 RoundRect round_rect;
16
17 EXPECT_TRUE(round_rect.IsEmpty());
18 EXPECT_FALSE(round_rect.IsRect());
19 EXPECT_FALSE(round_rect.IsOval());
20 EXPECT_TRUE(round_rect.IsFinite());
21 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
22 EXPECT_EQ(round_rect.GetBounds(), Rect());
23 EXPECT_EQ(round_rect.GetBounds().GetLeft(), 0.0f);
24 EXPECT_EQ(round_rect.GetBounds().GetTop(), 0.0f);
25 EXPECT_EQ(round_rect.GetBounds().GetRight(), 0.0f);
26 EXPECT_EQ(round_rect.GetBounds().GetBottom(), 0.0f);
27 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
28 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
29 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
30 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
31 EXPECT_EQ(round_rect.GetRadii().top_left.width, 0.0f);
32 EXPECT_EQ(round_rect.GetRadii().top_left.height, 0.0f);
33 EXPECT_EQ(round_rect.GetRadii().top_right.width, 0.0f);
34 EXPECT_EQ(round_rect.GetRadii().top_right.height, 0.0f);
35 EXPECT_EQ(round_rect.GetRadii().bottom_left.width, 0.0f);
36 EXPECT_EQ(round_rect.GetRadii().bottom_left.height, 0.0f);
37 EXPECT_EQ(round_rect.GetRadii().bottom_right.width, 0.0f);
38 EXPECT_EQ(round_rect.GetRadii().bottom_right.height, 0.0f);
39 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TRect< T >::GetBottom(), impeller::RoundRect::GetBounds(), impeller::TRect< T >::GetLeft(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TSize< T >::height, impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [422/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyOvalConstruction |
| ) |  |

Definition at line 104 of file round_rect_unittests.cc.

104 {
105 RoundRect round_rect = RoundRect::MakeRectXY(
106 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
107
108 EXPECT_TRUE(round_rect.IsEmpty());
109 EXPECT_FALSE(round_rect.IsRect());
110 EXPECT_FALSE(round_rect.IsOval());
111 EXPECT_TRUE(round_rect.IsFinite());
112 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
113 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
114 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
115 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
116 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
117 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
118 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [423/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | EmptyRectConstruction |
| ) |  |

Definition at line 56 of file round_rect_unittests.cc.

56 {
57 RoundRect round_rect =
58 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
59
60 EXPECT_TRUE(round_rect.IsEmpty());
61 EXPECT_FALSE(round_rect.IsRect());
62 EXPECT_FALSE(round_rect.IsOval());
63 EXPECT_TRUE(round_rect.IsFinite());
64 EXPECT_TRUE(round_rect.GetBounds().IsEmpty());
65 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
66 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
67 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
68 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
69 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
70 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [424/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandFourScalars |
| ) |  |

Definition at line 368 of file round_rect_unittests.cc.

368 {
369 RoundRect round_rect =
370 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
371 {
372 .top_left = Size(1.0f, 2.0f),
373 .top_right = Size(3.0f, 4.0f),
374 .bottom_left = Size(5.0f, 6.0f),
375 .bottom_right = Size(7.0f, 8.0f),
376 });
377 RoundRect expanded = round_rect.Expand(5.0, 6.0, 7.0, 8.0);
378
379 EXPECT_FALSE(expanded.IsEmpty());
380 EXPECT_FALSE(expanded.IsRect());
381 EXPECT_FALSE(expanded.IsOval());
382 EXPECT_TRUE(expanded.IsFinite());
383 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
384 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
385 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
386 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
387 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
388 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
389
390 EXPECT_EQ(expanded,
391 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
392 {
393 .top_left = Size(1.0f, 2.0f),
394 .top_right = Size(3.0f, 4.0f),
395 .bottom_left = Size(5.0f, 6.0f),
396 .bottom_right = Size(7.0f, 8.0f),
397 }));
398 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [425/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandScalar |
| ) |  |

Definition at line 304 of file round_rect_unittests.cc.

304 {
305 RoundRect round_rect =
306 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
307 {
308 .top_left = Size(1.0f, 2.0f),
309 .top_right = Size(3.0f, 4.0f),
310 .bottom_left = Size(5.0f, 6.0f),
311 .bottom_right = Size(7.0f, 8.0f),
312 });
313 RoundRect expanded = round_rect.Expand(5.0);
314
315 EXPECT_FALSE(expanded.IsEmpty());
316 EXPECT_FALSE(expanded.IsRect());
317 EXPECT_FALSE(expanded.IsOval());
318 EXPECT_TRUE(expanded.IsFinite());
319 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
320 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
321 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
322 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
323 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
324 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
325
326 EXPECT_EQ(expanded,
327 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
328 {
329 .top_left = Size(1.0f, 2.0f),
330 .top_right = Size(3.0f, 4.0f),
331 .bottom_left = Size(5.0f, 6.0f),
332 .bottom_right = Size(7.0f, 8.0f),
333 }));
334 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [426/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | ExpandTwoScalars |
| ) |  |

Definition at line 336 of file round_rect_unittests.cc.

336 {
337 RoundRect round_rect =
338 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
339 {
340 .top_left = Size(1.0f, 2.0f),
341 .top_right = Size(3.0f, 4.0f),
342 .bottom_left = Size(5.0f, 6.0f),
343 .bottom_right = Size(7.0f, 8.0f),
344 });
345 RoundRect expanded = round_rect.Expand(5.0, 6.0);
346
347 EXPECT_FALSE(expanded.IsEmpty());
348 EXPECT_FALSE(expanded.IsRect());
349 EXPECT_FALSE(expanded.IsOval());
350 EXPECT_TRUE(expanded.IsFinite());
351 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
352 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
353 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
354 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
355 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
356 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
357
358 EXPECT_EQ(expanded,
359 RoundRect::MakeRectRadii(Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
360 {
361 .top_left = Size(1.0f, 2.0f),
362 .top_right = Size(3.0f, 4.0f),
363 .bottom_left = Size(5.0f, 6.0f),
364 .bottom_right = Size(7.0f, 8.0f),
365 }));
366 }

References impeller::RoundRect::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [427/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | InvertedOvalConstruction |
| ) |  |

Definition at line 136 of file round_rect_unittests.cc.

136 {
137 RoundRect round_rect = RoundRect::MakeRectXY(
138 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
139
140 EXPECT_FALSE(round_rect.IsEmpty());
141 EXPECT_FALSE(round_rect.IsRect());
142 EXPECT_TRUE(round_rect.IsOval());
143 EXPECT_TRUE(round_rect.IsFinite());
144 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
145 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
146 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
147 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
148 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
149 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
150 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [428/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | InvertedRectConstruction |
| ) |  |

Definition at line 88 of file round_rect_unittests.cc.

88 {
89 RoundRect round_rect =
90 RoundRect::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
91
92 EXPECT_FALSE(round_rect.IsEmpty());
93 EXPECT_TRUE(round_rect.IsRect());
94 EXPECT_FALSE(round_rect.IsOval());
95 EXPECT_TRUE(round_rect.IsFinite());
96 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
97 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
98 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
99 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
100 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
101 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
102 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [429/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | NoCornerRoundRectContains |
| ) |  |

Definition at line 546 of file round_rect_unittests.cc.

546 {
547 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
548 // RRect of bounds with no corners contains corners just barely
549 auto no_corners = RoundRect::MakeRectXY(bounds, 0.0f, 0.0f);
550
551 EXPECT_TRUE(no_corners.Contains({-50, -50}));
552 // Rectangles have half-in, half-out containment so we need
553 // to be careful about testing containment of right/bottom corners.
554 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
555 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
556 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
557 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
558 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
559 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
560 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
561 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
562 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
563 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
564 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
565 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [430/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | OvalConstructor |
| ) |  |

Definition at line 120 of file round_rect_unittests.cc.

120 {
121 RoundRect round_rect =
122 RoundRect::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
123
124 EXPECT_FALSE(round_rect.IsEmpty());
125 EXPECT_FALSE(round_rect.IsRect());
126 EXPECT_TRUE(round_rect.IsOval());
127 EXPECT_TRUE(round_rect.IsFinite());
128 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
129 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
130 EXPECT_EQ(round_rect.GetRadii().top_left, Size(5.0f, 5.0f));
131 EXPECT_EQ(round_rect.GetRadii().top_right, Size(5.0f, 5.0f));
132 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(5.0f, 5.0f));
133 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(5.0f, 5.0f));
134 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeOval(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [431/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectConstructor |
| ) |  |

Definition at line 72 of file round_rect_unittests.cc.

72 {
73 RoundRect round_rect =
74 RoundRect::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
75
76 EXPECT_FALSE(round_rect.IsEmpty());
77 EXPECT_TRUE(round_rect.IsRect());
78 EXPECT_FALSE(round_rect.IsOval());
79 EXPECT_TRUE(round_rect.IsFinite());
80 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
81 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
82 EXPECT_EQ(round_rect.GetRadii().top_left, Size());
83 EXPECT_EQ(round_rect.GetRadii().top_right, Size());
84 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size());
85 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size());
86 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [432/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiConstructor |
| ) |  |

Definition at line 200 of file round_rect_unittests.cc.

200 {
201 RoundRect round_rect =
202 RoundRect::MakeRectRadii(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
203 {
204 .top_left = Size(1.0, 1.5),
205 .top_right = Size(2.0, 2.5f),
206 .bottom_left = Size(3.0, 3.5f),
207 .bottom_right = Size(4.0, 4.5f),
208 });
209
210 EXPECT_FALSE(round_rect.IsEmpty());
211 EXPECT_FALSE(round_rect.IsRect());
212 EXPECT_FALSE(round_rect.IsOval());
213 EXPECT_TRUE(round_rect.IsFinite());
214 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
215 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
216 EXPECT_EQ(round_rect.GetRadii().top_left, Size(1.0f, 1.5f));
217 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.5f));
218 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(3.0f, 3.5f));
219 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(4.0f, 4.5f));
220 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [433/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiOverflowHeightConstructor |
| ) |  |

Definition at line 247 of file round_rect_unittests.cc.

247 {
248 RoundRect round_rect =
249 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
250 {
251 .top_left = Size(1.0f, 2.0f),
252 .top_right = Size(3.0f, 4.0f),
253 .bottom_left = Size(5.0f, 6.0f),
254 .bottom_right = Size(7.0f, 8.0f),
255 });
256 // Largest sum of paired radii heights is the right edge which sums to 12
257 // Rect is only 6 tall so all radii are scaled by half
258 // Rect is 30 wide so no scaling should happen due to radii widths
259
260 EXPECT_FALSE(round_rect.IsEmpty());
261 EXPECT_FALSE(round_rect.IsRect());
262 EXPECT_FALSE(round_rect.IsOval());
263 EXPECT_TRUE(round_rect.IsFinite());
264 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
265 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
266 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
267 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
268 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
269 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
270 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [434/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiiOverflowWidthConstructor |
| ) |  |

Definition at line 222 of file round_rect_unittests.cc.

222 {
223 RoundRect round_rect =
224 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
225 {
226 .top_left = Size(1.0f, 2.0f),
227 .top_right = Size(3.0f, 4.0f),
228 .bottom_left = Size(5.0f, 6.0f),
229 .bottom_right = Size(7.0f, 8.0f),
230 });
231 // Largest sum of paired radii widths is the bottom edge which sums to 12
232 // Rect is only 6 wide so all radii are scaled by half
233 // Rect is 30 tall so no scaling should happen due to radii heights
234
235 EXPECT_FALSE(round_rect.IsEmpty());
236 EXPECT_FALSE(round_rect.IsRect());
237 EXPECT_FALSE(round_rect.IsOval());
238 EXPECT_TRUE(round_rect.IsFinite());
239 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
240 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
241 EXPECT_EQ(round_rect.GetRadii().top_left, Size(0.5f, 1.0f));
242 EXPECT_EQ(round_rect.GetRadii().top_right, Size(1.5f, 2.0f));
243 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.5f, 3.0f));
244 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(3.5f, 4.0f));
245 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [435/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectRadiusConstructor |
| ) |  |

Definition at line 152 of file round_rect_unittests.cc.

152 {
153 RoundRect round_rect = RoundRect::MakeRectRadius(
154 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
155
156 EXPECT_FALSE(round_rect.IsEmpty());
157 EXPECT_FALSE(round_rect.IsRect());
158 EXPECT_FALSE(round_rect.IsOval());
159 EXPECT_TRUE(round_rect.IsFinite());
160 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
161 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
162 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 2.0f));
163 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 2.0f));
164 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 2.0f));
165 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 2.0f));
166 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [436/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectSizeConstructor |
| ) |  |

Definition at line 184 of file round_rect_unittests.cc.

184 {
185 RoundRect round_rect = RoundRect::MakeRectXY(
186 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
187
188 EXPECT_FALSE(round_rect.IsEmpty());
189 EXPECT_FALSE(round_rect.IsRect());
190 EXPECT_FALSE(round_rect.IsOval());
191 EXPECT_TRUE(round_rect.IsFinite());
192 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
193 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
194 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
195 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
196 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
197 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
198 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [437/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | RectXYConstructor |
| ) |  |

Definition at line 168 of file round_rect_unittests.cc.

168 {
169 RoundRect round_rect = RoundRect::MakeRectXY(
170 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
171
172 EXPECT_FALSE(round_rect.IsEmpty());
173 EXPECT_FALSE(round_rect.IsRect());
174 EXPECT_FALSE(round_rect.IsOval());
175 EXPECT_TRUE(round_rect.IsFinite());
176 EXPECT_FALSE(round_rect.GetBounds().IsEmpty());
177 EXPECT_EQ(round_rect.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
178 EXPECT_EQ(round_rect.GetRadii().top_left, Size(2.0f, 3.0f));
179 EXPECT_EQ(round_rect.GetRadii().top_right, Size(2.0f, 3.0f));
180 EXPECT_EQ(round_rect.GetRadii().bottom_left, Size(2.0f, 3.0f));
181 EXPECT_EQ(round_rect.GetRadii().bottom_right, Size(2.0f, 3.0f));
182 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundRect::IsEmpty(), impeller::RoundRect::IsFinite(), impeller::RoundRect::IsOval(), impeller::RoundRect::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [438/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | Shift |
| ) |  |

Definition at line 272 of file round_rect_unittests.cc.

272 {
273 RoundRect round_rect =
274 RoundRect::MakeRectRadii(Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
275 {
276 .top_left = Size(1.0f, 2.0f),
277 .top_right = Size(3.0f, 4.0f),
278 .bottom_left = Size(5.0f, 6.0f),
279 .bottom_right = Size(7.0f, 8.0f),
280 });
281 RoundRect shifted = round_rect.Shift(5.0, 6.0);
282
283 EXPECT_FALSE(shifted.IsEmpty());
284 EXPECT_FALSE(shifted.IsRect());
285 EXPECT_FALSE(shifted.IsOval());
286 EXPECT_TRUE(shifted.IsFinite());
287 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
288 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
289 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
290 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
291 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
292 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
293
294 EXPECT_EQ(shifted,
295 RoundRect::MakeRectRadii(Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
296 {
297 .top_left = Size(1.0f, 2.0f),
298 .top_right = Size(3.0f, 4.0f),
299 .bottom_left = Size(5.0f, 6.0f),
300 .bottom_right = Size(7.0f, 8.0f),
301 }));
302 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::RoundRect::Shift().

## ◆ TEST() [439/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | TinyCornerRoundRectContains |
| ) |  |

Definition at line 567 of file round_rect_unittests.cc.

567 {
568 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
569 // RRect of bounds with even the tiniest corners does not contain corners
570 auto tiny_corners = RoundRect::MakeRectXY(bounds, 0.01f, 0.01f);
571
572 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
573 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
574 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
575 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
576 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [440/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | UniformCircularRoundRectContains |
| ) |  |

Definition at line 578 of file round_rect_unittests.cc.

578 {
579 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
580 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 2.0f);
581
582 // Expanded by 2.0 and then with a corner of 2.0 obviously still
583 // contains the corners
584 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
585 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
586 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
587 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
588
589 // Now we try to box in the corner containment to exactly where the
590 // rounded corner of the expanded round rect with radii of 2.0 lies.
591 // The 45-degree diagonal point of a circle of radius 2.0 lies at:
592 //
593 // (2 * sqrt(2) / 2, 2 * sqrt(2) / 2)
594 // (sqrt(2), sqrt(2))
595 //
596 // So we test +/- (50 + sqrt(2) +/- epsilon)
597 const auto coord_out = 50 + kSqrt2 + kEhCloseEnough;
598 const auto coord_in = 50 + kSqrt2 - kEhCloseEnough;
599 // Upper left corner
600 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, -coord_in}));
601 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, -coord_out}));
602 // Upper right corner
603 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, -coord_in}));
604 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, -coord_out}));
605 // Lower left corner
606 EXPECT_TRUE(expanded_2_r_2.Contains({-coord_in, coord_in}));
607 EXPECT_FALSE(expanded_2_r_2.Contains({-coord_out, coord_out}));
608 // Lower right corner
609 EXPECT_TRUE(expanded_2_r_2.Contains({coord_in, coord_in}));
610 EXPECT_FALSE(expanded_2_r_2.Contains({coord_out, coord_out}));
611 }

References impeller::TRect< T >::Expand(), impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [441/574]

impeller::testing::TEST | ( | RoundRectTest | ,
|  | UniformEllipticalRoundRectContains |
| ) |  |

Definition at line 613 of file round_rect_unittests.cc.

613 {
614 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
615 auto expanded_2_r_2 = RoundRect::MakeRectXY(bounds.Expand(2.0), 2.0f, 3.0f);
616
617 // Expanded by 2.0 and then with a corner of 2x3 should still
618 // contain the corners
619 EXPECT_TRUE(expanded_2_r_2.Contains({-50, -50}));
620 EXPECT_TRUE(expanded_2_r_2.Contains({-50, 50}));
621 EXPECT_TRUE(expanded_2_r_2.Contains({50, -50}));
622 EXPECT_TRUE(expanded_2_r_2.Contains({50, 50}));
623
624 // Now we try to box in the corner containment to exactly where the
625 // rounded corner of the expanded round rect with radii of 2x3 lies.
626 // The "45-degree diagonal point" of an ellipse of radii 2x3 lies at:
627 //
628 // (2 * sqrt(2) / 2, 3 * sqrt(2) / 2)
629 // (sqrt(2), 3 * sqrt(2) / 2)
630 //
631 // And the center(s) of these corners are at:
632 // (+/-(50 + 2 - 2), +/-(50 + 2 - 3))
633 // = (+/-50, +/-49)
634 const auto x_coord_out = 50 + kSqrt2 + kEhCloseEnough;
635 const auto x_coord_in = 50 + kSqrt2 - kEhCloseEnough;
636 const auto y_coord_out = 49 + 3 * kSqrt2 / 2 + kEhCloseEnough;
637 const auto y_coord_in = 49 + 3 * kSqrt2 / 2 - kEhCloseEnough;
638 // Upper left corner
639 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, -y_coord_in}));
640 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, -y_coord_out}));
641 // Upper right corner
642 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, -y_coord_in}));
643 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, -y_coord_out}));
644 // Lower left corner
645 EXPECT_TRUE(expanded_2_r_2.Contains({-x_coord_in, y_coord_in}));
646 EXPECT_FALSE(expanded_2_r_2.Contains({-x_coord_out, y_coord_out}));
647 // Lower right corner
648 EXPECT_TRUE(expanded_2_r_2.Contains({x_coord_in, y_coord_in}));
649 EXPECT_FALSE(expanded_2_r_2.Contains({x_coord_out, y_coord_out}));
650 }

References impeller::TRect< T >::Expand(), impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectXY().

## ◆ TEST() [442/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractAndRequireRadiiAdjustment |
| ) |  |

Definition at line 555 of file round_superellipse_unittests.cc.

555 {
556 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
557 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
558 {
559 .top_left = Size(1.0f, 2.0f),
560 .top_right = Size(3.0f, 4.0f),
561 .bottom_left = Size(5.0f, 6.0f),
562 .bottom_right = Size(7.0f, 8.0f),
563 });
564 RoundSuperellipse expanded = rse.Expand(-12.0);
565 // Largest sum of paired radii sizes are the bottom and right edges
566 // both of which sum to 12
567 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
568 // radii are scaled by half to avoid overflowing the contracted rect
569
570 EXPECT_FALSE(expanded.IsEmpty());
571 EXPECT_FALSE(expanded.IsRect());
572 EXPECT_FALSE(expanded.IsOval());
573 EXPECT_TRUE(expanded.IsFinite());
574 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
575 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
576 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
577 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
578 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
579 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
580
581 // In this test, the MakeRectRadii constructor will make the same
582 // adjustment to the radii that the Expand method applied.
583 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
584 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
585 {
586 .top_left = Size(1.0f, 2.0f),
587 .top_right = Size(3.0f, 4.0f),
588 .bottom_left = Size(5.0f, 6.0f),
589 .bottom_right = Size(7.0f, 8.0f),
590 }));
591
592 // In this test, the arguments to the constructor supply the correctly
593 // adjusted radii (though there is no real way to tell other than
594 // the result is the same).
595 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
596 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
597 {
598 .top_left = Size(0.5f, 1.0f),
599 .top_right = Size(1.5f, 2.0f),
600 .bottom_left = Size(2.5f, 3.0f),
601 .bottom_right = Size(3.5f, 4.0f),
602 }));
603 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [443/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractFourScalars |
| ) |  |

Definition at line 523 of file round_superellipse_unittests.cc.

523 {
524 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
525 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
526 {
527 .top_left = Size(1.0f, 2.0f),
528 .top_right = Size(3.0f, 4.0f),
529 .bottom_left = Size(5.0f, 6.0f),
530 .bottom_right = Size(7.0f, 8.0f),
531 });
532 RoundSuperellipse expanded = rse.Expand(-1.0, -1.5, -2.0, -2.5);
533
534 EXPECT_FALSE(expanded.IsEmpty());
535 EXPECT_FALSE(expanded.IsRect());
536 EXPECT_FALSE(expanded.IsOval());
537 EXPECT_TRUE(expanded.IsFinite());
538 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
539 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
540 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
541 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
542 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
543 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
544
545 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
546 Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
547 {
548 .top_left = Size(1.0f, 2.0f),
549 .top_right = Size(3.0f, 4.0f),
550 .bottom_left = Size(5.0f, 6.0f),
551 .bottom_right = Size(7.0f, 8.0f),
552 }));
553 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [444/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractScalar |
| ) |  |

Definition at line 459 of file round_superellipse_unittests.cc.

459 {
460 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
461 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
462 {
463 .top_left = Size(1.0f, 2.0f),
464 .top_right = Size(3.0f, 4.0f),
465 .bottom_left = Size(5.0f, 6.0f),
466 .bottom_right = Size(7.0f, 8.0f),
467 });
468 RoundSuperellipse expanded = rse.Expand(-2.0);
469
470 EXPECT_FALSE(expanded.IsEmpty());
471 EXPECT_FALSE(expanded.IsRect());
472 EXPECT_FALSE(expanded.IsOval());
473 EXPECT_TRUE(expanded.IsFinite());
474 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
475 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
476 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
477 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
478 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
479 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
480
481 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
482 Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
483 {
484 .top_left = Size(1.0f, 2.0f),
485 .top_right = Size(3.0f, 4.0f),
486 .bottom_left = Size(5.0f, 6.0f),
487 .bottom_right = Size(7.0f, 8.0f),
488 }));
489 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [445/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractTwoScalars |
| ) |  |

Definition at line 491 of file round_superellipse_unittests.cc.

491 {
492 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
493 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
494 {
495 .top_left = Size(1.0f, 2.0f),
496 .top_right = Size(3.0f, 4.0f),
497 .bottom_left = Size(5.0f, 6.0f),
498 .bottom_right = Size(7.0f, 8.0f),
499 });
500 RoundSuperellipse expanded = rse.Expand(-1.0, -2.0);
501
502 EXPECT_FALSE(expanded.IsEmpty());
503 EXPECT_FALSE(expanded.IsRect());
504 EXPECT_FALSE(expanded.IsOval());
505 EXPECT_TRUE(expanded.IsFinite());
506 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
507 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
508 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
509 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
510 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
511 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
512
513 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
514 Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
515 {
516 .top_left = Size(1.0f, 2.0f),
517 .top_right = Size(3.0f, 4.0f),
518 .bottom_left = Size(5.0f, 6.0f),
519 .bottom_right = Size(7.0f, 8.0f),
520 }));
521 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [446/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | DefaultConstructor |
| ) |  |

Definition at line 100 of file round_superellipse_unittests.cc.

100 {
101 RoundSuperellipse rse = RoundSuperellipse();
102
103 EXPECT_TRUE(rse.IsEmpty());
104 EXPECT_FALSE(rse.IsRect());
105 EXPECT_FALSE(rse.IsOval());
106 EXPECT_TRUE(rse.IsFinite());
107 EXPECT_TRUE(rse.GetBounds().IsEmpty());
108 EXPECT_EQ(rse.GetBounds(), Rect());
109 EXPECT_EQ(rse.GetRadii().top_left, Size());
110 EXPECT_EQ(rse.GetRadii().top_right, Size());
111 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
112 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
113 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [447/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyDeclaration |
| ) |  |

Definition at line 73 of file round_superellipse_unittests.cc.

73 {
74 RoundSuperellipse rse;
75
76 EXPECT_TRUE(rse.IsEmpty());
77 EXPECT_FALSE(rse.IsRect());
78 EXPECT_FALSE(rse.IsOval());
79 EXPECT_TRUE(rse.IsFinite());
80 EXPECT_TRUE(rse.GetBounds().IsEmpty());
81 EXPECT_EQ(rse.GetBounds(), Rect());
82 EXPECT_EQ(rse.GetBounds().GetLeft(), 0.0f);
83 EXPECT_EQ(rse.GetBounds().GetTop(), 0.0f);
84 EXPECT_EQ(rse.GetBounds().GetRight(), 0.0f);
85 EXPECT_EQ(rse.GetBounds().GetBottom(), 0.0f);
86 EXPECT_EQ(rse.GetRadii().top_left, Size());
87 EXPECT_EQ(rse.GetRadii().top_right, Size());
88 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
89 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
90 EXPECT_EQ(rse.GetRadii().top_left.width, 0.0f);
91 EXPECT_EQ(rse.GetRadii().top_left.height, 0.0f);
92 EXPECT_EQ(rse.GetRadii().top_right.width, 0.0f);
93 EXPECT_EQ(rse.GetRadii().top_right.height, 0.0f);
94 EXPECT_EQ(rse.GetRadii().bottom_left.width, 0.0f);
95 EXPECT_EQ(rse.GetRadii().bottom_left.height, 0.0f);
96 EXPECT_EQ(rse.GetRadii().bottom_right.width, 0.0f);
97 EXPECT_EQ(rse.GetRadii().bottom_right.height, 0.0f);
98 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::TRect< T >::GetBottom(), impeller::RoundSuperellipse::GetBounds(), impeller::TRect< T >::GetLeft(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TSize< T >::height, impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::RoundingRadii::top_left, impeller::RoundingRadii::top_right, and impeller::TSize< T >::width.

## ◆ TEST() [448/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyOvalConstruction |
| ) |  |

Definition at line 163 of file round_superellipse_unittests.cc.

163 {
164 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
165 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
166
167 EXPECT_TRUE(rse.IsEmpty());
168 EXPECT_FALSE(rse.IsRect());
169 EXPECT_FALSE(rse.IsOval());
170 EXPECT_TRUE(rse.IsFinite());
171 EXPECT_TRUE(rse.GetBounds().IsEmpty());
172 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
173 EXPECT_EQ(rse.GetRadii().top_left, Size());
174 EXPECT_EQ(rse.GetRadii().top_right, Size());
175 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
176 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
177 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [449/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyRectConstruction |
| ) |  |

Definition at line 115 of file round_superellipse_unittests.cc.

115 {
116 RoundSuperellipse rse =
117 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
118
119 EXPECT_TRUE(rse.IsEmpty());
120 EXPECT_FALSE(rse.IsRect());
121 EXPECT_FALSE(rse.IsOval());
122 EXPECT_TRUE(rse.IsFinite());
123 EXPECT_TRUE(rse.GetBounds().IsEmpty());
124 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
125 EXPECT_EQ(rse.GetRadii().top_left, Size());
126 EXPECT_EQ(rse.GetRadii().top_right, Size());
127 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
128 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
129 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [450/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandFourScalars |
| ) |  |

Definition at line 427 of file round_superellipse_unittests.cc.

427 {
428 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
429 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
430 {
431 .top_left = Size(1.0f, 2.0f),
432 .top_right = Size(3.0f, 4.0f),
433 .bottom_left = Size(5.0f, 6.0f),
434 .bottom_right = Size(7.0f, 8.0f),
435 });
436 RoundSuperellipse expanded = rse.Expand(5.0, 6.0, 7.0, 8.0);
437
438 EXPECT_FALSE(expanded.IsEmpty());
439 EXPECT_FALSE(expanded.IsRect());
440 EXPECT_FALSE(expanded.IsOval());
441 EXPECT_TRUE(expanded.IsFinite());
442 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
443 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
444 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
445 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
446 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
447 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
448
449 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
450 Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
451 {
452 .top_left = Size(1.0f, 2.0f),
453 .top_right = Size(3.0f, 4.0f),
454 .bottom_left = Size(5.0f, 6.0f),
455 .bottom_right = Size(7.0f, 8.0f),
456 }));
457 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [451/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandScalar |
| ) |  |

Definition at line 363 of file round_superellipse_unittests.cc.

363 {
364 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
365 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
366 {
367 .top_left = Size(1.0f, 2.0f),
368 .top_right = Size(3.0f, 4.0f),
369 .bottom_left = Size(5.0f, 6.0f),
370 .bottom_right = Size(7.0f, 8.0f),
371 });
372 RoundSuperellipse expanded = rse.Expand(5.0);
373
374 EXPECT_FALSE(expanded.IsEmpty());
375 EXPECT_FALSE(expanded.IsRect());
376 EXPECT_FALSE(expanded.IsOval());
377 EXPECT_TRUE(expanded.IsFinite());
378 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
379 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
380 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
381 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
382 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
383 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
384
385 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
386 Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
387 {
388 .top_left = Size(1.0f, 2.0f),
389 .top_right = Size(3.0f, 4.0f),
390 .bottom_left = Size(5.0f, 6.0f),
391 .bottom_right = Size(7.0f, 8.0f),
392 }));
393 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [452/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandTwoScalars |
| ) |  |

Definition at line 395 of file round_superellipse_unittests.cc.

395 {
396 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
397 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
398 {
399 .top_left = Size(1.0f, 2.0f),
400 .top_right = Size(3.0f, 4.0f),
401 .bottom_left = Size(5.0f, 6.0f),
402 .bottom_right = Size(7.0f, 8.0f),
403 });
404 RoundSuperellipse expanded = rse.Expand(5.0, 6.0);
405
406 EXPECT_FALSE(expanded.IsEmpty());
407 EXPECT_FALSE(expanded.IsRect());
408 EXPECT_FALSE(expanded.IsOval());
409 EXPECT_TRUE(expanded.IsFinite());
410 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
411 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
412 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
413 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
414 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
415 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
416
417 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
418 Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
419 {
420 .top_left = Size(1.0f, 2.0f),
421 .top_right = Size(3.0f, 4.0f),
422 .bottom_left = Size(5.0f, 6.0f),
423 .bottom_right = Size(7.0f, 8.0f),
424 }));
425 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [453/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | InvertedOvalConstruction |
| ) |  |

Definition at line 195 of file round_superellipse_unittests.cc.

195 {
196 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
197 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
198
199 EXPECT_FALSE(rse.IsEmpty());
200 EXPECT_FALSE(rse.IsRect());
201 EXPECT_TRUE(rse.IsOval());
202 EXPECT_TRUE(rse.IsFinite());
203 EXPECT_FALSE(rse.GetBounds().IsEmpty());
204 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
205 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
206 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
207 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
208 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
209 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [454/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | InvertedRectConstruction |
| ) |  |

Definition at line 147 of file round_superellipse_unittests.cc.

147 {
148 RoundSuperellipse rse =
149 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
150
151 EXPECT_FALSE(rse.IsEmpty());
152 EXPECT_TRUE(rse.IsRect());
153 EXPECT_FALSE(rse.IsOval());
154 EXPECT_TRUE(rse.IsFinite());
155 EXPECT_FALSE(rse.GetBounds().IsEmpty());
156 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
157 EXPECT_EQ(rse.GetRadii().top_left, Size());
158 EXPECT_EQ(rse.GetRadii().top_right, Size());
159 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
160 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
161 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [455/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | NoCornerRoundSuperellipseContains |
| ) |  |

Definition at line 605 of file round_superellipse_unittests.cc.

605 {
606 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
607 // Rounded superellipses of bounds with no corners contains corners just
608 // barely.
609 auto no_corners = RoundSuperellipse::MakeRectRadii(
610 bounds, RoundingRadii::MakeRadii({0.0f, 0.0f}));
611
612 EXPECT_TRUE(no_corners.Contains({-50, -50}));
613 // Rectangles have half-in, half-out containment so we need
614 // to be careful about testing containment of right/bottom corners.
615 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
616 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
617 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
618 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
619 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
620 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
621 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
622 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
623 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
624 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
625 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
626 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [456/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | OvalConstructor |
| ) |  |

Definition at line 179 of file round_superellipse_unittests.cc.

179 {
180 RoundSuperellipse rse =
181 RoundSuperellipse::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
182
183 EXPECT_FALSE(rse.IsEmpty());
184 EXPECT_FALSE(rse.IsRect());
185 EXPECT_TRUE(rse.IsOval());
186 EXPECT_TRUE(rse.IsFinite());
187 EXPECT_FALSE(rse.GetBounds().IsEmpty());
188 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
189 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
190 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
191 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
192 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
193 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeOval(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [457/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | PathForLongRseShouldBeCorrect |
| ) |  |

Definition at line 794 of file round_superellipse_unittests.cc.

794 {
795 Rect bounds = Rect::MakeLTRB(0, 0, 300, 100000);
796 // Regression test for https://github.com/flutter/flutter/issues/179875.
797
798 auto rr = RoundSuperellipseParam::MakeBoundsRadius(bounds, 100);
799 SpyPathReceiver receiver;
800 receiver.SpyLineTo(
801 [&](const Point& p2) { EXPECT_TRUE(bounds.ContainsInclusive(p2)); });
802 receiver.SpyCubicTo([&](const Point& cp1, const Point& cp2, const Point& p2) {
803 EXPECT_TRUE(bounds.ContainsInclusive(cp1));
804 EXPECT_TRUE(bounds.ContainsInclusive(cp2));
805 EXPECT_TRUE(bounds.ContainsInclusive(p2));
806 });
807 receiver.SpyConicTo([&](const Point& cp, const Point& p2, Scalar weight) {
808 EXPECT_TRUE(bounds.ContainsInclusive(cp));
809 EXPECT_TRUE(bounds.ContainsInclusive(p2));
810 });
811
812 rr.Dispatch(receiver);
813 }
weight
Scalar weight
Definition: round_superellipse_param.cc:319

References impeller::TRect< T >::ContainsInclusive(), impeller::RoundSuperellipseParam::MakeBoundsRadius(), impeller::TRect< Scalar >::MakeLTRB(), p2, and weight.

## ◆ TEST() [458/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | PathForRectangularRseWithShapeCornersShouldBeWithinBounds |
| ) |  |

Definition at line 767 of file round_superellipse_unittests.cc.

768 {
769 Rect bounds = Rect::MakeLTRB(34.0f, 242.0f, 766.0f, 358.0f);
770 // Regression test for https://github.com/flutter/flutter/issues/170593.
771 // The issue was caused by incorrect calculation when building paths for
772 // rounded superellipses with sharp corners and unequal width and height.
773 // Since the most obvious symptom of the issue is some points being
774 // incorrectly placed out of bounds, this test case simply verifies that all
775 // points are within the bounds.
776
777 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
778 bounds, {
779 .top_left = Size(14.0, 14.0),
780 .top_right = Size(14.0, 14.0),
781 .bottom_left = Size(0.0, 0.0),
782 .bottom_right = Size(0.0, 0.0),
783 });
784 SpyPathReceiver receiver;
785 receiver.SpyLineTo(
786 [&](const Point& p2) { EXPECT_TRUE(bounds.ContainsInclusive(p2)); });
787 receiver.SpyCubicTo([&](const Point& cp1, const Point& cp2, const Point& p2) {
788 EXPECT_TRUE(bounds.ContainsInclusive(p2));
789 });
790
791 rr.Dispatch(receiver);
792 }

References impeller::TRect< T >::ContainsInclusive(), impeller::RoundSuperellipseParam::Dispatch(), impeller::RoundSuperellipseParam::MakeBoundsRadii(), impeller::TRect< Scalar >::MakeLTRB(), and p2.

## ◆ TEST() [459/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | PointsOutsideOfSharpCorner |
| ) |  |

Definition at line 750 of file round_superellipse_unittests.cc.

750 {
751 Rect bounds = Rect::MakeLTRB(196.0f, 0.0f, 294.0f, 28.0f);
752 // Regression test for a case where RoundSuperellipseParam::Contains
753 // previously failed. Although the bounding rect filter of
754 // `RoundSuperellipse::Contains` would reject this point, this test ensures
755 // the internal logic of RoundSuperellipseParam::Contains is now correct.
756 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
757 bounds, {
758 .top_left = Size(0.0, 0.0),
759 .top_right = Size(3.0, 3.0),
760 .bottom_left = Size(0.0, 0.0),
761 .bottom_right = Size(3.0, 3.0),
762 });
763
764 EXPECT_FALSE(rr.Contains(Point{147.0, 14.0}));
765 }

References impeller::RoundSuperellipseParam::MakeBoundsRadii(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [460/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectConstructor |
| ) |  |

Definition at line 131 of file round_superellipse_unittests.cc.

131 {
132 RoundSuperellipse rse =
133 RoundSuperellipse::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
134
135 EXPECT_FALSE(rse.IsEmpty());
136 EXPECT_TRUE(rse.IsRect());
137 EXPECT_FALSE(rse.IsOval());
138 EXPECT_TRUE(rse.IsFinite());
139 EXPECT_FALSE(rse.GetBounds().IsEmpty());
140 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
141 EXPECT_EQ(rse.GetRadii().top_left, Size());
142 EXPECT_EQ(rse.GetRadii().top_right, Size());
143 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
144 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
145 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRect(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [461/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiConstructor |
| ) |  |

Definition at line 259 of file round_superellipse_unittests.cc.

259 {
260 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
261 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
262 {
263 .top_left = Size(1.0, 1.5),
264 .top_right = Size(2.0, 2.5f),
265 .bottom_left = Size(3.0, 3.5f),
266 .bottom_right = Size(4.0, 4.5f),
267 });
268
269 EXPECT_FALSE(rse.IsEmpty());
270 EXPECT_FALSE(rse.IsRect());
271 EXPECT_FALSE(rse.IsOval());
272 EXPECT_TRUE(rse.IsFinite());
273 EXPECT_FALSE(rse.GetBounds().IsEmpty());
274 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
275 EXPECT_EQ(rse.GetRadii().top_left, Size(1.0f, 1.5f));
276 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.5f));
277 EXPECT_EQ(rse.GetRadii().bottom_left, Size(3.0f, 3.5f));
278 EXPECT_EQ(rse.GetRadii().bottom_right, Size(4.0f, 4.5f));
279 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [462/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiOverflowHeightConstructor |
| ) |  |

Definition at line 306 of file round_superellipse_unittests.cc.

306 {
307 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
308 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
309 {
310 .top_left = Size(1.0f, 2.0f),
311 .top_right = Size(3.0f, 4.0f),
312 .bottom_left = Size(5.0f, 6.0f),
313 .bottom_right = Size(7.0f, 8.0f),
314 });
315 // Largest sum of paired radii heights is the right edge which sums to 12
316 // Rect is only 6 tall so all radii are scaled by half
317 // Rect is 30 wide so no scaling should happen due to radii widths
318
319 EXPECT_FALSE(rse.IsEmpty());
320 EXPECT_FALSE(rse.IsRect());
321 EXPECT_FALSE(rse.IsOval());
322 EXPECT_TRUE(rse.IsFinite());
323 EXPECT_FALSE(rse.GetBounds().IsEmpty());
324 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
325 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
326 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
327 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
328 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
329 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [463/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiOverflowWidthConstructor |
| ) |  |

Definition at line 281 of file round_superellipse_unittests.cc.

281 {
282 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
283 Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
284 {
285 .top_left = Size(1.0f, 2.0f),
286 .top_right = Size(3.0f, 4.0f),
287 .bottom_left = Size(5.0f, 6.0f),
288 .bottom_right = Size(7.0f, 8.0f),
289 });
290 // Largest sum of paired radii widths is the bottom edge which sums to 12
291 // Rect is only 6 wide so all radii are scaled by half
292 // Rect is 30 tall so no scaling should happen due to radii heights
293
294 EXPECT_FALSE(rse.IsEmpty());
295 EXPECT_FALSE(rse.IsRect());
296 EXPECT_FALSE(rse.IsOval());
297 EXPECT_TRUE(rse.IsFinite());
298 EXPECT_FALSE(rse.GetBounds().IsEmpty());
299 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
300 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
301 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
302 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
303 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
304 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [464/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiusConstructor |
| ) |  |

Definition at line 211 of file round_superellipse_unittests.cc.

211 {
212 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadius(
213 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
214
215 EXPECT_FALSE(rse.IsEmpty());
216 EXPECT_FALSE(rse.IsRect());
217 EXPECT_FALSE(rse.IsOval());
218 EXPECT_TRUE(rse.IsFinite());
219 EXPECT_FALSE(rse.GetBounds().IsEmpty());
220 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
221 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 2.0f));
222 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.0f));
223 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 2.0f));
224 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 2.0f));
225 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [465/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectSizeConstructor |
| ) |  |

Definition at line 243 of file round_superellipse_unittests.cc.

243 {
244 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
245 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
246
247 EXPECT_FALSE(rse.IsEmpty());
248 EXPECT_FALSE(rse.IsRect());
249 EXPECT_FALSE(rse.IsOval());
250 EXPECT_TRUE(rse.IsFinite());
251 EXPECT_FALSE(rse.GetBounds().IsEmpty());
252 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
253 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
254 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
255 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
256 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
257 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [466/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectXYConstructor |
| ) |  |

Definition at line 227 of file round_superellipse_unittests.cc.

227 {
228 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
229 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
230
231 EXPECT_FALSE(rse.IsEmpty());
232 EXPECT_FALSE(rse.IsRect());
233 EXPECT_FALSE(rse.IsOval());
234 EXPECT_TRUE(rse.IsFinite());
235 EXPECT_FALSE(rse.GetBounds().IsEmpty());
236 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
237 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
238 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
239 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
240 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
241 }

References impeller::RoundingRadii::bottom_left, impeller::RoundingRadii::bottom_right, impeller::RoundSuperellipse::GetBounds(), impeller::RoundSuperellipse::GetRadii(), impeller::TRect< T >::IsEmpty(), impeller::RoundSuperellipse::IsEmpty(), impeller::RoundSuperellipse::IsFinite(), impeller::RoundSuperellipse::IsOval(), impeller::RoundSuperellipse::IsRect(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectXY(), impeller::RoundingRadii::top_left, and impeller::RoundingRadii::top_right.

## ◆ TEST() [467/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | Shift |
| ) |  |

Definition at line 331 of file round_superellipse_unittests.cc.

331 {
332 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
333 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
334 {
335 .top_left = Size(1.0f, 2.0f),
336 .top_right = Size(3.0f, 4.0f),
337 .bottom_left = Size(5.0f, 6.0f),
338 .bottom_right = Size(7.0f, 8.0f),
339 });
340 RoundSuperellipse shifted = rse.Shift(5.0, 6.0);
341
342 EXPECT_FALSE(shifted.IsEmpty());
343 EXPECT_FALSE(shifted.IsRect());
344 EXPECT_FALSE(shifted.IsOval());
345 EXPECT_TRUE(shifted.IsFinite());
346 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
347 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
348 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
349 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
350 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
351 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
352
353 EXPECT_EQ(shifted, RoundSuperellipse::MakeRectRadii(
354 Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
355 {
356 .top_left = Size(1.0f, 2.0f),
357 .top_right = Size(3.0f, 4.0f),
358 .bottom_left = Size(5.0f, 6.0f),
359 .bottom_right = Size(7.0f, 8.0f),
360 }));
361 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::RoundSuperellipse::Shift().

## ◆ TEST() [468/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | SlimDiagonalContains |
| ) |  |

Definition at line 713 of file round_superellipse_unittests.cc.

713 {
714 // This shape has large radii on one diagonal and tiny radii on the other,
715 // resulting in a almond-like shape placed diagonally (NW to SE).
716 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
717 auto rr = RoundSuperellipse::MakeRectRadii(
718 bounds, {
719 .top_left = Size(1.0, 1.0),
720 .top_right = Size(99.0, 99.0),
721 .bottom_left = Size(99.0, 99.0),
722 .bottom_right = Size(1.0, 1.0),
723 });
724
725 EXPECT_TRUE(rr.Contains(Point{0, 0}));
726 EXPECT_FALSE(rr.Contains(Point{-49.999, -49.999}));
727 EXPECT_FALSE(rr.Contains(Point{-49.999, 49.999}));
728 EXPECT_FALSE(rr.Contains(Point{49.999, 49.999}));
729 EXPECT_FALSE(rr.Contains(Point{49.999, -49.999}));
730
731 // The pointy ends at the NE and SW corners
732 CHECK_POINT_WITH_OFFSET(rr, Point(-49.70, -49.70), Point(-0.02, -0.02));
733 CHECK_POINT_WITH_OFFSET(rr, Point(49.70, 49.70), Point(0.02, 0.02));
734
735 // Checks two points symmetrical to the origin.
736 #define CHECK_DIAGONAL_POINTS(p) \
737 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, -0.02)); \
738 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, 0.02));
739
740 // A few other points along the edge
741 CHECK_DIAGONAL_POINTS(Point(-40.0, -49.59));
742 CHECK_DIAGONAL_POINTS(Point(-20.0, -45.64));
743 CHECK_DIAGONAL_POINTS(Point(0.0, -37.01));
744 CHECK_DIAGONAL_POINTS(Point(20.0, -21.96));
745 CHECK_DIAGONAL_POINTS(Point(21.05, -20.92));
746 CHECK_DIAGONAL_POINTS(Point(40.0, 5.68));
747 #undef CHECK_POINT_AND_MIRRORS
748 }
CHECK_DIAGONAL_POINTS
#define CHECK_DIAGONAL_POINTS(p)
CHECK_POINT_WITH_OFFSET
#define CHECK_POINT_WITH_OFFSET(rr, p, outward_offset)
Definition: round_superellipse_unittests.cc:12

References CHECK_DIAGONAL_POINTS, CHECK_POINT_WITH_OFFSET, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [469/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | TinyCornerContains |
| ) |  |

Definition at line 628 of file round_superellipse_unittests.cc.

628 {
629 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
630 // Rounded superellipses of bounds with even the tiniest corners does not
631 // contain corners.
632 auto tiny_corners = RoundSuperellipse::MakeRectRadii(
633 bounds, RoundingRadii::MakeRadii({0.01f, 0.01f}));
634
635 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
636 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
637 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
638 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
639 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [470/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformEllipticalContains |
| ) |  |

Definition at line 662 of file round_superellipse_unittests.cc.

662 {
663 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
664 auto rr = RoundSuperellipse::MakeRectRadii(
665 bounds, RoundingRadii::MakeRadii({5.0f, 10.0f}));
666
667 #define CHECK_POINT_AND_MIRRORS(p) \
668 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
669 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
670 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
671 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
672
673 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
674 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.911)); // Top curve start
675 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.75)); // Top joint
676 CHECK_POINT_AND_MIRRORS(Point(48.51, 47.07)); // Circular arc mid
677 CHECK_POINT_AND_MIRRORS(Point(49.87, 41.44)); // Right joint
678 CHECK_POINT_AND_MIRRORS(Point(49.95, 38.49)); // Right curve start
679 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
680 #undef CHECK_POINT_AND_MIRRORS
681 }
CHECK_POINT_AND_MIRRORS
#define CHECK_POINT_AND_MIRRORS(p)

References CHECK_POINT_AND_MIRRORS, impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [471/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformRectangularContains |
| ) |  |

Definition at line 683 of file round_superellipse_unittests.cc.

683 {
684 // The bounds is not centered at the origin and has unequal height and width.
685 Rect bounds = Rect::MakeLTRB(0.0f, 0.0f, 50.0f, 100.0f);
686 auto rr = RoundSuperellipse::MakeRectRadii(
687 bounds, RoundingRadii::MakeRadii({23.0f, 30.0f}));
688
689 Point center = bounds.GetCenter();
690 #define CHECK_POINT_AND_MIRRORS(p) \
691 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, 1) + center, \
692 Point(0.02, 0.02)); \
693 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, -1) + center, \
694 Point(0.02, -0.02)); \
695 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, 1) + center, \
696 Point(-0.02, 0.02)); \
697 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, -1) + center, \
698 Point(-0.02, -0.02));
699
700 CHECK_POINT_AND_MIRRORS(Point(24.99, 99.99)); // Bottom mid edge
701 CHECK_POINT_AND_MIRRORS(Point(29.99, 99.64));
702 CHECK_POINT_AND_MIRRORS(Point(34.99, 98.06));
703 CHECK_POINT_AND_MIRRORS(Point(39.99, 94.73));
704 CHECK_POINT_AND_MIRRORS(Point(44.13, 89.99));
705 CHECK_POINT_AND_MIRRORS(Point(48.46, 79.99));
706 CHECK_POINT_AND_MIRRORS(Point(49.70, 69.99));
707 CHECK_POINT_AND_MIRRORS(Point(49.97, 59.99));
708 CHECK_POINT_AND_MIRRORS(Point(49.99, 49.99)); // Right mid edge
709
710 #undef CHECK_POINT_AND_MIRRORS
711 }

References CHECK_POINT_AND_MIRRORS, impeller::TRect< T >::GetCenter(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [472/574]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformSquareContains |
| ) |  |

Definition at line 641 of file round_superellipse_unittests.cc.

641 {
642 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
643 auto rr = RoundSuperellipse::MakeRectRadii(
644 bounds, RoundingRadii::MakeRadii({5.0f, 5.0f}));
645
646 #define CHECK_POINT_AND_MIRRORS(p) \
647 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
648 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
649 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
650 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
651
652 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
653 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.95)); // Top curve start
654 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.87)); // Top joint
655 CHECK_POINT_AND_MIRRORS(Point(48.53, 48.53)); // Circular arc mid
656 CHECK_POINT_AND_MIRRORS(Point(49.87, 45.72)); // Right joint
657 CHECK_POINT_AND_MIRRORS(Point(49.95, 44.245)); // Right curve start
658 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
659 #undef CHECK_POINT_AND_MIRRORS
660 }

References CHECK_POINT_AND_MIRRORS, impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [473/574]

impeller::testing::TEST | ( | RSTransformTest | ,
|  | CompareToMatrix |
| ) |  |

Definition at line 32 of file rstransform_unittests.cc.

32 {
33 for (int tx = 0; tx <= 100; tx += 10) {
34 for (int ty = 0; ty <= 100; ty += 10) {
35 Point origin(tx, ty);
36 for (int scale = 1; scale <= 20; scale += 5) {
37 // Overshoot a full circle by 30 degrees
38 for (int degrees = 0; degrees <= 390; degrees += 45) {
39 auto matrix = Matrix::MakeTranslation(origin) *
40 Matrix::MakeRotationZ(Degrees(degrees)) *
41 Matrix::MakeScale(Vector2(scale, scale));
42 auto rst = RSTransform::Make(origin, scale, Degrees(degrees));
43 EXPECT_MATRIX_NEAR(rst.GetMatrix(), matrix);
44 for (int w = 10; w <= 100; w += 10) {
45 for (int h = 10; h <= 100; h += 10) {
46 Quad q = rst.GetQuad(w, h);
47 auto points = Rect::MakeWH(w, h).GetTransformedPoints(matrix);
48 for (int i = 0; i < 4; i++) {
49 EXPECT_NEAR(q[i].x, points[i].x, kEhCloseEnough);
50 EXPECT_NEAR(q[i].y, points[i].y, kEhCloseEnough);
51 }
52 }
53 }
54 }
55 }
56 }
57 }
58 }
EXPECT_MATRIX_NEAR
#define EXPECT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:201

References EXPECT_MATRIX_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::kEhCloseEnough, impeller::RSTransform::Make(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeWH(), points, and x.

## ◆ TEST() [474/574]

impeller::testing::TEST | ( | RSTransformTest | ,
|  | Construction |
| ) |  |

Definition at line 14 of file rstransform_unittests.cc.

14 {
15 RSTransform transform = RSTransform::Make({10.0f, 12.0f}, 2.0f, Degrees(90));
16
17 EXPECT_EQ(transform.scaled_cos, 0.0f);
18 EXPECT_EQ(transform.scaled_sin, 2.0f);
19 EXPECT_EQ(transform.translate_x, 10.0f);
20 EXPECT_EQ(transform.translate_y, 12.0f);
21
22 EXPECT_EQ(transform.GetBounds(20.0f, 30.0f),
23 // relative corners are at
24 // 0, 0
25 // 0, 40
26 // -60, 0
27 // -60, 40
28 // then add 10, 12 to all values
29 Rect::MakeLTRB(10 + -2 * 30, 12 + 0, 10 + 0, 12 + 40));
30 }

References impeller::RSTransform::Make(), impeller::TRect< Scalar >::MakeLTRB(), and transform.

## ◆ TEST() [475/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingFiniteDoubleToFloatStaysFinite |
| ) |  |

Definition at line 981 of file saturated_math_unittests.cc.

981 {
982 const double d_max = std::numeric_limits<double>::max();
983 const float f_max = std::numeric_limits<float>::max();
984
985 {
986 const float result = saturated::Cast<double, float>(d_max);
987 EXPECT_EQ(result, f_max);
988 }
989
990 {
991 const float result = saturated::Cast<double, float>(-d_max);
992 EXPECT_EQ(result, -f_max);
993 }
994 }

## ◆ TEST() [476/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingInfiniteDoubleToFloatStaysInfinite |
| ) |  |

Definition at line 996 of file saturated_math_unittests.cc.

996 {
997 const double d_inf = std::numeric_limits<double>::infinity();
998 const float f_max = std::numeric_limits<float>::infinity();
999
1000 {
1001 const float result = saturated::Cast<double, float>(d_inf);
1002 EXPECT_EQ(result, f_max);
1003 }
1004
1005 {
1006 const float result = saturated::Cast<double, float>(-d_inf);
1007 EXPECT_EQ(result, -f_max);
1008 }
1009 }

## ◆ TEST() [477/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingInfiniteScalarToSignedIntProducesLimit |
| ) |  |

Definition at line 1066 of file saturated_math_unittests.cc.

1066 {
1067 // larger than even any [u]int64_t;
1068 const Scalar inf = std::numeric_limits<Scalar>::infinity();
1069
1070 {
1071 const auto result = saturated::Cast<Scalar, int8_t>(inf);
1072 EXPECT_EQ(result, int8_t(0x7F));
1073 }
1074 {
1075 const auto result = saturated::Cast<Scalar, int8_t>(-inf);
1076 EXPECT_EQ(result, int8_t(0x80));
1077 }
1078
1079 {
1080 const auto result = saturated::Cast<Scalar, int16_t>(inf);
1081 EXPECT_EQ(result, int16_t(0x7FFF));
1082 }
1083 {
1084 const auto result = saturated::Cast<Scalar, int16_t>(-inf);
1085 EXPECT_EQ(result, int16_t(0x8000));
1086 }
1087
1088 {
1089 const auto result = saturated::Cast<Scalar, int32_t>(inf);
1090 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1091 }
1092 {
1093 const auto result = saturated::Cast<Scalar, int32_t>(-inf);
1094 EXPECT_EQ(result, int32_t(0x80000000));
1095 }
1096
1097 {
1098 const auto result = saturated::Cast<Scalar, int64_t>(inf);
1099 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1100 }
1101 {
1102 const auto result = saturated::Cast<Scalar, int64_t>(-inf);
1103 EXPECT_EQ(result, int64_t(0x8000000000000000));
1104 }
1105 }

## ◆ TEST() [478/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingLargeScalarToSignedIntProducesLimit |
| ) |  |

Definition at line 1025 of file saturated_math_unittests.cc.

1025 {
1026 // larger than even any [u]int64_t;
1027 const Scalar large = 1e20f;
1028
1029 {
1030 const auto result = saturated::Cast<Scalar, int8_t>(large);
1031 EXPECT_EQ(result, int8_t(0x7F));
1032 }
1033 {
1034 const auto result = saturated::Cast<Scalar, int8_t>(-large);
1035 EXPECT_EQ(result, int8_t(0x80));
1036 }
1037
1038 {
1039 const auto result = saturated::Cast<Scalar, int16_t>(large);
1040 EXPECT_EQ(result, int16_t(0x7FFF));
1041 }
1042 {
1043 const auto result = saturated::Cast<Scalar, int16_t>(-large);
1044 EXPECT_EQ(result, int16_t(0x8000));
1045 }
1046
1047 {
1048 const auto result = saturated::Cast<Scalar, int32_t>(large);
1049 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1050 }
1051 {
1052 const auto result = saturated::Cast<Scalar, int32_t>(-large);
1053 EXPECT_EQ(result, int32_t(0x80000000));
1054 }
1055
1056 {
1057 const auto result = saturated::Cast<Scalar, int64_t>(large);
1058 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1059 }
1060 {
1061 const auto result = saturated::Cast<Scalar, int64_t>(-large);
1062 EXPECT_EQ(result, int64_t(0x8000000000000000));
1063 }
1064 }

## ◆ TEST() [479/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingNaNDoubleToFloatStaysNaN |
| ) |  |

Definition at line 1011 of file saturated_math_unittests.cc.

1011 {
1012 const double d_nan = std::numeric_limits<double>::quiet_NaN();
1013
1014 {
1015 const float result = saturated::Cast<double, float>(d_nan);
1016 EXPECT_TRUE(std::isnan(result));
1017 }
1018
1019 {
1020 const float result = saturated::Cast<double, float>(-d_nan);
1021 EXPECT_TRUE(std::isnan(result));
1022 }
1023 }

## ◆ TEST() [480/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingNaNScalarToSignedIntProducesZero |
| ) |  |

Definition at line 1107 of file saturated_math_unittests.cc.

1107 {
1108 // larger than even any [u]int64_t;
1109 const Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1110
1111 {
1112 const auto result = saturated::Cast<Scalar, int8_t>(nan);
1113 EXPECT_EQ(result, int8_t(0));
1114 }
1115
1116 {
1117 const auto result = saturated::Cast<Scalar, int16_t>(nan);
1118 EXPECT_EQ(result, int16_t(0));
1119 }
1120
1121 {
1122 const auto result = saturated::Cast<Scalar, int32_t>(nan);
1123 EXPECT_EQ(result, int32_t(0));
1124 }
1125
1126 {
1127 const auto result = saturated::Cast<Scalar, int64_t>(nan);
1128 EXPECT_EQ(result, int64_t(0));
1129 }
1130 }

## ◆ TEST() [481/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAddOfFloatingPoint |
| ) |  |

Definition at line 136 of file saturated_math_unittests.cc.

136 {
137 {
138 const float inf = std::numeric_limits<float>::infinity();
139 const float max = std::numeric_limits<float>::max();
140 const float big = max * 0.5f;
141
142 EXPECT_EQ(saturated::Add<float>(big, big), max);
143 EXPECT_EQ(saturated::Add<float>(max, big), inf);
144 EXPECT_EQ(saturated::Add<float>(big, max), inf);
145 EXPECT_EQ(saturated::Add<float>(max, max), inf);
146 EXPECT_EQ(saturated::Add<float>(max, inf), inf);
147 EXPECT_EQ(saturated::Add<float>(inf, max), inf);
148 EXPECT_EQ(saturated::Add<float>(inf, inf), inf);
149
150 EXPECT_EQ(saturated::Add<float>(-big, -big), -max);
151 EXPECT_EQ(saturated::Add<float>(-max, -big), -inf);
152 EXPECT_EQ(saturated::Add<float>(-big, -max), -inf);
153 EXPECT_EQ(saturated::Add<float>(-max, -max), -inf);
154 EXPECT_EQ(saturated::Add<float>(-max, -inf), -inf);
155 EXPECT_EQ(saturated::Add<float>(-inf, -max), -inf);
156 EXPECT_EQ(saturated::Add<float>(-inf, -inf), -inf);
157
158 EXPECT_EQ(saturated::Add<float>(big, -big), 0.0f);
159 EXPECT_EQ(saturated::Add<float>(max, -big), big);
160 EXPECT_EQ(saturated::Add<float>(big, -max), -big);
161 EXPECT_EQ(saturated::Add<float>(max, -max), 0.0f);
162 EXPECT_EQ(saturated::Add<float>(max, -inf), -inf);
163 EXPECT_EQ(saturated::Add<float>(inf, -max), inf);
164 EXPECT_TRUE(std::isnan(saturated::Add<float>(inf, -inf)));
165
166 EXPECT_EQ(saturated::Add<float>(-big, big), 0.0f);
167 EXPECT_EQ(saturated::Add<float>(-max, big), -big);
168 EXPECT_EQ(saturated::Add<float>(-big, max), big);
169 EXPECT_EQ(saturated::Add<float>(-max, max), 0.0f);
170 EXPECT_EQ(saturated::Add<float>(-max, inf), inf);
171 EXPECT_EQ(saturated::Add<float>(-inf, max), -inf);
172 EXPECT_TRUE(std::isnan(saturated::Add<float>(-inf, inf)));
173 }
174 {
175 const double inf = std::numeric_limits<double>::infinity();
176 const double max = std::numeric_limits<double>::max();
177 const double big = max * 0.5f;
178
179 EXPECT_EQ(saturated::Add<double>(big, big), max);
180 EXPECT_EQ(saturated::Add<double>(max, big), inf);
181 EXPECT_EQ(saturated::Add<double>(big, max), inf);
182 EXPECT_EQ(saturated::Add<double>(max, max), inf);
183 EXPECT_EQ(saturated::Add<double>(max, inf), inf);
184 EXPECT_EQ(saturated::Add<double>(inf, max), inf);
185 EXPECT_EQ(saturated::Add<double>(inf, inf), inf);
186
187 EXPECT_EQ(saturated::Add<double>(-big, -big), -max);
188 EXPECT_EQ(saturated::Add<double>(-max, -big), -inf);
189 EXPECT_EQ(saturated::Add<double>(-big, -max), -inf);
190 EXPECT_EQ(saturated::Add<double>(-max, -max), -inf);
191 EXPECT_EQ(saturated::Add<double>(-max, -inf), -inf);
192 EXPECT_EQ(saturated::Add<double>(-inf, -max), -inf);
193 EXPECT_EQ(saturated::Add<double>(-inf, -inf), -inf);
194
195 EXPECT_EQ(saturated::Add<double>(big, -big), 0.0f);
196 EXPECT_EQ(saturated::Add<double>(max, -big), big);
197 EXPECT_EQ(saturated::Add<double>(big, -max), -big);
198 EXPECT_EQ(saturated::Add<double>(max, -max), 0.0f);
199 EXPECT_EQ(saturated::Add<double>(max, -inf), -inf);
200 EXPECT_EQ(saturated::Add<double>(inf, -max), inf);
201 EXPECT_TRUE(std::isnan(saturated::Add<double>(inf, -inf)));
202
203 EXPECT_EQ(saturated::Add<double>(-big, big), 0.0f);
204 EXPECT_EQ(saturated::Add<double>(-max, big), -big);
205 EXPECT_EQ(saturated::Add<double>(-big, max), big);
206 EXPECT_EQ(saturated::Add<double>(-max, max), 0.0f);
207 EXPECT_EQ(saturated::Add<double>(-max, inf), inf);
208 EXPECT_EQ(saturated::Add<double>(-inf, max), -inf);
209 EXPECT_TRUE(std::isnan(saturated::Add<double>(-inf, inf)));
210 }
211 {
212 const Scalar inf = std::numeric_limits<Scalar>::infinity();
213 const Scalar max = std::numeric_limits<Scalar>::max();
214 const Scalar big = max * 0.5f;
215
216 EXPECT_EQ(saturated::Add<Scalar>(big, big), max);
217 EXPECT_EQ(saturated::Add<Scalar>(max, big), inf);
218 EXPECT_EQ(saturated::Add<Scalar>(big, max), inf);
219 EXPECT_EQ(saturated::Add<Scalar>(max, max), inf);
220 EXPECT_EQ(saturated::Add<Scalar>(max, inf), inf);
221 EXPECT_EQ(saturated::Add<Scalar>(inf, max), inf);
222 EXPECT_EQ(saturated::Add<Scalar>(inf, inf), inf);
223
224 EXPECT_EQ(saturated::Add<Scalar>(-big, -big), -max);
225 EXPECT_EQ(saturated::Add<Scalar>(-max, -big), -inf);
226 EXPECT_EQ(saturated::Add<Scalar>(-big, -max), -inf);
227 EXPECT_EQ(saturated::Add<Scalar>(-max, -max), -inf);
228 EXPECT_EQ(saturated::Add<Scalar>(-max, -inf), -inf);
229 EXPECT_EQ(saturated::Add<Scalar>(-inf, -max), -inf);
230 EXPECT_EQ(saturated::Add<Scalar>(-inf, -inf), -inf);
231
232 EXPECT_EQ(saturated::Add<Scalar>(big, -big), 0.0f);
233 EXPECT_EQ(saturated::Add<Scalar>(max, -big), big);
234 EXPECT_EQ(saturated::Add<Scalar>(big, -max), -big);
235 EXPECT_EQ(saturated::Add<Scalar>(max, -max), 0.0f);
236 EXPECT_EQ(saturated::Add<Scalar>(max, -inf), -inf);
237 EXPECT_EQ(saturated::Add<Scalar>(inf, -max), inf);
238 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(inf, -inf)));
239
240 EXPECT_EQ(saturated::Add<Scalar>(-big, big), 0.0f);
241 EXPECT_EQ(saturated::Add<Scalar>(-max, big), -big);
242 EXPECT_EQ(saturated::Add<Scalar>(-big, max), big);
243 EXPECT_EQ(saturated::Add<Scalar>(-max, max), 0.0f);
244 EXPECT_EQ(saturated::Add<Scalar>(-max, inf), inf);
245 EXPECT_EQ(saturated::Add<Scalar>(-inf, max), -inf);
246 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(-inf, inf)));
247 }
248 }

## ◆ TEST() [482/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAddOfSignedInts |
| ) |  |

Definition at line 12 of file saturated_math_unittests.cc.

12 {
13 {
14 EXPECT_EQ(saturated::Add<int8_t>(0x79, 5), int8_t(0x7E));
15 EXPECT_EQ(saturated::Add<int8_t>(0x7A, 5), int8_t(0x7F));
16 EXPECT_EQ(saturated::Add<int8_t>(0x7B, 5), int8_t(0x7F));
17 }
18 {
19 EXPECT_EQ(saturated::Add<int8_t>(0x86, -5), int8_t(0x81));
20 EXPECT_EQ(saturated::Add<int8_t>(0x85, -5), int8_t(0x80));
21 EXPECT_EQ(saturated::Add<int8_t>(0x84, -5), int8_t(0x80));
22 }
23 {
24 EXPECT_EQ(saturated::Add<int16_t>(0x7FF9, 5), int16_t(0x7FFE));
25 EXPECT_EQ(saturated::Add<int16_t>(0x7FFA, 5), int16_t(0x7FFF));
26 EXPECT_EQ(saturated::Add<int16_t>(0x7FFB, 5), int16_t(0x7FFF));
27 }
28 {
29 EXPECT_EQ(saturated::Add<int16_t>(0x8006, -5), int16_t(0x8001));
30 EXPECT_EQ(saturated::Add<int16_t>(0x8005, -5), int16_t(0x8000));
31 EXPECT_EQ(saturated::Add<int16_t>(0x8004, -5), int16_t(0x8000));
32 }
33 {
34 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFF9, 5), int32_t(0x7FFFFFFE));
35 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFA, 5), int32_t(0x7FFFFFFF));
36 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFB, 5), int32_t(0x7FFFFFFF));
37 }
38 {
39 EXPECT_EQ(saturated::Add<int32_t>(0x80000006, -5), int32_t(0x80000001));
40 EXPECT_EQ(saturated::Add<int32_t>(0x80000005, -5), int32_t(0x80000000));
41 EXPECT_EQ(saturated::Add<int32_t>(0x80000004, -5), int32_t(0x80000000));
42 }
43 {
44 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFF9, 5),
45 int64_t(0x7FFFFFFFFFFFFFFE));
46 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFA, 5),
47 int64_t(0x7FFFFFFFFFFFFFFF));
48 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFB, 5),
49 int64_t(0x7FFFFFFFFFFFFFFF));
50 }
51 {
52 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000006, -5),
53 int64_t(0x8000000000000001));
54 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000005, -5),
55 int64_t(0x8000000000000000));
56 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000004, -5),
57 int64_t(0x8000000000000000));
58 }
59 }

## ◆ TEST() [483/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAverageScalarOfFloatingPoint |
| ) |  |

Definition at line 828 of file saturated_math_unittests.cc.

828 {
829 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
830 const Scalar s_max = std::numeric_limits<Scalar>::max();
831 const Scalar s_big = s_max * 0.5f;
832
833 {
834 const float inf = std::numeric_limits<Scalar>::infinity();
835 const float max = std::numeric_limits<float>::max();
836 const float big = max * 0.5f;
837
838 EXPECT_EQ(saturated::AverageScalar<float>(big, big), s_big);
839 EXPECT_EQ(saturated::AverageScalar<float>(max, max), s_max);
840 EXPECT_EQ(saturated::AverageScalar<float>(big, -big), 0.0f);
841 EXPECT_EQ(saturated::AverageScalar<float>(max, -max), 0.0f);
842 EXPECT_EQ(saturated::AverageScalar<float>(-big, big), 0.0f);
843 EXPECT_EQ(saturated::AverageScalar<float>(-max, max), 0.0f);
844 EXPECT_EQ(saturated::AverageScalar<float>(-big, -big), -s_big);
845 EXPECT_EQ(saturated::AverageScalar<float>(-max, -max), -s_max);
846
847 EXPECT_EQ(saturated::AverageScalar<float>(inf, inf), s_inf);
848 EXPECT_EQ(saturated::AverageScalar<float>(-inf, -inf), -s_inf);
849 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(-inf, inf)));
850 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(inf, -inf)));
851 }
852 {
853 const double inf = std::numeric_limits<Scalar>::infinity();
854 const double max = std::numeric_limits<double>::max();
855 const double big = max * 0.5;
856
857 // Most of the averages below using the double constants will
858 // overflow the Scalar return value and result in infinity,
859 // so we also test with some Scalar constants (promoted to double)
860 // to verify that they don't overflow in the double template
861 EXPECT_EQ(saturated::AverageScalar<double>(s_big, s_big), s_big);
862 EXPECT_EQ(saturated::AverageScalar<double>(s_max, s_max), s_max);
863 EXPECT_EQ(saturated::AverageScalar<double>(-s_big, -s_big), -s_big);
864 EXPECT_EQ(saturated::AverageScalar<double>(-s_max, -s_max), -s_max);
865
866 // And now testing continues with the double constants which
867 // mostly overflow
868 EXPECT_EQ(saturated::AverageScalar<double>(big, big), s_inf);
869 EXPECT_EQ(saturated::AverageScalar<double>(max, max), s_inf);
870 EXPECT_EQ(saturated::AverageScalar<double>(big, -big), 0.0f);
871 EXPECT_EQ(saturated::AverageScalar<double>(max, -max), 0.0f);
872 EXPECT_EQ(saturated::AverageScalar<double>(-big, big), 0.0f);
873 EXPECT_EQ(saturated::AverageScalar<double>(-max, max), 0.0f);
874 EXPECT_EQ(saturated::AverageScalar<double>(-big, -big), -s_inf);
875 EXPECT_EQ(saturated::AverageScalar<double>(-max, -max), -s_inf);
876
877 EXPECT_EQ(saturated::AverageScalar<double>(inf, inf), s_inf);
878 EXPECT_EQ(saturated::AverageScalar<double>(-inf, -inf), -s_inf);
879 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(-inf, inf)));
880 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(inf, -inf)));
881 }
882 {
883 const Scalar inf = std::numeric_limits<Scalar>::infinity();
884 const Scalar max = std::numeric_limits<Scalar>::max();
885 const Scalar big = max * 0.5f;
886
887 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, big), s_big);
888 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, max), s_max);
889 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, -big), 0.0f);
890 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, -max), 0.0f);
891 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, big), 0.0f);
892 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, max), 0.0f);
893 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, -big), -s_big);
894 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, -max), -s_max);
895
896 EXPECT_EQ(saturated::AverageScalar<Scalar>(inf, inf), s_inf);
897 EXPECT_EQ(saturated::AverageScalar<Scalar>(-inf, -inf), -s_inf);
898 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(-inf, s_inf)));
899 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(inf, -s_inf)));
900 }
901 }

## ◆ TEST() [484/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAverageScalarOfSignedInts |
| ) |  |

Definition at line 716 of file saturated_math_unittests.cc.

716 {
717 // For each type try:
718 //
719 // - near the limits, averaging to 0
720 // - at the limits, averaging to 0 or 0.5 depending on precision
721 // - both large enough for the sum to overflow
722 // - both negative enough for the sum to underflow
723 {
724 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x81, 0x7F), -0.0f);
725 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x80, 0x7F), -0.5f);
726 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x70, 0x75), 114.5f);
727 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x85, 0x8A), -120.5f);
728 }
729 {
730 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8001, 0x7FFF), -0.0f);
731 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8000, 0x7FFF), -0.5f);
732 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x7000, 0x7005), 28674.5f);
733 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8005, 0x800A), -32760.5f);
734 }
735 {
736 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000001, 0x7FFFFFFF), -0.0f);
737 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000000, 0x7FFFFFFF), -0.5f);
738 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x70000000, 0x70000005),
739 1879048195.5f);
740 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000005, 0x8000000A),
741 -2147483655.5f);
742 }
743 {
744 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000001,
745 0x7FFFFFFFFFFFFFFF),
746 0.0f);
747 // 64-bit integers overflow the ability of a Scalar (float) to
748 // represent discrete integers and so the two numbers we are
749 // averaging here will look like the same number with different
750 // signs and the answer will be "0"
751 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000000,
752 0x7FFFFFFFFFFFFFFF),
753 0.0f);
754 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x7000000000000000,
755 0x7000000000000005),
756 8.07045053e+18, 1e18);
757 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x8000000000000005,
758 0x800000000000000A),
759 -9.223372e+18, 1e18);
760 }
761 }

## ◆ TEST() [485/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitSubOfFloatingPoint |
| ) |  |

Definition at line 488 of file saturated_math_unittests.cc.

488 {
489 {
490 const float inf = std::numeric_limits<float>::infinity();
491 const float max = std::numeric_limits<float>::max();
492 const float big = max * 0.5f;
493
494 EXPECT_EQ(saturated::Sub<float>(big, big), 0.0f);
495 EXPECT_EQ(saturated::Sub<float>(max, big), big);
496 EXPECT_EQ(saturated::Sub<float>(big, max), -big);
497 EXPECT_EQ(saturated::Sub<float>(max, max), 0.0f);
498 EXPECT_EQ(saturated::Sub<float>(max, inf), -inf);
499 EXPECT_EQ(saturated::Sub<float>(inf, max), inf);
500 EXPECT_TRUE(std::isnan(saturated::Sub<float>(inf, inf)));
501
502 EXPECT_EQ(saturated::Sub<float>(-big, -big), 0.0f);
503 EXPECT_EQ(saturated::Sub<float>(-max, -big), -big);
504 EXPECT_EQ(saturated::Sub<float>(-big, -max), big);
505 EXPECT_EQ(saturated::Sub<float>(-max, -max), 0.0f);
506 EXPECT_EQ(saturated::Sub<float>(-max, -inf), inf);
507 EXPECT_EQ(saturated::Sub<float>(-inf, -max), -inf);
508 EXPECT_TRUE(std::isnan(saturated::Sub<float>(-inf, -inf)));
509
510 EXPECT_EQ(saturated::Sub<float>(big, -big), max);
511 EXPECT_EQ(saturated::Sub<float>(max, -big), inf);
512 EXPECT_EQ(saturated::Sub<float>(big, -max), inf);
513 EXPECT_EQ(saturated::Sub<float>(max, -max), inf);
514 EXPECT_EQ(saturated::Sub<float>(max, -inf), inf);
515 EXPECT_EQ(saturated::Sub<float>(inf, -max), inf);
516 EXPECT_EQ(saturated::Sub<float>(inf, -inf), inf);
517
518 EXPECT_EQ(saturated::Sub<float>(-big, big), -max);
519 EXPECT_EQ(saturated::Sub<float>(-max, big), -inf);
520 EXPECT_EQ(saturated::Sub<float>(-big, max), -inf);
521 EXPECT_EQ(saturated::Sub<float>(-max, max), -inf);
522 EXPECT_EQ(saturated::Sub<float>(-max, inf), -inf);
523 EXPECT_EQ(saturated::Sub<float>(-inf, max), -inf);
524 EXPECT_EQ(saturated::Sub<float>(-inf, inf), -inf);
525 }
526 {
527 const double inf = std::numeric_limits<double>::infinity();
528 const double max = std::numeric_limits<double>::max();
529 const double big = max * 0.5f;
530
531 EXPECT_EQ(saturated::Sub<double>(big, big), 0.0f);
532 EXPECT_EQ(saturated::Sub<double>(max, big), big);
533 EXPECT_EQ(saturated::Sub<double>(big, max), -big);
534 EXPECT_EQ(saturated::Sub<double>(max, max), 0.0f);
535 EXPECT_EQ(saturated::Sub<double>(max, inf), -inf);
536 EXPECT_EQ(saturated::Sub<double>(inf, max), inf);
537 EXPECT_TRUE(std::isnan(saturated::Sub<double>(inf, inf)));
538
539 EXPECT_EQ(saturated::Sub<double>(-big, -big), 0.0f);
540 EXPECT_EQ(saturated::Sub<double>(-max, -big), -big);
541 EXPECT_EQ(saturated::Sub<double>(-big, -max), big);
542 EXPECT_EQ(saturated::Sub<double>(-max, -max), 0.0f);
543 EXPECT_EQ(saturated::Sub<double>(-max, -inf), inf);
544 EXPECT_EQ(saturated::Sub<double>(-inf, -max), -inf);
545 EXPECT_TRUE(std::isnan(saturated::Sub<double>(-inf, -inf)));
546
547 EXPECT_EQ(saturated::Sub<double>(big, -big), max);
548 EXPECT_EQ(saturated::Sub<double>(max, -big), inf);
549 EXPECT_EQ(saturated::Sub<double>(big, -max), inf);
550 EXPECT_EQ(saturated::Sub<double>(max, -max), inf);
551 EXPECT_EQ(saturated::Sub<double>(max, -inf), inf);
552 EXPECT_EQ(saturated::Sub<double>(inf, -max), inf);
553 EXPECT_EQ(saturated::Sub<double>(inf, -inf), inf);
554
555 EXPECT_EQ(saturated::Sub<double>(-big, big), -max);
556 EXPECT_EQ(saturated::Sub<double>(-max, big), -inf);
557 EXPECT_EQ(saturated::Sub<double>(-big, max), -inf);
558 EXPECT_EQ(saturated::Sub<double>(-max, max), -inf);
559 EXPECT_EQ(saturated::Sub<double>(-max, inf), -inf);
560 EXPECT_EQ(saturated::Sub<double>(-inf, max), -inf);
561 EXPECT_EQ(saturated::Sub<double>(-inf, inf), -inf);
562 }
563 {
564 const Scalar inf = std::numeric_limits<Scalar>::infinity();
565 const Scalar max = std::numeric_limits<Scalar>::max();
566 const Scalar big = max * 0.5f;
567
568 EXPECT_EQ(saturated::Sub<Scalar>(big, big), 0.0f);
569 EXPECT_EQ(saturated::Sub<Scalar>(max, big), big);
570 EXPECT_EQ(saturated::Sub<Scalar>(big, max), -big);
571 EXPECT_EQ(saturated::Sub<Scalar>(max, max), 0.0f);
572 EXPECT_EQ(saturated::Sub<Scalar>(max, inf), -inf);
573 EXPECT_EQ(saturated::Sub<Scalar>(inf, max), inf);
574 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(inf, inf)));
575
576 EXPECT_EQ(saturated::Sub<Scalar>(-big, -big), 0.0f);
577 EXPECT_EQ(saturated::Sub<Scalar>(-max, -big), -big);
578 EXPECT_EQ(saturated::Sub<Scalar>(-big, -max), big);
579 EXPECT_EQ(saturated::Sub<Scalar>(-max, -max), 0.0f);
580 EXPECT_EQ(saturated::Sub<Scalar>(-max, -inf), inf);
581 EXPECT_EQ(saturated::Sub<Scalar>(-inf, -max), -inf);
582 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(-inf, -inf)));
583
584 EXPECT_EQ(saturated::Sub<Scalar>(big, -big), max);
585 EXPECT_EQ(saturated::Sub<Scalar>(max, -big), inf);
586 EXPECT_EQ(saturated::Sub<Scalar>(big, -max), inf);
587 EXPECT_EQ(saturated::Sub<Scalar>(max, -max), inf);
588 EXPECT_EQ(saturated::Sub<Scalar>(max, -inf), inf);
589 EXPECT_EQ(saturated::Sub<Scalar>(inf, -max), inf);
590 EXPECT_EQ(saturated::Sub<Scalar>(inf, -inf), inf);
591
592 EXPECT_EQ(saturated::Sub<Scalar>(-big, big), -max);
593 EXPECT_EQ(saturated::Sub<Scalar>(-max, big), -inf);
594 EXPECT_EQ(saturated::Sub<Scalar>(-big, max), -inf);
595 EXPECT_EQ(saturated::Sub<Scalar>(-max, max), -inf);
596 EXPECT_EQ(saturated::Sub<Scalar>(-max, inf), -inf);
597 EXPECT_EQ(saturated::Sub<Scalar>(-inf, max), -inf);
598 EXPECT_EQ(saturated::Sub<Scalar>(-inf, inf), -inf);
599 }
600 }

## ◆ TEST() [486/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitSubOfSignedInts |
| ) |  |

Definition at line 364 of file saturated_math_unittests.cc.

364 {
365 {
366 EXPECT_EQ(saturated::Sub<int8_t>(0x79, -5), int8_t(0x7E));
367 EXPECT_EQ(saturated::Sub<int8_t>(0x7A, -5), int8_t(0x7F));
368 EXPECT_EQ(saturated::Sub<int8_t>(0x7B, -5), int8_t(0x7F));
369 }
370 {
371 EXPECT_EQ(saturated::Sub<int8_t>(0x86, 5), int8_t(0x81));
372 EXPECT_EQ(saturated::Sub<int8_t>(0x85, 5), int8_t(0x80));
373 EXPECT_EQ(saturated::Sub<int8_t>(0x84, 5), int8_t(0x80));
374 }
375 {
376 EXPECT_EQ(saturated::Sub<int16_t>(0x7FF9, -5), int16_t(0x7FFE));
377 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFA, -5), int16_t(0x7FFF));
378 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFB, -5), int16_t(0x7FFF));
379 }
380 {
381 EXPECT_EQ(saturated::Sub<int16_t>(0x8006, 5), int16_t(0x8001));
382 EXPECT_EQ(saturated::Sub<int16_t>(0x8005, 5), int16_t(0x8000));
383 EXPECT_EQ(saturated::Sub<int16_t>(0x8004, 5), int16_t(0x8000));
384 }
385 {
386 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFF9, -5), int32_t(0x7FFFFFFE));
387 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFA, -5), int32_t(0x7FFFFFFF));
388 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFB, -5), int32_t(0x7FFFFFFF));
389 }
390 {
391 EXPECT_EQ(saturated::Sub<int32_t>(0x80000006, 5), int32_t(0x80000001));
392 EXPECT_EQ(saturated::Sub<int32_t>(0x80000005, 5), int32_t(0x80000000));
393 EXPECT_EQ(saturated::Sub<int32_t>(0x80000004, 5), int32_t(0x80000000));
394 }
395 {
396 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFF9, -5),
397 int64_t(0x7FFFFFFFFFFFFFFE));
398 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFA, -5),
399 int64_t(0x7FFFFFFFFFFFFFFF));
400 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFB, -5),
401 int64_t(0x7FFFFFFFFFFFFFFF));
402 }
403 {
404 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000006, 5),
405 int64_t(0x8000000000000001));
406 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000005, 5),
407 int64_t(0x8000000000000000));
408 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000004, 5),
409 int64_t(0x8000000000000000));
410 }
411 }

## ◆ TEST() [487/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAddOfFloatingPoint |
| ) |  |

Definition at line 250 of file saturated_math_unittests.cc.

250 {
251 {
252 const float inf = std::numeric_limits<float>::infinity();
253 const float max = std::numeric_limits<float>::max();
254 const float big = max * 0.5f;
255
256 EXPECT_EQ(saturated::Add(big, big), max);
257 EXPECT_EQ(saturated::Add(max, big), inf);
258 EXPECT_EQ(saturated::Add(big, max), inf);
259 EXPECT_EQ(saturated::Add(max, max), inf);
260 EXPECT_EQ(saturated::Add(max, inf), inf);
261 EXPECT_EQ(saturated::Add(inf, max), inf);
262 EXPECT_EQ(saturated::Add(inf, inf), inf);
263
264 EXPECT_EQ(saturated::Add(-big, -big), -max);
265 EXPECT_EQ(saturated::Add(-max, -big), -inf);
266 EXPECT_EQ(saturated::Add(-big, -max), -inf);
267 EXPECT_EQ(saturated::Add(-max, -max), -inf);
268 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
269 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
270 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
271
272 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
273 EXPECT_EQ(saturated::Add(max, -big), big);
274 EXPECT_EQ(saturated::Add(big, -max), -big);
275 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
276 EXPECT_EQ(saturated::Add(max, -inf), -inf);
277 EXPECT_EQ(saturated::Add(inf, -max), inf);
278 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
279
280 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
281 EXPECT_EQ(saturated::Add(-max, big), -big);
282 EXPECT_EQ(saturated::Add(-big, max), big);
283 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
284 EXPECT_EQ(saturated::Add(-max, inf), inf);
285 EXPECT_EQ(saturated::Add(-inf, max), -inf);
286 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
287 }
288 {
289 const double inf = std::numeric_limits<double>::infinity();
290 const double max = std::numeric_limits<double>::max();
291 const double big = max * 0.5f;
292
293 EXPECT_EQ(saturated::Add(big, big), max);
294 EXPECT_EQ(saturated::Add(max, big), inf);
295 EXPECT_EQ(saturated::Add(big, max), inf);
296 EXPECT_EQ(saturated::Add(max, max), inf);
297 EXPECT_EQ(saturated::Add(max, inf), inf);
298 EXPECT_EQ(saturated::Add(inf, max), inf);
299 EXPECT_EQ(saturated::Add(inf, inf), inf);
300
301 EXPECT_EQ(saturated::Add(-big, -big), -max);
302 EXPECT_EQ(saturated::Add(-max, -big), -inf);
303 EXPECT_EQ(saturated::Add(-big, -max), -inf);
304 EXPECT_EQ(saturated::Add(-max, -max), -inf);
305 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
306 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
307 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
308
309 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
310 EXPECT_EQ(saturated::Add(max, -big), big);
311 EXPECT_EQ(saturated::Add(big, -max), -big);
312 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
313 EXPECT_EQ(saturated::Add(max, -inf), -inf);
314 EXPECT_EQ(saturated::Add(inf, -max), inf);
315 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
316
317 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
318 EXPECT_EQ(saturated::Add(-max, big), -big);
319 EXPECT_EQ(saturated::Add(-big, max), big);
320 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
321 EXPECT_EQ(saturated::Add(-max, inf), inf);
322 EXPECT_EQ(saturated::Add(-inf, max), -inf);
323 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
324 }
325 {
326 const Scalar inf = std::numeric_limits<Scalar>::infinity();
327 const Scalar max = std::numeric_limits<Scalar>::max();
328 const Scalar big = max * 0.5f;
329
330 EXPECT_EQ(saturated::Add(big, big), max);
331 EXPECT_EQ(saturated::Add(max, big), inf);
332 EXPECT_EQ(saturated::Add(big, max), inf);
333 EXPECT_EQ(saturated::Add(max, max), inf);
334 EXPECT_EQ(saturated::Add(max, inf), inf);
335 EXPECT_EQ(saturated::Add(inf, max), inf);
336 EXPECT_EQ(saturated::Add(inf, inf), inf);
337
338 EXPECT_EQ(saturated::Add(-big, -big), -max);
339 EXPECT_EQ(saturated::Add(-max, -big), -inf);
340 EXPECT_EQ(saturated::Add(-big, -max), -inf);
341 EXPECT_EQ(saturated::Add(-max, -max), -inf);
342 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
343 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
344 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
345
346 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
347 EXPECT_EQ(saturated::Add(max, -big), big);
348 EXPECT_EQ(saturated::Add(big, -max), -big);
349 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
350 EXPECT_EQ(saturated::Add(max, -inf), -inf);
351 EXPECT_EQ(saturated::Add(inf, -max), inf);
352 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
353
354 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
355 EXPECT_EQ(saturated::Add(-max, big), -big);
356 EXPECT_EQ(saturated::Add(-big, max), big);
357 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
358 EXPECT_EQ(saturated::Add(-max, inf), inf);
359 EXPECT_EQ(saturated::Add(-inf, max), -inf);
360 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
361 }
362 }

## ◆ TEST() [488/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAddOfSignedInts |
| ) |  |

Definition at line 61 of file saturated_math_unittests.cc.

61 {
62 {
63 int8_t a = 0x79;
64 int8_t b = 5;
65 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7E));
66 a = 0x7A;
67 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
68 a = 0x7B;
69 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
70 }
71 {
72 int8_t a = 0x86;
73 int8_t b = -5;
74 EXPECT_EQ(saturated::Add(a, b), int8_t(0x81));
75 a = 0x85;
76 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
77 a = 0x84;
78 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
79 }
80 {
81 int16_t a = 0x7FF9;
82 int16_t b = 5;
83 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFE));
84 a = 0x7FFA;
85 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
86 a = 0x7FFB;
87 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
88 }
89 {
90 int16_t a = 0x8006;
91 int16_t b = -5;
92 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8001));
93 a = 0x8005;
94 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
95 a = 0x8004;
96 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
97 }
98 {
99 int32_t a = 0x7FFFFFF9;
100 int32_t b = 5;
101 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFE));
102 a = 0x7FFFFFFA;
103 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
104 a = 0x7FFFFFFB;
105 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
106 }
107 {
108 int32_t a = 0x80000006;
109 int32_t b = -5;
110 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000001));
111 a = 0x80000005;
112 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
113 a = 0x80000004;
114 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
115 }
116 {
117 int64_t a = 0x7FFFFFFFFFFFFFF9;
118 int64_t b = 5;
119 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
120 a = 0x7FFFFFFFFFFFFFFA;
121 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
122 a = 0x7FFFFFFFFFFFFFFB;
123 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
124 }
125 {
126 int64_t a = 0x8000000000000006;
127 int64_t b = -5;
128 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000001));
129 a = 0x8000000000000005;
130 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
131 a = 0x8000000000000004;
132 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
133 }
134 }

References impeller::saturated::b.

## ◆ TEST() [489/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAverageScalarOfFloatingPoint |
| ) |  |

Definition at line 903 of file saturated_math_unittests.cc.

903 {
904 // All return values are Scalar regardless of the operand types
905 // so these constants are used as the expected answers.
906 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
907 const Scalar s_max = std::numeric_limits<Scalar>::max();
908 const Scalar s_big = s_max * 0.5f;
909
910 {
911 const float inf = std::numeric_limits<float>::infinity();
912 const float max = std::numeric_limits<float>::max();
913 const float big = max * 0.5f;
914
915 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
916 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
917 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
918 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
919 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
920 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
921 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
922 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
923
924 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
925 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
926 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
927 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
928 }
929 {
930 const double inf = std::numeric_limits<double>::infinity();
931 const double max = std::numeric_limits<double>::max();
932 const double big = max * 0.5;
933
934 // The s_constants converted to double. We should get finite results
935 // from finding the averages of these values, but we'll get a lot of
936 // overflow to infinity when testing the large double constants.
937 const double d_s_max = s_max;
938 const double d_s_big = s_big;
939 EXPECT_EQ(saturated::AverageScalar(d_s_big, d_s_big), s_big);
940 EXPECT_EQ(saturated::AverageScalar(d_s_max, d_s_max), s_max);
941 EXPECT_EQ(saturated::AverageScalar(-d_s_big, -d_s_big), -s_big);
942 EXPECT_EQ(saturated::AverageScalar(-d_s_max, -d_s_max), -s_max);
943
944 // And now testing continues with the double constants which
945 // mostly overflow
946 EXPECT_EQ(saturated::AverageScalar(big, big), s_inf);
947 EXPECT_EQ(saturated::AverageScalar(max, max), s_inf);
948 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
949 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
950 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
951 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
952 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_inf);
953 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_inf);
954
955 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
956 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
957 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
958 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
959 }
960 {
961 const Scalar inf = std::numeric_limits<Scalar>::infinity();
962 const Scalar max = std::numeric_limits<Scalar>::max();
963 const Scalar big = max * 0.5f;
964
965 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
966 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
967 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
968 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
969 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
970 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
971 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
972 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
973
974 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
975 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
976 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, s_inf)));
977 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -s_inf)));
978 }
979 }

## ◆ TEST() [490/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAverageScalarOfSignedInts |
| ) |  |

Definition at line 763 of file saturated_math_unittests.cc.

763 {
764 // For each type try:
765 //
766 // - near the limits, averaging to 0
767 // - at the limits, averaging to 0 or 0.5 depending on precision
768 // - both large enough for the sum to overflow
769 // - both negative enough for the sum to underflow
770 {
771 int8_t a = 0x81;
772 int8_t b = 0x7f;
773 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
774 a = 0x80;
775 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
776 a = 0x70;
777 b = 0x75;
778 EXPECT_EQ(saturated::AverageScalar(a, b), 114.5f);
779 a = 0x85;
780 b = 0x8A;
781 EXPECT_EQ(saturated::AverageScalar(a, b), -120.5f);
782 }
783 {
784 int16_t a = 0x8001;
785 int16_t b = 0x7FFF;
786 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
787 a = 0x8000;
788 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
789 a = 0x7000;
790 b = 0x7005;
791 EXPECT_EQ(saturated::AverageScalar(a, b), 28674.5f);
792 a = 0x8005;
793 b = 0x800A;
794 EXPECT_EQ(saturated::AverageScalar(a, b), -32760.5f);
795 }
796 {
797 int32_t a = 0x80000001;
798 int32_t b = 0x7FFFFFFF;
799 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
800 a = 0x80000000;
801 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
802 a = 0x70000000;
803 b = 0x70000005;
804 EXPECT_EQ(saturated::AverageScalar(a, b), 1879048195.5f);
805 a = 0x80000005;
806 b = 0x8000000A;
807 EXPECT_EQ(saturated::AverageScalar(a, b), -2147483655.5f);
808 }
809 {
810 int64_t a = 0x8000000000000001;
811 int64_t b = 0x7FFFFFFFFFFFFFFF;
812 EXPECT_EQ(saturated::AverageScalar(a, b), 0.0f);
813 // 64-bit integers overflow the ability of a Scalar (float) to
814 // represent discrete integers and so the two numbers we are
815 // averaging here will look like the same number with different
816 // signs and the answer will be "0"
817 a = 0x8000000000000000;
818 EXPECT_EQ(saturated::AverageScalar<int64_t>(a, b), 0.0f);
819 a = 0x7000000000000000;
820 b = 0x7000000000000005;
821 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), 8.0704505e+18, 1e18);
822 a = 0x8000000000000005;
823 b = 0x800000000000000A;
824 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), -9.223372e+18, 1e18);
825 }
826 }

References impeller::saturated::b.

## ◆ TEST() [491/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitSubOfFloatingPoint |
| ) |  |

Definition at line 602 of file saturated_math_unittests.cc.

602 {
603 {
604 const float inf = std::numeric_limits<float>::infinity();
605 const float max = std::numeric_limits<float>::max();
606 const float big = max * 0.5f;
607
608 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
609 EXPECT_EQ(saturated::Sub(max, big), big);
610 EXPECT_EQ(saturated::Sub(big, max), -big);
611 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
612 EXPECT_EQ(saturated::Sub(max, inf), -inf);
613 EXPECT_EQ(saturated::Sub(inf, max), inf);
614 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
615
616 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
617 EXPECT_EQ(saturated::Sub(-max, -big), -big);
618 EXPECT_EQ(saturated::Sub(-big, -max), big);
619 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
620 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
621 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
622 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
623
624 EXPECT_EQ(saturated::Sub(big, -big), max);
625 EXPECT_EQ(saturated::Sub(max, -big), inf);
626 EXPECT_EQ(saturated::Sub(big, -max), inf);
627 EXPECT_EQ(saturated::Sub(max, -max), inf);
628 EXPECT_EQ(saturated::Sub(max, -inf), inf);
629 EXPECT_EQ(saturated::Sub(inf, -max), inf);
630 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
631
632 EXPECT_EQ(saturated::Sub(-big, big), -max);
633 EXPECT_EQ(saturated::Sub(-max, big), -inf);
634 EXPECT_EQ(saturated::Sub(-big, max), -inf);
635 EXPECT_EQ(saturated::Sub(-max, max), -inf);
636 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
637 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
638 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
639 }
640 {
641 const double inf = std::numeric_limits<double>::infinity();
642 const double max = std::numeric_limits<double>::max();
643 const double big = max * 0.5f;
644
645 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
646 EXPECT_EQ(saturated::Sub(max, big), big);
647 EXPECT_EQ(saturated::Sub(big, max), -big);
648 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
649 EXPECT_EQ(saturated::Sub(max, inf), -inf);
650 EXPECT_EQ(saturated::Sub(inf, max), inf);
651 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
652
653 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
654 EXPECT_EQ(saturated::Sub(-max, -big), -big);
655 EXPECT_EQ(saturated::Sub(-big, -max), big);
656 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
657 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
658 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
659 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
660
661 EXPECT_EQ(saturated::Sub(big, -big), max);
662 EXPECT_EQ(saturated::Sub(max, -big), inf);
663 EXPECT_EQ(saturated::Sub(big, -max), inf);
664 EXPECT_EQ(saturated::Sub(max, -max), inf);
665 EXPECT_EQ(saturated::Sub(max, -inf), inf);
666 EXPECT_EQ(saturated::Sub(inf, -max), inf);
667 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
668
669 EXPECT_EQ(saturated::Sub(-big, big), -max);
670 EXPECT_EQ(saturated::Sub(-max, big), -inf);
671 EXPECT_EQ(saturated::Sub(-big, max), -inf);
672 EXPECT_EQ(saturated::Sub(-max, max), -inf);
673 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
674 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
675 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
676 }
677 {
678 const Scalar inf = std::numeric_limits<Scalar>::infinity();
679 const Scalar max = std::numeric_limits<Scalar>::max();
680 const Scalar big = max * 0.5f;
681
682 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
683 EXPECT_EQ(saturated::Sub(max, big), big);
684 EXPECT_EQ(saturated::Sub(big, max), -big);
685 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
686 EXPECT_EQ(saturated::Sub(max, inf), -inf);
687 EXPECT_EQ(saturated::Sub(inf, max), inf);
688 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
689
690 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
691 EXPECT_EQ(saturated::Sub(-max, -big), -big);
692 EXPECT_EQ(saturated::Sub(-big, -max), big);
693 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
694 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
695 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
696 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
697
698 EXPECT_EQ(saturated::Sub(big, -big), max);
699 EXPECT_EQ(saturated::Sub(max, -big), inf);
700 EXPECT_EQ(saturated::Sub(big, -max), inf);
701 EXPECT_EQ(saturated::Sub(max, -max), inf);
702 EXPECT_EQ(saturated::Sub(max, -inf), inf);
703 EXPECT_EQ(saturated::Sub(inf, -max), inf);
704 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
705
706 EXPECT_EQ(saturated::Sub(-big, big), -max);
707 EXPECT_EQ(saturated::Sub(-max, big), -inf);
708 EXPECT_EQ(saturated::Sub(-big, max), -inf);
709 EXPECT_EQ(saturated::Sub(-max, max), -inf);
710 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
711 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
712 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
713 }
714 }

## ◆ TEST() [492/574]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitSubOfSignedInts |
| ) |  |

Definition at line 413 of file saturated_math_unittests.cc.

413 {
414 {
415 int8_t a = 0x79;
416 int8_t b = -5;
417 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7E));
418 a = 0x7A;
419 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
420 a = 0x7B;
421 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
422 }
423 {
424 int8_t a = 0x86;
425 int8_t b = 5;
426 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x81));
427 a = 0x85;
428 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
429 a = 0x84;
430 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
431 }
432 {
433 int16_t a = 0x7FF9;
434 int16_t b = -5;
435 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFE));
436 a = 0x7FFA;
437 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
438 a = 0x7FFB;
439 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
440 }
441 {
442 int16_t a = 0x8006;
443 int16_t b = 5;
444 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8001));
445 a = 0x8005;
446 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
447 a = 0x8004;
448 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
449 }
450 {
451 int32_t a = 0x7FFFFFF9;
452 int32_t b = -5;
453 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFE));
454 a = 0x7FFFFFFA;
455 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
456 a = 0x7FFFFFFB;
457 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
458 }
459 {
460 int32_t a = 0x80000006;
461 int32_t b = 5;
462 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000001));
463 a = 0x80000005;
464 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
465 a = 0x80000004;
466 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
467 }
468 {
469 int64_t a = 0x7FFFFFFFFFFFFFF9;
470 int64_t b = -5;
471 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
472 a = 0x7FFFFFFFFFFFFFFA;
473 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
474 a = 0x7FFFFFFFFFFFFFFB;
475 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
476 }
477 {
478 int64_t a = 0x8000000000000006;
479 int64_t b = 5;
480 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000001));
481 a = 0x8000000000000005;
482 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
483 a = 0x8000000000000004;
484 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
485 }
486 }

References impeller::saturated::b.

## ◆ TEST() [493/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BackdropFilterEmptyCoverage |
| ) |  |

Definition at line 163 of file save_layer_utils_unittests.cc.

163 {
164 // Empty coverage with backdrop filter.
165 auto coverage = ComputeSaveLayerCoverage(
166 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
167 /*effect_transform=*/{}, //
168 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
169 /*image_filter=*/nullptr, //
170 /*flood_output_coverage=*/true //
171 );
172
173 ASSERT_TRUE(coverage.has_value());
174 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
175 }
impeller::ComputeSaveLayerCoverage
std::optional< Rect > ComputeSaveLayerCoverage(const Rect &content_coverage, const Matrix &effect_transform, const Rect &coverage_limit, const std::shared_ptr< FilterContents > &image_filter, bool flood_output_coverage, bool flood_input_coverage)
Compute the coverage of a subpass in the global coordinate space.
Definition: save_layer_utils.cc:19

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [494/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BackdropFiterComputedCoverage |
| ) |  |

Definition at line 29 of file save_layer_utils_unittests.cc.

29 {
30 // Backdrop Filter, computed coverage
31 auto coverage = ComputeSaveLayerCoverage(
32 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
33 /*effect_transform=*/{}, //
34 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
35 /*image_filter=*/nullptr,
36 /*flood_output_coverage=*/false, //
37 /*flood_input_coverage=*/true //
38 );
39
40 ASSERT_TRUE(coverage.has_value());
41 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
42 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [495/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | BasicEmptyCoverage |
| ) |  |

Definition at line 137 of file save_layer_utils_unittests.cc.

137 {
138 auto coverage = ComputeSaveLayerCoverage(
139 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
140 /*effect_transform=*/{}, //
141 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
142 /*image_filter=*/nullptr //
143 );
144
145 ASSERT_FALSE(coverage.has_value());
146 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [496/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter |
| ) |  |

Definition at line 246 of file save_layer_utils_unittests.cc.

248 {
249 // Create an image filter that slightly stretches the coverage limit. Even
250 // without the special logic for using the original content coverage, we
251 // verify that we don't introduce any artifacts from the intersection.
252 auto image_filter = FilterContents::MakeMatrixFilter(
253 FilterInput::Make(Rect()), Matrix::MakeScale({0.9, 0.9, 1}), {});
254
255 auto coverage = ComputeSaveLayerCoverage(
256 /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
257 /*effect_transform=*/{}, //
258 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
259 /*image_filter=*/image_filter //
260 );
261
262 ASSERT_TRUE(coverage.has_value());
263 // The transfomed coverage limit is ((0, 0), (111.111, 111.111)).
264 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
265 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [497/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter |
| ) |  |

Definition at line 227 of file save_layer_utils_unittests.cc.

229 {
230 // Create an image filter that slightly shrinks the coverage limit
231 auto image_filter = FilterContents::MakeMatrixFilter(
232 FilterInput::Make(Rect()), Matrix::MakeScale({1.1, 1.1, 1}), {});
233
234 auto coverage = ComputeSaveLayerCoverage(
235 /*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
236 /*effect_transform=*/{}, //
237 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
238 /*image_filter=*/image_filter //
239 );
240
241 ASSERT_TRUE(coverage.has_value());
242 // The transfomed coverage limit is ((0, 0), (90.9091, 90.9091)).
243 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
244 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [498/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverage |
| ) |  |

Definition at line 267 of file save_layer_utils_unittests.cc.

268 {
269 auto image_filter = FilterContents::MakeMatrixFilter(
270 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
271
272 auto coverage = ComputeSaveLayerCoverage(
273 /*content_coverage=*/Rect::MakeLTRB(0, 0, 1000, 1000), //
274 /*effect_transform=*/{}, //
275 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
276 /*image_filter=*/image_filter //
277 );
278
279 ASSERT_TRUE(coverage.has_value());
280 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
281 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [499/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoverage |
| ) |  |

Definition at line 94 of file save_layer_utils_unittests.cc.

94 {
95 // No intersection in coverage
96 auto coverage = ComputeSaveLayerCoverage(
97 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
98 /*effect_transform=*/{}, //
99 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
100 /*image_filter=*/nullptr //
101 );
102
103 EXPECT_FALSE(coverage.has_value());
104 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [500/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoverageTransformedByImageFilter |
| ) |  |

Definition at line 106 of file save_layer_utils_unittests.cc.

106 {
107 // Coverage disjoint from parent coverage but transformed into parent space
108 // with image filter.
109 auto image_filter = FilterContents::MakeMatrixFilter(
110 FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
111
112 auto coverage = ComputeSaveLayerCoverage(
113 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
114 /*effect_transform=*/{}, //
115 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
116 /*image_filter=*/image_filter //
117 );
118
119 ASSERT_TRUE(coverage.has_value());
120 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(200, 200, 210, 210));
121 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [501/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DisjointCoveragTransformedByCTM |
| ) |  |

Definition at line 123 of file save_layer_utils_unittests.cc.

123 {
124 // Coverage disjoint from parent coverage.
125 Matrix ctm = Matrix::MakeTranslation({-200, -200, 0});
126 auto coverage = ComputeSaveLayerCoverage(
127 /*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
128 /*effect_transform=*/ctm, //
129 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
130 /*image_filter=*/nullptr //
131 );
132
133 ASSERT_TRUE(coverage.has_value());
134 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
135 }

References impeller::ComputeSaveLayerCoverage(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [502/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight |
| ) |  |

Definition at line 311 of file save_layer_utils_unittests.cc.

311 {
312 // X varies, translation is performed on coverage.
313 auto coverage = ComputeSaveLayerCoverage(
314 /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 50), //
315 /*effect_transform=*/{}, //
316 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
317 /*image_filter=*/nullptr //
318 );
319
320 ASSERT_TRUE(coverage.has_value());
321 // Size that matches coverage limit
322 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 90, 50));
323 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [503/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth |
| ) |  |

Definition at line 297 of file save_layer_utils_unittests.cc.

297 {
298 // X varies, translation is performed on coverage.
299 auto coverage = ComputeSaveLayerCoverage(
300 /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 90), //
301 /*effect_transform=*/{}, //
302 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
303 /*image_filter=*/nullptr //
304 );
305
306 ASSERT_TRUE(coverage.has_value());
307 // Size that matches coverage limit
308 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 90));
309 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [504/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight |
| ) |  |

Definition at line 325 of file save_layer_utils_unittests.cc.

326 {
327 // X varies, translation is performed on coverage.
328 auto coverage = ComputeSaveLayerCoverage(
329 /*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 50), //
330 /*effect_transform=*/{}, //
331 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
332 /*image_filter=*/nullptr //
333 );
334
335 ASSERT_TRUE(coverage.has_value());
336 // Size that matches coverage limit
337 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
338 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [505/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverage |
| ) |  |

Definition at line 177 of file save_layer_utils_unittests.cc.

177 {
178 auto coverage = ComputeSaveLayerCoverage(
179 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
180 /*effect_transform=*/{}, //
181 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
182 /*image_filter=*/nullptr, //
183 /*flood_output_coverage=*/false, //
184 /*flood_input_coverage=*/true //
185 );
186
187 ASSERT_TRUE(coverage.has_value());
188 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
189 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [506/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverageWithImageFilter |
| ) |  |

Definition at line 191 of file save_layer_utils_unittests.cc.

191 {
192 auto image_filter = FilterContents::MakeMatrixFilter(
193 FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
194
195 auto coverage = ComputeSaveLayerCoverage(
196 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
197 /*effect_transform=*/{}, //
198 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
199 /*image_filter=*/image_filter, //
200 /*flood_output_coverage=*/false, //
201 /*flood_input_coverage=*/true //
202 );
203
204 ASSERT_TRUE(coverage.has_value());
205 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 4800, 3600));
206 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [507/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage |
| ) |  |

Definition at line 208 of file save_layer_utils_unittests.cc.

209 {
210 // Even if we flood the input coverage due to a bdf, we can still cull out the
211 // layer if the image filter results in no coverage.
212 auto image_filter = FilterContents::MakeMatrixFilter(
213 FilterInput::Make(Rect()), Matrix::MakeScale({1, 1, 0}), {});
214
215 auto coverage = ComputeSaveLayerCoverage(
216 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
217 /*effect_transform=*/{}, //
218 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
219 /*image_filter=*/image_filter, //
220 /*flood_output_coverage=*/false, //
221 /*flood_input_coverage=*/true //
222 );
223
224 ASSERT_FALSE(coverage.has_value());
225 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [508/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFilterEmptyCoverage |
| ) |  |

Definition at line 148 of file save_layer_utils_unittests.cc.

148 {
149 // Empty coverage with Image Filter
150 auto image_filter = FilterContents::MakeMatrixFilter(
151 FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
152
153 auto coverage = ComputeSaveLayerCoverage(
154 /*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
155 /*effect_transform=*/{}, //
156 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
157 /*image_filter=*/image_filter //
158 );
159
160 ASSERT_FALSE(coverage.has_value());
161 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [509/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterComputedCoverage |
| ) |  |

Definition at line 44 of file save_layer_utils_unittests.cc.

44 {
45 // Image Filter, computed coverage
46 auto image_filter = FilterContents::MakeMatrixFilter(
47 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
48
49 auto coverage = ComputeSaveLayerCoverage(
50 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
51 /*effect_transform=*/{}, //
52 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
53 /*image_filter=*/image_filter //
54 );
55
56 ASSERT_TRUE(coverage.has_value());
57 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
58 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [510/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit |
| ) |  |

Definition at line 77 of file save_layer_utils_unittests.cc.

78 {
79 // Image Filter scaling small, computed coverage is larger than bounds limit.
80 auto image_filter = FilterContents::MakeMatrixFilter(
81 FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
82
83 auto coverage = ComputeSaveLayerCoverage(
84 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
85 /*effect_transform=*/{}, //
86 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
87 /*image_filter=*/image_filter //
88 );
89
90 ASSERT_TRUE(coverage.has_value());
91 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
92 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [511/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit |
| ) |  |

Definition at line 60 of file save_layer_utils_unittests.cc.

61 {
62 // Image Filter scaling large, computed coverage is larger than bounds limit.
63 auto image_filter = FilterContents::MakeMatrixFilter(
64 FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
65
66 auto coverage = ComputeSaveLayerCoverage(
67 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
68 /*effect_transform=*/{}, //
69 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
70 /*image_filter=*/image_filter //
71 );
72
73 ASSERT_TRUE(coverage.has_value());
74 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2.5, 2.5));
75 }

References impeller::ComputeSaveLayerCoverage(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::FilterContents::MakeMatrixFilter(), and impeller::Matrix::MakeScale().

## ◆ TEST() [512/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | RoundUpCoverageWhenCloseToCoverageLimit |
| ) |  |

Definition at line 283 of file save_layer_utils_unittests.cc.

283 {
284 // X varies, translation is performed on coverage.
285 auto coverage = ComputeSaveLayerCoverage(
286 /*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 90), //
287 /*effect_transform=*/{}, //
288 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
289 /*image_filter=*/nullptr //
290 );
291
292 ASSERT_TRUE(coverage.has_value());
293 // Size that matches coverage limit
294 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
295 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [513/574]

impeller::testing::TEST | ( | SaveLayerUtilsTest | ,
|  | SimplePaintComputedCoverage |
| ) |  |

Definition at line 17 of file save_layer_utils_unittests.cc.

17 {
18 // Basic Case, simple paint, computed coverage
19 auto coverage = ComputeSaveLayerCoverage(
20 /*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
21 /*effect_transform=*/{}, //
22 /*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
23 /*image_filter=*/nullptr //
24 );
25 ASSERT_TRUE(coverage.has_value());
26 EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
27 }

References impeller::ComputeSaveLayerCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [514/574]

impeller::testing::TEST | ( | ShaderArchiveTest | ,
|  | CanReadAndWriteBlobs |
| ) |  |

Definition at line 30 of file shader_archive_unittests.cc.

30 {
31 ShaderArchiveWriter writer;
32 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Hello",
33 CreateMappingFromString("World")));
34 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Foo",
35 CreateMappingFromString("Bar")));
36 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Baz",
37 CreateMappingFromString("Bang")));
38 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Ping",
39 CreateMappingFromString("Pong")));
40 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Pang",
41 CreateMappingFromString("World")));
42
43 auto mapping = writer.CreateMapping();
44 ASSERT_NE(mapping, nullptr);
45
46 auto library = ShaderArchive::Create(mapping);
47 ASSERT_TRUE(library.ok());
48 ASSERT_EQ(library->GetShaderCount(), 5u);
49
50 // Wrong type.
51 ASSERT_EQ(library->GetMapping(ArchiveShaderType::kFragment, "Hello"),
52 nullptr);
53
54 auto hello_vtx = library->GetMapping(ArchiveShaderType::kVertex, "Hello");
55 ASSERT_NE(hello_vtx, nullptr);
56 ASSERT_EQ(CreateStringFromMapping(*hello_vtx), "World");
57 }
impeller::testing::CreateStringFromMapping
const std::string CreateStringFromMapping(const fml::Mapping &mapping)
Definition: shader_archive_unittests.cc:25
impeller::testing::CreateMappingFromString
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)
Definition: shader_archive_unittests.cc:17

References impeller::ShaderArchiveWriter::AddShader(), impeller::ShaderArchive::Create(), impeller::ShaderArchiveWriter::CreateMapping(), CreateMappingFromString(), CreateStringFromMapping(), impeller::kFragment, and impeller::kVertex.

## ◆ TEST() [515/574]

impeller::testing::TEST | ( | ShaderArchiveTest | ,
|  | ReturnsErrorOnInvalidVersion |
| ) |  |

Definition at line 59 of file shader_archive_unittests.cc.

59 {
60 fb::ShaderArchiveT shader_archive;
61 shader_archive.format_version = -1;
62
63 auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
64 builder->Finish(fb::ShaderArchive::Pack(*builder.get(), &shader_archive),
65 fb::ShaderArchiveIdentifier());
66 auto mapping = std::make_shared<fml::NonOwnedMapping>(
67 builder->GetBufferPointer(), builder->GetSize(),
68 [builder](auto, auto) {});
69
70 auto library = ShaderArchive::Create(mapping);
71 ASSERT_FALSE(library.ok());
72 ASSERT_EQ(library.status().code(), absl::StatusCode::kInvalidArgument);
73 std::stringstream stream;
74 stream << "Unsupported shader archive format version. Expected: "
75 << static_cast<uint32_t>(fb::ShaderArchiveFormatVersion::kVersion)
76 << ", Got: 4294967295";
77 ASSERT_EQ(library.status().message(), stream.str());
78 }

References impeller::ShaderArchive::Create().

## ◆ TEST() [516/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseOctagonCollapsedUmbraPolygonTest |
| ) |  |

Definition at line 972 of file shadow_path_geometry_unittests.cc.

972 {
973 const Matrix matrix = Matrix::MakeScale({2, 2, 1});
974 const Scalar height = 100.0f;
975
976 DlPathBuilder path_builder;
977 path_builder.MoveTo(DlPoint(100, 125));
978 path_builder.LineTo(DlPoint(125, 100));
979 path_builder.LineTo(DlPoint(275, 100));
980 path_builder.LineTo(DlPoint(300, 125));
981 path_builder.LineTo(DlPoint(300, 275));
982 path_builder.LineTo(DlPoint(275, 300));
983 path_builder.LineTo(DlPoint(125, 300));
984 path_builder.LineTo(DlPoint(100, 275));
985 path_builder.Close();
986 DlPath path = path_builder.TakePath();
987
988 Tessellator tessellator;
989 std::shared_ptr<ShadowVertices> shadow_vertices =
990 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
991 matrix);
992
993 ASSERT_NE(shadow_vertices, nullptr);
994 EXPECT_FALSE(shadow_vertices->IsEmpty());
995 EXPECT_EQ(shadow_vertices->GetVertexCount(), 87u);
996 EXPECT_EQ(shadow_vertices->GetIndexCount(), 267u);
997 EXPECT_EQ(shadow_vertices->GetVertices().size(), 87u);
998 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 87u);
999 EXPECT_EQ(shadow_vertices->GetIndices().size(), 267u);
1000 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
1001 // We repeat the first and last vertex that is on the outer umbra.
1002 // There are a couple additional duplicate vertices in this case.
1003 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1004 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1005 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1006 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices(), and impeller::Matrix::MakeScale().

## ◆ TEST() [517/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseRectExtraColinearPointsTest |
| ) |  |

Definition at line 417 of file shadow_path_geometry_unittests.cc.

417 {
418 // This path includes a colinear point to each edge of the rectangle
419 // which should be trimmed out and ignored when generating the mesh
420 // resulting in the same number of vertices and triangles as the mesh
421 // above.
422 DlPathBuilder path_builder;
423 path_builder.MoveTo(DlPoint(0, 0));
424 path_builder.LineTo(DlPoint(50, 0));
425 path_builder.LineTo(DlPoint(100, 0));
426 path_builder.LineTo(DlPoint(100, 40));
427 path_builder.LineTo(DlPoint(100, 80));
428 path_builder.LineTo(DlPoint(50, 80));
429 path_builder.LineTo(DlPoint(0, 80));
430 path_builder.LineTo(DlPoint(0, 40));
431 path_builder.Close();
432 const DlPath path = path_builder.TakePath();
433 const Matrix matrix;
434 const Scalar height = 10.0f;
435
436 Tessellator tessellator;
437 std::shared_ptr<ShadowVertices> shadow_vertices =
438 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
439 matrix);
440
441 ASSERT_NE(shadow_vertices, nullptr);
442 EXPECT_FALSE(shadow_vertices->IsEmpty());
443 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
444 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
445 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
446 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
447 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
448 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
449 // We repeat the first and last vertex that is on the outer umbra.
450 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
451 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
452 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
453
454 #if SHADOW_UNITTEST_SHOW_VERTICES
455 ShowVertices("Impeller Vertices", shadow_vertices);
456 #endif
457 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [518/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseRectNearlyColinearPointsTest |
| ) |  |

Definition at line 677 of file shadow_path_geometry_unittests.cc.

677 {
678 // This path includes a bunch of colinear points and one point that
679 // is barely non-colinear but still convex. It should add exactly
680 // one extra set of vertices to the mesh (3 points and 3 triangles)
681 // compared to the regular rects.
682 DlPathBuilder path_builder;
683 path_builder.MoveTo(DlPoint(0, 0));
684 path_builder.LineTo(DlPoint(50, -0.065));
685 path_builder.LineTo(DlPoint(100, 0));
686 path_builder.LineTo(DlPoint(100, 40));
687 path_builder.LineTo(DlPoint(100, 80));
688 path_builder.LineTo(DlPoint(50, 80));
689 path_builder.LineTo(DlPoint(0, 80));
690 path_builder.LineTo(DlPoint(0, 40));
691 path_builder.Close();
692 const DlPath path = path_builder.TakePath();
693 const Matrix matrix;
694 const Scalar height = 10.0f;
695
696 Tessellator tessellator;
697 std::shared_ptr<ShadowVertices> shadow_vertices =
698 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
699 matrix);
700
701 ASSERT_NE(shadow_vertices, nullptr);
702 EXPECT_FALSE(shadow_vertices->IsEmpty());
703 EXPECT_EQ(shadow_vertices->GetVertexCount(), 37u);
704 EXPECT_EQ(shadow_vertices->GetIndexCount(), 120u);
705 EXPECT_EQ(shadow_vertices->GetVertices().size(), 37u);
706 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 37u);
707 EXPECT_EQ(shadow_vertices->GetIndices().size(), 120u);
708 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
709 // We repeat the first and last vertex that is on the outer umbra.
710 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
711 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
712 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
713
714 #if SHADOW_UNITTEST_SHOW_VERTICES
715 ShowVertices("Impeller Vertices", shadow_vertices);
716 #endif
717 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [519/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseRectTest |
| ) |  |

Definition at line 349 of file shadow_path_geometry_unittests.cc.

349 {
350 DlPathBuilder path_builder;
351 path_builder.MoveTo(DlPoint(0, 0));
352 path_builder.LineTo(DlPoint(100, 0));
353 path_builder.LineTo(DlPoint(100, 80));
354 path_builder.LineTo(DlPoint(0, 80));
355 path_builder.Close();
356 const DlPath path = path_builder.TakePath();
357 const Matrix matrix;
358 const Scalar height = 10.0f;
359
360 Tessellator tessellator;
361 std::shared_ptr<ShadowVertices> shadow_vertices =
362 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
363 matrix);
364
365 ASSERT_NE(shadow_vertices, nullptr);
366 EXPECT_FALSE(shadow_vertices->IsEmpty());
367 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
368 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
369 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
370 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
371 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
372 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
373 // We repeat the first and last vertex that is on the outer umbra.
374 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
375 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
376 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
377
378 #if SHADOW_UNITTEST_SHOW_VERTICES
379 ShowVertices("Impeller Vertices", shadow_vertices);
380 #endif
381 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [520/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseRectTrickyColinearPointsTest |
| ) |  |

Definition at line 501 of file shadow_path_geometry_unittests.cc.

501 {
502 // This path includes a colinear point added to each edge of the rectangle
503 // which seems to violate convexity, but is eliminated as not contributing
504 // to the path. We should be able to process the path anyway.
505 DlPathBuilder path_builder;
506 path_builder.MoveTo(DlPoint(0, 0));
507 path_builder.LineTo(DlPoint(-10, 0));
508 path_builder.LineTo(DlPoint(100, 0));
509 path_builder.LineTo(DlPoint(100, -10));
510 path_builder.LineTo(DlPoint(100, 80));
511 path_builder.LineTo(DlPoint(110, 80));
512 path_builder.LineTo(DlPoint(0, 80));
513 path_builder.LineTo(DlPoint(0, 90));
514 path_builder.Close();
515 const DlPath path = path_builder.TakePath();
516 const Matrix matrix;
517 const Scalar height = 10.0f;
518
519 Tessellator tessellator;
520 std::shared_ptr<ShadowVertices> shadow_vertices =
521 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
522 matrix);
523
524 ASSERT_NE(shadow_vertices, nullptr);
525 EXPECT_FALSE(shadow_vertices->IsEmpty());
526 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
527 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
528 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
529 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
530 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
531 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
532 // We repeat the first and last vertex that is on the outer umbra.
533 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
534 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
535 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
536
537 #if SHADOW_UNITTEST_SHOW_VERTICES
538 ShowVertices("Impeller Vertices", shadow_vertices);
539 #endif
540 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [521/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseRectTrickyDupColinearPointsTest |
| ) |  |

Definition at line 583 of file shadow_path_geometry_unittests.cc.

583 {
584 // This path includes a colinear point added to each edge of the rectangle
585 // which seems to violate convexity, but is eliminated as not contributing
586 // to the path. We should be able to process the path anyway.
587 // It also includes multiple collinear points on the first and last points
588 // that end up back where we started to make sure that in that case we
589 // eliminate all of the collinear points and the duplicate, rather than
590 // just the intermediate collinear points.
591 DlPathBuilder path_builder;
592 path_builder.MoveTo(DlPoint(0, 0));
593 path_builder.LineTo(DlPoint(-10, 0));
594 path_builder.LineTo(DlPoint(0, 0));
595 path_builder.LineTo(DlPoint(100, 0));
596 path_builder.LineTo(DlPoint(100, -10));
597 path_builder.LineTo(DlPoint(100, 80));
598 path_builder.LineTo(DlPoint(110, 80));
599 path_builder.LineTo(DlPoint(0, 80));
600 path_builder.LineTo(DlPoint(0, 90));
601 path_builder.LineTo(DlPoint(0, 80));
602 path_builder.Close();
603 const DlPath path = path_builder.TakePath();
604 const Matrix matrix;
605 const Scalar height = 10.0f;
606
607 Tessellator tessellator;
608 std::shared_ptr<ShadowVertices> shadow_vertices =
609 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
610 matrix);
611
612 ASSERT_NE(shadow_vertices, nullptr);
613 EXPECT_FALSE(shadow_vertices->IsEmpty());
614 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
615 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
616 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
617 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
618 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
619 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
620 // We repeat the first and last vertex that is on the outer umbra.
621 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
622 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
623 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
624
625 #if SHADOW_UNITTEST_SHOW_VERTICES
626 ShowVertices("Impeller Vertices", shadow_vertices);
627 #endif
628 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [522/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ClockwiseTriangleTest |
| ) |  |

Definition at line 281 of file shadow_path_geometry_unittests.cc.

281 {
282 DlPathBuilder path_builder;
283 path_builder.MoveTo(DlPoint(100, 0));
284 path_builder.LineTo(DlPoint(200, 110));
285 path_builder.LineTo(DlPoint(0, 110));
286 path_builder.Close();
287 const DlPath path = path_builder.TakePath();
288 const Matrix matrix;
289 const Scalar height = 10.0f;
290
291 Tessellator tessellator;
292 std::shared_ptr<ShadowVertices> shadow_vertices =
293 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
294 matrix);
295
296 ASSERT_NE(shadow_vertices, nullptr);
297 EXPECT_FALSE(shadow_vertices->IsEmpty());
298 EXPECT_EQ(shadow_vertices->GetVertexCount(), 33u);
299 EXPECT_EQ(shadow_vertices->GetIndexCount(), 102u);
300 EXPECT_EQ(shadow_vertices->GetVertices().size(), 33u);
301 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 33u);
302 EXPECT_EQ(shadow_vertices->GetIndices().size(), 102u);
303 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
304 // We repeat the first and last vertex that is on the outer umbra.
305 // There is another duplicate vertex from somewhere else not yet realized.
306 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
307 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
308 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
309
310 #if SHADOW_UNITTEST_SHOW_VERTICES
311 ShowVertices("Impeller Vertices", shadow_vertices);
312 #endif
313 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [523/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseOctagonCollapsedUmbraPolygonTest |
| ) |  |

Definition at line 1008 of file shadow_path_geometry_unittests.cc.

1008 {
1009 const Matrix matrix = Matrix::MakeScale({2, 2, 1});
1010 const Scalar height = 100.0f;
1011
1012 DlPathBuilder path_builder;
1013 path_builder.MoveTo(DlPoint(100, 125));
1014 path_builder.LineTo(DlPoint(100, 275));
1015 path_builder.LineTo(DlPoint(125, 300));
1016 path_builder.LineTo(DlPoint(275, 300));
1017 path_builder.LineTo(DlPoint(300, 275));
1018 path_builder.LineTo(DlPoint(300, 125));
1019 path_builder.LineTo(DlPoint(275, 100));
1020 path_builder.LineTo(DlPoint(125, 100));
1021 path_builder.Close();
1022 DlPath path = path_builder.TakePath();
1023
1024 Tessellator tessellator;
1025 std::shared_ptr<ShadowVertices> shadow_vertices =
1026 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
1027 matrix);
1028
1029 ASSERT_NE(shadow_vertices, nullptr);
1030 EXPECT_FALSE(shadow_vertices->IsEmpty());
1031 EXPECT_EQ(shadow_vertices->GetVertexCount(), 88u);
1032 EXPECT_EQ(shadow_vertices->GetIndexCount(), 267u);
1033 EXPECT_EQ(shadow_vertices->GetVertices().size(), 88u);
1034 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 88u);
1035 EXPECT_EQ(shadow_vertices->GetIndices().size(), 267u);
1036 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
1037 // We repeat the first and last vertex that is on the outer umbra.
1038 // There are a couple additional duplicate vertices in this case.
1039 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 3u);
1040 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
1041 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
1042 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices(), and impeller::Matrix::MakeScale().

## ◆ TEST() [524/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseRectExtraColinearPointsTest |
| ) |  |

Definition at line 459 of file shadow_path_geometry_unittests.cc.

459 {
460 // This path includes a colinear point to each edge of the rectangle
461 // which should be trimmed out and ignored when generating the mesh
462 // resulting in the same number of vertices and triangles as the mesh
463 // above.
464 DlPathBuilder path_builder;
465 path_builder.MoveTo(DlPoint(0, 0));
466 path_builder.LineTo(DlPoint(0, 40));
467 path_builder.LineTo(DlPoint(0, 80));
468 path_builder.LineTo(DlPoint(50, 80));
469 path_builder.LineTo(DlPoint(100, 80));
470 path_builder.LineTo(DlPoint(100, 40));
471 path_builder.LineTo(DlPoint(100, 0));
472 path_builder.LineTo(DlPoint(50, 0));
473 path_builder.Close();
474 DlPath path = path_builder.TakePath();
475 Matrix matrix;
476 const Scalar height = 10.0f;
477
478 Tessellator tessellator;
479 std::shared_ptr<ShadowVertices> shadow_vertices =
480 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
481 matrix);
482
483 ASSERT_NE(shadow_vertices, nullptr);
484 EXPECT_FALSE(shadow_vertices->IsEmpty());
485 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
486 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
487 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
488 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
489 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
490 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
491 // We repeat the first and last vertex that is on the outer umbra.
492 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
493 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
494 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
495
496 #if SHADOW_UNITTEST_SHOW_VERTICES
497 ShowVertices("Impeller Vertices", shadow_vertices);
498 #endif
499 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [525/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseRectNearlyColinearPointsTest |
| ) |  |

Definition at line 719 of file shadow_path_geometry_unittests.cc.

719 {
720 // This path includes a bunch of colinear points and one point that
721 // is barely non-colinear but still convex. It should add exactly
722 // one extra set of vertices to the mesh (3 points and 3 triangles)
723 // compared to the regular rects.
724 DlPathBuilder path_builder;
725 path_builder.MoveTo(DlPoint(0, 0));
726 path_builder.LineTo(DlPoint(-0.065, 40));
727 path_builder.LineTo(DlPoint(0, 80));
728 path_builder.LineTo(DlPoint(50, 80));
729 path_builder.LineTo(DlPoint(100, 80));
730 path_builder.LineTo(DlPoint(100, 40));
731 path_builder.LineTo(DlPoint(100, 0));
732 path_builder.LineTo(DlPoint(50, 0));
733 path_builder.Close();
734 DlPath path = path_builder.TakePath();
735 Matrix matrix;
736 const Scalar height = 10.0f;
737
738 Tessellator tessellator;
739 std::shared_ptr<ShadowVertices> shadow_vertices =
740 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
741 matrix);
742
743 ASSERT_NE(shadow_vertices, nullptr);
744 EXPECT_FALSE(shadow_vertices->IsEmpty());
745 EXPECT_EQ(shadow_vertices->GetVertexCount(), 37u);
746 EXPECT_EQ(shadow_vertices->GetIndexCount(), 120u);
747 EXPECT_EQ(shadow_vertices->GetVertices().size(), 37u);
748 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 37u);
749 EXPECT_EQ(shadow_vertices->GetIndices().size(), 120u);
750 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
751 // We repeat the first and last vertex that is on the outer umbra.
752 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
753 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
754 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
755
756 #if SHADOW_UNITTEST_SHOW_VERTICES
757 ShowVertices("Impeller Vertices", shadow_vertices);
758 #endif
759 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [526/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseRectTest |
| ) |  |

Definition at line 383 of file shadow_path_geometry_unittests.cc.

383 {
384 DlPathBuilder path_builder;
385 path_builder.MoveTo(DlPoint(0, 0));
386 path_builder.LineTo(DlPoint(0, 80));
387 path_builder.LineTo(DlPoint(100, 80));
388 path_builder.LineTo(DlPoint(100, 0));
389 path_builder.Close();
390 DlPath path = path_builder.TakePath();
391 Matrix matrix;
392 const Scalar height = 10.0f;
393
394 Tessellator tessellator;
395 std::shared_ptr<ShadowVertices> shadow_vertices =
396 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
397 matrix);
398
399 ASSERT_NE(shadow_vertices, nullptr);
400 EXPECT_FALSE(shadow_vertices->IsEmpty());
401 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
402 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
403 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
404 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
405 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
406 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
407 // We repeat the first and last vertex that is on the outer umbra.
408 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
409 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
410 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
411
412 #if SHADOW_UNITTEST_SHOW_VERTICES
413 ShowVertices("Impeller Vertices", shadow_vertices);
414 #endif
415 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [527/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseRectTrickyColinearPointsTest |
| ) |  |

Definition at line 542 of file shadow_path_geometry_unittests.cc.

542 {
543 // This path includes a colinear point added to each edge of the rectangle
544 // which seems to violate convexity, but is eliminated as not contributing
545 // to the path. We should be able to process the path anyway.
546 DlPathBuilder path_builder;
547 path_builder.MoveTo(DlPoint(0, 0));
548 path_builder.LineTo(DlPoint(0, -10));
549 path_builder.LineTo(DlPoint(0, 80));
550 path_builder.LineTo(DlPoint(-10, 80));
551 path_builder.LineTo(DlPoint(100, 80));
552 path_builder.LineTo(DlPoint(100, 90));
553 path_builder.LineTo(DlPoint(100, 0));
554 path_builder.LineTo(DlPoint(110, 0));
555 path_builder.Close();
556 DlPath path = path_builder.TakePath();
557 Matrix matrix;
558 const Scalar height = 10.0f;
559
560 Tessellator tessellator;
561 std::shared_ptr<ShadowVertices> shadow_vertices =
562 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
563 matrix);
564
565 ASSERT_NE(shadow_vertices, nullptr);
566 EXPECT_FALSE(shadow_vertices->IsEmpty());
567 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
568 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
569 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
570 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
571 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
572 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
573 // We repeat the first and last vertex that is on the outer umbra.
574 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
575 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
576 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
577
578 #if SHADOW_UNITTEST_SHOW_VERTICES
579 ShowVertices("Impeller Vertices", shadow_vertices);
580 #endif
581 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [528/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseRectTrickyDupColinearPointsTest |
| ) |  |

Definition at line 630 of file shadow_path_geometry_unittests.cc.

630 {
631 // This path includes a colinear point added to each edge of the rectangle
632 // which seems to violate convexity, but is eliminated as not contributing
633 // to the path. We should be able to process the path anyway.
634 // It also includes multiple collinear points on the first and last points
635 // that end up back where we started to make sure that in that case we
636 // eliminate all of the collinear points and the duplicate, rather than
637 // just the intermediate collinear points.
638 DlPathBuilder path_builder;
639 path_builder.MoveTo(DlPoint(0, 0));
640 path_builder.LineTo(DlPoint(0, -10));
641 path_builder.LineTo(DlPoint(0, 0));
642 path_builder.LineTo(DlPoint(0, 80));
643 path_builder.LineTo(DlPoint(-10, 80));
644 path_builder.LineTo(DlPoint(100, 80));
645 path_builder.LineTo(DlPoint(100, 90));
646 path_builder.LineTo(DlPoint(100, 0));
647 path_builder.LineTo(DlPoint(110, 0));
648 path_builder.LineTo(DlPoint(100, 0));
649 path_builder.Close();
650 DlPath path = path_builder.TakePath();
651 Matrix matrix;
652 const Scalar height = 10.0f;
653
654 Tessellator tessellator;
655 std::shared_ptr<ShadowVertices> shadow_vertices =
656 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
657 matrix);
658
659 ASSERT_NE(shadow_vertices, nullptr);
660 EXPECT_FALSE(shadow_vertices->IsEmpty());
661 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
662 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
663 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
664 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
665 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
666 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
667 // We repeat the first and last vertex that is on the outer umbra.
668 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
669 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
670 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
671
672 #if SHADOW_UNITTEST_SHOW_VERTICES
673 ShowVertices("Impeller Vertices", shadow_vertices);
674 #endif
675 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [529/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | CounterClockwiseTriangleTest |
| ) |  |

Definition at line 315 of file shadow_path_geometry_unittests.cc.

315 {
316 DlPathBuilder path_builder;
317 path_builder.MoveTo(DlPoint(100, 0));
318 path_builder.LineTo(DlPoint(0, 110));
319 path_builder.LineTo(DlPoint(200, 110));
320 path_builder.Close();
321 const DlPath path = path_builder.TakePath();
322 const Matrix matrix;
323 const Scalar height = 10.0f;
324
325 Tessellator tessellator;
326 std::shared_ptr<ShadowVertices> shadow_vertices =
327 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
328 matrix);
329
330 ASSERT_NE(shadow_vertices, nullptr);
331 EXPECT_FALSE(shadow_vertices->IsEmpty());
332 EXPECT_EQ(shadow_vertices->GetVertexCount(), 33u);
333 EXPECT_EQ(shadow_vertices->GetIndexCount(), 102u);
334 EXPECT_EQ(shadow_vertices->GetVertices().size(), 33u);
335 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 33u);
336 EXPECT_EQ(shadow_vertices->GetIndices().size(), 102u);
337 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
338 // We repeat the first and last vertex that is on the outer umbra.
339 // There is another duplicate vertex from somewhere else not yet realized.
340 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
341 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
342 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
343
344 #if SHADOW_UNITTEST_SHOW_VERTICES
345 ShowVertices("Impeller Vertices", shadow_vertices);
346 #endif
347 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [530/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | EllipseTest |
| ) |  |

Definition at line 789 of file shadow_path_geometry_unittests.cc.

789 {
790 Tessellator tessellator;
791 DlPath path = DlPath::MakeOval(DlRect::MakeLTRB(0, 0, 100, 80));
792 Matrix matrix;
793 const Scalar height = 10.0f;
794
795 std::shared_ptr<ShadowVertices> shadow_vertices =
796 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
797 matrix);
798
799 ASSERT_NE(shadow_vertices, nullptr);
800 EXPECT_FALSE(shadow_vertices->IsEmpty());
801 EXPECT_EQ(shadow_vertices->GetVertexCount(), 122u);
802 EXPECT_EQ(shadow_vertices->GetIndexCount(), 480u);
803 EXPECT_EQ(shadow_vertices->GetVertices().size(), 122u);
804 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 122u);
805 EXPECT_EQ(shadow_vertices->GetIndices().size(), 480u);
806 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
807 // We repeat the first and last vertex that is on the outer umbra.
808 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
809 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
810 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
811 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [531/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | EmptyPathTest |
| ) |  |

Definition at line 175 of file shadow_path_geometry_unittests.cc.

175 {
176 DlPathBuilder path_builder;
177 const DlPath path = path_builder.TakePath();
178 const Matrix matrix;
179 const Scalar height = 10.0f;
180
181 Tessellator tessellator;
182 std::shared_ptr<ShadowVertices> shadow_vertices =
183 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
184 matrix);
185
186 ASSERT_NE(shadow_vertices, nullptr);
187 EXPECT_TRUE(shadow_vertices->IsEmpty());
188 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [532/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | EmptyRectTest |
| ) |  |

Definition at line 241 of file shadow_path_geometry_unittests.cc.

241 {
242 DlPathBuilder path_builder;
243 path_builder.MoveTo(DlPoint(100, 100));
244 path_builder.LineTo(DlPoint(200, 100));
245 path_builder.LineTo(DlPoint(200, 100));
246 path_builder.LineTo(DlPoint(100, 100));
247 path_builder.Close();
248 const DlPath path = path_builder.TakePath();
249 const Matrix matrix;
250 const Scalar height = 10.0f;
251
252 Tessellator tessellator;
253 std::shared_ptr<ShadowVertices> shadow_vertices =
254 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
255 matrix);
256
257 ASSERT_NE(shadow_vertices, nullptr);
258 EXPECT_TRUE(shadow_vertices->IsEmpty());
259 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [533/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | GetAndTakeVertices |
| ) |  |

Definition at line 261 of file shadow_path_geometry_unittests.cc.

261 {
262 DlPath path = DlPath::MakeRectLTRB(100, 100, 200, 200);
263 const Scalar height = 10.0f;
264
265 Tessellator tessellator;
266 ShadowPathGeometry geometry(tessellator, {}, path, height);
267
268 // Can call Get as many times as you want.
269 for (int i = 0; i < 10; i++) {
270 EXPECT_TRUE(geometry.GetShadowVertices());
271 }
272
273 // Can only call Take once.
274 EXPECT_TRUE(geometry.TakeShadowVertices());
275
276 // Further access wll then fail.
277 EXPECT_FALSE(geometry.GetShadowVertices());
278 EXPECT_FALSE(geometry.TakeShadowVertices());
279 }

## ◆ TEST() [534/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | HourglassSelfIntersectingTest |
| ) |  |

Definition at line 838 of file shadow_path_geometry_unittests.cc.

838 {
839 DlPathBuilder path_builder;
840 path_builder.MoveTo(DlPoint(0, 0));
841 path_builder.LineTo(DlPoint(100, 80));
842 path_builder.LineTo(DlPoint(100, 0));
843 path_builder.LineTo(DlPoint(0, 80));
844 path_builder.Close();
845 const DlPath path = path_builder.TakePath();
846 const Matrix matrix;
847 const Scalar height = 10.0f;
848
849 Tessellator tessellator;
850 std::shared_ptr<ShadowVertices> shadow_vertices =
851 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
852 matrix);
853
854 EXPECT_EQ(shadow_vertices, nullptr);
855 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [535/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | InnerToOuterOverturningSpiralTest |
| ) |  |

Definition at line 876 of file shadow_path_geometry_unittests.cc.

876 {
877 const Matrix matrix;
878 const Scalar height = 10.0f;
879 int step_count = 20;
880
881 DlPathBuilder path_builder;
882 path_builder.MoveTo(DlPoint(300, 200));
883 for (int i = 1; i < step_count * 2; i++) {
884 Scalar angle = (k2Pi * i) / step_count;
885 Scalar radius = 80.0f + std::abs(i - step_count);
886 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
887 std::sin(angle) * radius));
888 }
889 path_builder.Close();
890 DlPath path = path_builder.TakePath();
891
892 Tessellator tessellator;
893 std::shared_ptr<ShadowVertices> shadow_vertices =
894 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
895 matrix);
896
897 EXPECT_EQ(shadow_vertices, nullptr);
898 }

References impeller::k2Pi, and impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [536/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | MoveToOnlyTest |
| ) |  |

Definition at line 190 of file shadow_path_geometry_unittests.cc.

190 {
191 DlPathBuilder path_builder;
192 path_builder.MoveTo(DlPoint(100, 100));
193 const DlPath path = path_builder.TakePath();
194 const Matrix matrix;
195 const Scalar height = 10.0f;
196
197 Tessellator tessellator;
198 std::shared_ptr<ShadowVertices> shadow_vertices =
199 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
200 matrix);
201
202 ASSERT_NE(shadow_vertices, nullptr);
203 EXPECT_TRUE(shadow_vertices->IsEmpty());
204 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [537/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | MultipleContoursTest |
| ) |  |

Definition at line 1044 of file shadow_path_geometry_unittests.cc.

1044 {
1045 const Matrix matrix;
1046 const Scalar height = 10.0f;
1047
1048 DlPathBuilder path_builder;
1049 path_builder.MoveTo(DlPoint(150, 100));
1050 path_builder.LineTo(DlPoint(200, 300));
1051 path_builder.LineTo(DlPoint(100, 300));
1052 path_builder.Close();
1053 path_builder.MoveTo(DlPoint(250, 100));
1054 path_builder.LineTo(DlPoint(300, 300));
1055 path_builder.LineTo(DlPoint(200, 300));
1056 path_builder.Close();
1057 DlPath path = path_builder.TakePath();
1058
1059 Tessellator tessellator;
1060 std::shared_ptr<ShadowVertices> shadow_vertices =
1061 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
1062 matrix);
1063
1064 EXPECT_EQ(shadow_vertices, nullptr);
1065 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [538/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | OnePathSegmentTest |
| ) |  |

Definition at line 206 of file shadow_path_geometry_unittests.cc.

206 {
207 DlPathBuilder path_builder;
208 path_builder.MoveTo(DlPoint(100, 100));
209 path_builder.LineTo(DlPoint(200, 100));
210 const DlPath path = path_builder.TakePath();
211 const Matrix matrix;
212 const Scalar height = 10.0f;
213
214 Tessellator tessellator;
215 std::shared_ptr<ShadowVertices> shadow_vertices =
216 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
217 matrix);
218
219 ASSERT_NE(shadow_vertices, nullptr);
220 EXPECT_TRUE(shadow_vertices->IsEmpty());
221 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [539/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | OuterToInnerOverturningSpiralTest |
| ) |  |

Definition at line 924 of file shadow_path_geometry_unittests.cc.

924 {
925 const Matrix matrix;
926 const Scalar height = 10.0f;
927 int step_count = 20;
928
929 DlPathBuilder path_builder;
930 path_builder.MoveTo(DlPoint(280, 200));
931 for (int i = 1; i < step_count * 2; i++) {
932 Scalar angle = (k2Pi * i) / step_count;
933 Scalar radius = 100.0f - std::abs(i - step_count);
934 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
935 std::sin(angle) * radius));
936 }
937 path_builder.Close();
938 DlPath path = path_builder.TakePath();
939
940 Tessellator tessellator;
941 std::shared_ptr<ShadowVertices> shadow_vertices =
942 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
943 matrix);
944
945 EXPECT_EQ(shadow_vertices, nullptr);
946 }

References impeller::k2Pi, and impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [540/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ReverseHourglassSelfIntersectingTest |
| ) |  |

Definition at line 857 of file shadow_path_geometry_unittests.cc.

857 {
858 DlPathBuilder path_builder;
859 path_builder.MoveTo(DlPoint(0, 0));
860 path_builder.LineTo(DlPoint(100, 80));
861 path_builder.LineTo(DlPoint(0, 80));
862 path_builder.LineTo(DlPoint(100, 0));
863 path_builder.Close();
864 const DlPath path = path_builder.TakePath();
865 const Matrix matrix;
866 const Scalar height = 10.0f;
867
868 Tessellator tessellator;
869 std::shared_ptr<ShadowVertices> shadow_vertices =
870 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
871 matrix);
872
873 EXPECT_EQ(shadow_vertices, nullptr);
874 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [541/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ReverseInnerToOuterOverturningSpiralTest |
| ) |  |

Definition at line 900 of file shadow_path_geometry_unittests.cc.

900 {
901 const Matrix matrix;
902 const Scalar height = 10.0f;
903 int step_count = 20;
904
905 DlPathBuilder path_builder;
906 path_builder.MoveTo(DlPoint(300, 200));
907 for (int i = 1; i < step_count * 2; i++) {
908 Scalar angle = -(k2Pi * i) / step_count;
909 Scalar radius = 80.0f + std::abs(i - step_count);
910 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
911 std::sin(angle) * radius));
912 }
913 path_builder.Close();
914 DlPath path = path_builder.TakePath();
915
916 Tessellator tessellator;
917 std::shared_ptr<ShadowVertices> shadow_vertices =
918 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
919 matrix);
920
921 EXPECT_EQ(shadow_vertices, nullptr);
922 }

References impeller::k2Pi, and impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [542/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ReverseOuterToInnerOverturningSpiralTest |
| ) |  |

Definition at line 948 of file shadow_path_geometry_unittests.cc.

948 {
949 const Matrix matrix;
950 const Scalar height = 10.0f;
951 int step_count = 20;
952
953 DlPathBuilder path_builder;
954 path_builder.MoveTo(DlPoint(280, 200));
955 for (int i = 1; i < step_count * 2; i++) {
956 Scalar angle = -(k2Pi * i) / step_count;
957 Scalar radius = 100.0f - std::abs(i - step_count);
958 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
959 std::sin(angle) * radius));
960 }
961 path_builder.Close();
962 DlPath path = path_builder.TakePath();
963
964 Tessellator tessellator;
965 std::shared_ptr<ShadowVertices> shadow_vertices =
966 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
967 matrix);
968
969 EXPECT_EQ(shadow_vertices, nullptr);
970 }

References impeller::k2Pi, and impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [543/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | RoundRectTest |
| ) |  |

Definition at line 813 of file shadow_path_geometry_unittests.cc.

813 {
814 Tessellator tessellator;
815 DlPath path = DlPath::MakeRoundRectXY(DlRect::MakeLTRB(0, 0, 100, 80), 5, 4);
816 Matrix matrix;
817 const Scalar height = 10.0f;
818
819 std::shared_ptr<ShadowVertices> shadow_vertices =
820 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
821 matrix);
822
823 ASSERT_NE(shadow_vertices, nullptr);
824 EXPECT_FALSE(shadow_vertices->IsEmpty());
825 EXPECT_EQ(shadow_vertices->GetVertexCount(), 55u);
826 EXPECT_EQ(shadow_vertices->GetIndexCount(), 168u);
827 EXPECT_EQ(shadow_vertices->GetVertices().size(), 55u);
828 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 55u);
829 EXPECT_EQ(shadow_vertices->GetIndices().size(), 168u);
830 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
831 // We repeat the first and last vertex that is on the outer umbra.
832 // There is another duplicate vertex from somewhere else not yet realized.
833 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 2u);
834 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
835 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
836 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [544/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | ScaledRectTest |
| ) |  |

Definition at line 761 of file shadow_path_geometry_unittests.cc.

761 {
762 Tessellator tessellator;
763 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 100, 80));
764 Matrix matrix = Matrix::MakeScale({2, 3, 1});
765 const Scalar height = 10.0f;
766
767 std::shared_ptr<ShadowVertices> shadow_vertices =
768 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
769 matrix);
770
771 ASSERT_NE(shadow_vertices, nullptr);
772 EXPECT_FALSE(shadow_vertices->IsEmpty());
773 EXPECT_EQ(shadow_vertices->GetVertexCount(), 34u);
774 EXPECT_EQ(shadow_vertices->GetIndexCount(), 108u);
775 EXPECT_EQ(shadow_vertices->GetVertices().size(), 34u);
776 EXPECT_EQ(shadow_vertices->GetGaussians().size(), 34u);
777 EXPECT_EQ(shadow_vertices->GetIndices().size(), 108u);
778 EXPECT_EQ((shadow_vertices->GetIndices().size() % 3u), 0u);
779 // We repeat the first and last vertex that is on the outer umbra.
780 EXPECT_LE(CountDuplicateVertices(shadow_vertices), 1u);
781 EXPECT_EQ(CountDuplicateTriangles(shadow_vertices), 0u);
782 EXPECT_FALSE(DoTrianglesOverlap(shadow_vertices));
783
784 #if SHADOW_UNITTEST_SHOW_VERTICES
785 ShowVertices("Impeller Vertices", shadow_vertices);
786 #endif
787 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices(), and impeller::Matrix::MakeScale().

## ◆ TEST() [545/574]

impeller::testing::TEST | ( | ShadowPathGeometryTest | ,
|  | TwoColinearSegmentsTest |
| ) |  |

Definition at line 223 of file shadow_path_geometry_unittests.cc.

223 {
224 DlPathBuilder path_builder;
225 path_builder.MoveTo(DlPoint(100, 100));
226 path_builder.LineTo(DlPoint(200, 100));
227 path_builder.LineTo(DlPoint(300, 100));
228 const DlPath path = path_builder.TakePath();
229 const Matrix matrix;
230 const Scalar height = 10.0f;
231
232 Tessellator tessellator;
233 std::shared_ptr<ShadowVertices> shadow_vertices =
234 ShadowPathGeometry::MakeAmbientShadowVertices(tessellator, path, height,
235 matrix);
236
237 ASSERT_NE(shadow_vertices, nullptr);
238 EXPECT_TRUE(shadow_vertices->IsEmpty());
239 }

References impeller::ShadowPathGeometry::MakeAmbientShadowVertices().

## ◆ TEST() [546/574]

impeller::testing::TEST | ( | SizeTest | ,
|  | ISizeIsEmpty |
| ) |  |

Definition at line 36 of file size_unittests.cc.

36 {
37 // Non-empty
38 EXPECT_FALSE(ISize(10, 7).IsEmpty());
39
40 // Empty both width and height both 0 or negative, in all combinations
41 EXPECT_TRUE(ISize(0, 0).IsEmpty());
42 EXPECT_TRUE(ISize(-1, -1).IsEmpty());
43 EXPECT_TRUE(ISize(-1, 0).IsEmpty());
44 EXPECT_TRUE(ISize(0, -1).IsEmpty());
45
46 // Empty for 0 or negative width or height (but not both at the same time)
47 EXPECT_TRUE(ISize(10, 0).IsEmpty());
48 EXPECT_TRUE(ISize(10, -1).IsEmpty());
49 EXPECT_TRUE(ISize(0, 7).IsEmpty());
50 EXPECT_TRUE(ISize(-1, 7).IsEmpty());
51 }

## ◆ TEST() [547/574]

impeller::testing::TEST | ( | SizeTest | ,
|  | IsSquare |
| ) |  |

Definition at line 53 of file size_unittests.cc.

53 {
54 EXPECT_TRUE(Size(20, 20).IsSquare());
55 EXPECT_FALSE(Size(20, 19).IsSquare());
56 EXPECT_FALSE(Size(19, 20).IsSquare());
57
58 EXPECT_TRUE(ISize(20, 20).IsSquare());
59 EXPECT_FALSE(ISize(20, 19).IsSquare());
60 EXPECT_FALSE(ISize(19, 20).IsSquare());
61 }

## ◆ TEST() [548/574]

impeller::testing::TEST | ( | SizeTest | ,
|  | MaxDimension |
| ) |  |

Definition at line 63 of file size_unittests.cc.

63 {
64 EXPECT_EQ(Size(20, 20).MaxDimension(), 20);
65 EXPECT_EQ(Size(20, 19).MaxDimension(), 20);
66 EXPECT_EQ(Size(19, 20).MaxDimension(), 20);
67 EXPECT_EQ(Size(20, 21).MaxDimension(), 21);
68 EXPECT_EQ(Size(21, 20).MaxDimension(), 21);
69
70 EXPECT_EQ(ISize(20, 20).MaxDimension(), 20);
71 EXPECT_EQ(ISize(20, 19).MaxDimension(), 20);
72 EXPECT_EQ(ISize(19, 20).MaxDimension(), 20);
73 EXPECT_EQ(ISize(20, 21).MaxDimension(), 21);
74 EXPECT_EQ(ISize(21, 20).MaxDimension(), 21);
75 }

## ◆ TEST() [549/574]

impeller::testing::TEST | ( | SizeTest | ,
|  | NegationOperator |
| ) |  |

Definition at line 77 of file size_unittests.cc.

77 {
78 EXPECT_EQ(-Size(10, 20), Size(-10, -20));
79 EXPECT_EQ(-Size(-10, 20), Size(10, -20));
80 EXPECT_EQ(-Size(10, -20), Size(-10, 20));
81 EXPECT_EQ(-Size(-10, -20), Size(10, 20));
82 }

## ◆ TEST() [550/574]

impeller::testing::TEST | ( | SizeTest | ,
|  | SizeIsEmpty |
| ) |  |

Definition at line 12 of file size_unittests.cc.

12 {
13 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
14
15 // Non-empty
16 EXPECT_FALSE(Size(10.5, 7.2).IsEmpty());
17
18 // Empty both width and height both 0 or negative, in all combinations
19 EXPECT_TRUE(Size(0.0, 0.0).IsEmpty());
20 EXPECT_TRUE(Size(-1.0, -1.0).IsEmpty());
21 EXPECT_TRUE(Size(-1.0, 0.0).IsEmpty());
22 EXPECT_TRUE(Size(0.0, -1.0).IsEmpty());
23
24 // Empty for 0 or negative width or height (but not both at the same time)
25 EXPECT_TRUE(Size(10.5, 0.0).IsEmpty());
26 EXPECT_TRUE(Size(10.5, -1.0).IsEmpty());
27 EXPECT_TRUE(Size(0.0, 7.2).IsEmpty());
28 EXPECT_TRUE(Size(-1.0, 7.2).IsEmpty());
29
30 // Empty for NaN in width or height or both
31 EXPECT_TRUE(Size(10.5, nan).IsEmpty());
32 EXPECT_TRUE(Size(nan, 7.2).IsEmpty());
33 EXPECT_TRUE(Size(nan, nan).IsEmpty());
34 }

## ◆ TEST() [551/574]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | ToColor |
| ) |  |

Definition at line 46 of file skia_conversions_unittests.cc.

46 {
47 // Create a color with alpha, red, green, and blue values that are all
48 // trivially divisible by 255 so that we can test the conversion results in
49 // correct scalar values.
50 // AARRGGBB
51 const flutter::DlColor color = flutter::DlColor(0x8040C020);
52 auto converted_color = skia_conversions::ToColor(color);
53
54 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
55 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
56 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
57 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
58 }
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:13

References impeller::ScalarNearlyEqual(), and impeller::skia_conversions::ToColor().

## ◆ TEST() [552/574]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToSamplerDescriptor |
| ) |  |

Definition at line 17 of file skia_conversions_unittests.cc.

17 {
18 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
19 flutter::DlImageSampling::kNearestNeighbor)
20 .min_filter,
21 impeller::MinMagFilter::kNearest);
22 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
23 flutter::DlImageSampling::kNearestNeighbor)
24 .mip_filter,
25 impeller::MipFilter::kBase);
26
27 EXPECT_EQ(
28 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
29 .min_filter,
30 impeller::MinMagFilter::kLinear);
31 EXPECT_EQ(
32 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
33 .mip_filter,
34 impeller::MipFilter::kBase);
35
36 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
37 flutter::DlImageSampling::kMipmapLinear)
38 .min_filter,
39 impeller::MinMagFilter::kLinear);
40 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
41 flutter::DlImageSampling::kMipmapLinear)
42 .mip_filter,
43 impeller::MipFilter::kLinear);
44 }
impeller::MipFilter::kLinear
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
impeller::MipFilter::kBase
@ kBase
The texture is sampled as if it only had a single mipmap level.
impeller::ToSamplerDescriptor
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlFilterMode options)
Definition: dl_dispatcher.cc:122
impeller::MinMagFilter::kLinear
@ kLinear
impeller::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.

References impeller::kBase, impeller::kLinear, impeller::kNearest, and impeller::skia_conversions::ToSamplerDescriptor().

## ◆ TEST() [553/574]

impeller::testing::TEST | ( | SurfaceContextVK | ,
|  | TearsDownSwapchain |
| ) |  |

Definition at line 31 of file surface_context_vk_unittests.cc.

31 {
32 SetSwapchainImageSize({100, 100});
33 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
34
35 vk::UniqueSurfaceKHR surface = CreateSurface(*context);
36 SurfaceContextVK surface_context(context);
37
38 EXPECT_TRUE(surface_context.SetWindowSurface(std::move(surface), {100, 100}));
39 EXPECT_NE(surface_context.AcquireNextSurface(), nullptr);
40
41 surface_context.TeardownSwapchain();
42
43 EXPECT_EQ(surface_context.AcquireNextSurface(), nullptr);
44 }

References impeller::SurfaceContextVK::AcquireNextSurface(), impeller::SurfaceContextVK::SetWindowSurface(), and impeller::SurfaceContextVK::TeardownSwapchain().

## ◆ TEST() [554/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | CircleVertexCounts |
| ) |  |

Definition at line 154 of file tessellator_unittests.cc.

154 {
155 Tessellator tessellator;
156
157 auto test = [&tessellator](const Matrix& transform, Scalar radius) {
158 auto generator = tessellator.FilledCircle(transform, {}, radius);
159 size_t quadrant_divisions = generator.GetVertexCount() / 4;
160
161 // Confirm the approximation error is within the currently accepted
162 // |kCircleTolerance| value advertised by |CircleTessellator|.
163 // (With an additional 1% tolerance for floating point rounding.)
164 double angle = kPiOver2 / quadrant_divisions;
165 Point first = {radius, 0};
166 Point next = {static_cast<Scalar>(cos(angle) * radius),
167 static_cast<Scalar>(sin(angle) * radius)};
168 Point midpoint = (first + next) * 0.5;
169 EXPECT_GE(midpoint.GetLength(),
170 radius - Tessellator::kCircleTolerance * 1.01)
171 << ", transform = " << transform << ", radius = " << radius
172 << ", divisions = " << quadrant_divisions;
173 };
174
175 test({}, 0.0);
176 test({}, 0.9);
177 test({}, 1.0);
178 test({}, 1.9);
179 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
180 test({}, 2.0);
181 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
182 test({}, 11.9);
183 test({}, 12.0);
184 test({}, 35.9);
185 for (int i = 36; i < 10000; i += 4) {
186 test({}, i);
187 }
188 }

References impeller::Tessellator::FilledCircle(), impeller::TPoint< T >::GetLength(), impeller::Tessellator::EllipticalVertexGenerator::GetVertexCount(), impeller::Tessellator::kCircleTolerance, impeller::kPiOver2, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [555/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | EarlyReturnEmptyConvexShape |
| ) |  |

Definition at line 590 of file tessellator_unittests.cc.

590 {
591 // This path is not technically empty (it has a size in one dimension), but
592 // it contains only move commands and no actual path segment definitions.
593 flutter::DlPathBuilder builder;
594 builder.MoveTo({0, 0});
595 builder.MoveTo({10, 10});
596
597 std::vector<Point> points;
598 std::vector<uint16_t> indices;
599 Tessellator::TessellateConvexInternal(builder.TakePath(), points, indices,
600 3.0f);
601
602 EXPECT_TRUE(points.empty());
603 EXPECT_TRUE(indices.empty());
604 }

References points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [556/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledArcStripTessellationVertices |
| ) |  |

Definition at line 306 of file tessellator_unittests.cc.

306 {
307 Tessellator tessellator;
308
309 auto test = [&tessellator](const Matrix& transform, const Arc& arc) {
310 auto generator = tessellator.FilledArc(transform, arc,
311 /*supports_triangle_fans=*/false);
312 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
313
314 auto vertex_count = generator.GetVertexCount();
315 auto vertices = std::vector<Point>();
316 generator.GenerateVertices([&vertices](const Point& p) { //
317 vertices.push_back(p);
318 });
319 EXPECT_EQ(vertices.size(), vertex_count);
320
321 auto center = arc.GetOvalBounds().GetCenter();
322 auto radius = arc.GetOvalSize().width * 0.5;
323
324 // Test position of first point
325 EXPECT_POINT_NEAR(
326 vertices[0],
327 Point(center.x + cos(Radians(arc.GetStart()).radians) * radius,
328 center.y + sin(Radians(arc.GetStart()).radians) * radius));
329
330 // Test position of last point
331 auto last_angle = arc.GetStart() + arc.GetSweep();
332 EXPECT_POINT_NEAR(
333 vertices[vertex_count - 1],
334 Point(center.x + cos(Radians(last_angle).radians) * radius,
335 center.y + sin(Radians(last_angle).radians) * radius));
336
337 // Test odd-indexed points. These are all the origin.
338 Point origin = arc.IncludeCenter()
339 ? center
340 : (vertices[0] + vertices[vertex_count - 1]) * 0.5f;
341 for (size_t i = 1; i < vertex_count; i += 2) {
342 EXPECT_POINT_NEAR(vertices[i], origin);
343 }
344
345 // Test even-indexed points. These are points on the outer edge of the arc.
346 auto previous_outer_point = vertices[0];
347 auto outer_increment_distance = (vertices[4] - vertices[2]).GetLength();
348 for (size_t i = 2; i < vertex_count; i += 2) {
349 // Each is |radius| from the center.
350 EXPECT_NEAR((vertices[i] - center).GetLength(), radius, kEhCloseEnough);
351
352 // Each is within |outer_increment_distance| from the previous
353 if (i == 2 || i == vertex_count - 1) {
354 // The very first and last points may be closer than
355 // |outer_increment_distance| to their adjacent outer points
356 EXPECT_LE((vertices[i] - previous_outer_point).GetLength(),
357 outer_increment_distance + kEhCloseEnough);
358 } else {
359 // Other outer points are |outer_increment_distance| apart
360 EXPECT_NEAR((vertices[i] - previous_outer_point).GetLength(),
361 outer_increment_distance, kEhCloseEnough);
362 }
363
364 previous_outer_point = vertices[i];
365 }
366 };
367
368 test({}, Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(0), Degrees(90), false));
369 test({}, Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(0), Degrees(90), true));
370
371 test({},
372 Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(0), Degrees(-270), false));
373 test({},
374 Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(0), Degrees(-270), true));
375
376 test({},
377 Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(94), Degrees(322), false));
378 test({},
379 Arc(Rect::MakeXYWH(0, 0, 100, 100), Degrees(94), Degrees(322), true));
380 }

References EXPECT_POINT_NEAR, impeller::Tessellator::FilledArc(), impeller::kEhCloseEnough, impeller::kTriangleStrip, impeller::TRect< Scalar >::MakeXYWH(), impeller::Radians::radians, and transform.

## ◆ TEST() [557/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledCircleTessellationVertices |
| ) |  |

Definition at line 190 of file tessellator_unittests.cc.

190 {
191 Tessellator tessellator;
192
193 auto test = [&tessellator](const Matrix& transform, const Point& center,
194 Scalar radius) {
195 auto generator = tessellator.FilledCircle(transform, center, radius);
196 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
197
198 auto vertex_count = generator.GetVertexCount();
199 auto vertices = std::vector<Point>();
200 generator.GenerateVertices([&vertices](const Point& p) { //
201 vertices.push_back(p);
202 });
203 EXPECT_EQ(vertices.size(), vertex_count);
204 ASSERT_EQ(vertex_count % 4, 0u);
205
206 auto quadrant_count = vertex_count / 4;
207 for (size_t i = 0; i < quadrant_count; i++) {
208 double angle = kPiOver2 * i / (quadrant_count - 1);
209 double degrees = angle * 180.0 / kPi;
210 double rsin = sin(angle) * radius;
211 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
212 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
213 EXPECT_POINT_NEAR(vertices[i * 2],
214 Point(center.x - rcos, center.y + rsin))
215 << "vertex " << i << ", angle = " << degrees << std::endl;
216 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
217 Point(center.x - rcos, center.y - rsin))
218 << "vertex " << i << ", angle = " << degrees << std::endl;
219 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
220 Point(center.x + rcos, center.y - rsin))
221 << "vertex " << i << ", angle = " << degrees << std::endl;
222 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
223 Point(center.x + rcos, center.y + rsin))
224 << "vertex " << i << ", angle = " << degrees << std::endl;
225 }
226 };
227
228 test({}, {}, 2.0);
229 test({}, {10, 10}, 2.0);
230 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0);
231 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0);
232 }

References EXPECT_POINT_NEAR, impeller::Tessellator::FilledCircle(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [558/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledEllipseTessellationVertices |
| ) |  |

Definition at line 455 of file tessellator_unittests.cc.

455 {
456 Tessellator tessellator;
457
458 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
459 auto center = bounds.GetCenter();
460 auto half_size = bounds.GetSize() * 0.5f;
461
462 auto generator = tessellator.FilledEllipse(transform, bounds);
463 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
464
465 auto vertex_count = generator.GetVertexCount();
466 auto vertices = std::vector<Point>();
467 generator.GenerateVertices([&vertices](const Point& p) { //
468 vertices.push_back(p);
469 });
470 EXPECT_EQ(vertices.size(), vertex_count);
471 ASSERT_EQ(vertex_count % 4, 0u);
472
473 auto quadrant_count = vertex_count / 4;
474 for (size_t i = 0; i < quadrant_count; i++) {
475 double angle = kPiOver2 * i / (quadrant_count - 1);
476 double degrees = angle * 180.0 / kPi;
477 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
478 double rcos =
479 (i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
480 double rsin = sin(angle) * half_size.height;
481 EXPECT_POINT_NEAR(vertices[i * 2],
482 Point(center.x - rcos, center.y + rsin))
483 << "vertex " << i << ", angle = " << degrees << ", " //
484 << "bounds = " << bounds << std::endl;
485 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
486 Point(center.x - rcos, center.y - rsin))
487 << "vertex " << i << ", angle = " << degrees << ", " //
488 << "bounds = " << bounds << std::endl;
489 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
490 Point(center.x + rcos, center.y - rsin))
491 << "vertex " << i << ", angle = " << degrees << ", " //
492 << "bounds = " << bounds << std::endl;
493 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
494 Point(center.x + rcos, center.y + rsin))
495 << "vertex " << i << ", angle = " << degrees << ", " //
496 << "bounds = " << bounds << std::endl;
497 }
498 };
499
500 // Square bounds should actually use the circle generator, but its
501 // results should match the same math as the ellipse generator.
502 test({}, Rect::MakeXYWH(0, 0, 2, 2));
503
504 test({}, Rect::MakeXYWH(0, 0, 2, 3));
505 test({}, Rect::MakeXYWH(0, 0, 3, 2));
506 test({}, Rect::MakeXYWH(5, 10, 2, 3));
507 test({}, Rect::MakeXYWH(16, 7, 3, 2));
508 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
509 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
510 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
511 Rect::MakeXYWH(5000, 10000, 3000, 2000));
512 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
513 Rect::MakeXYWH(5000, 10000, 2000, 3000));
514 }

References EXPECT_POINT_NEAR, impeller::Tessellator::FilledEllipse(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [559/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledRoundRectTessellationVertices |
| ) |  |

Definition at line 516 of file tessellator_unittests.cc.

516 {
517 Tessellator tessellator;
518
519 auto test = [&tessellator](const Matrix& transform, const Rect& bounds,
520 const Size& radii) {
521 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
522 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
523
524 Scalar middle_left = bounds.GetX() + radii.width;
525 Scalar middle_top = bounds.GetY() + radii.height;
526 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
527 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
528
529 auto generator = tessellator.FilledRoundRect(transform, bounds, radii);
530 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
531
532 auto vertex_count = generator.GetVertexCount();
533 auto vertices = std::vector<Point>();
534 generator.GenerateVertices([&vertices](const Point& p) { //
535 vertices.push_back(p);
536 });
537 EXPECT_EQ(vertices.size(), vertex_count);
538 ASSERT_EQ(vertex_count % 4, 0u);
539
540 auto quadrant_count = vertex_count / 4;
541 for (size_t i = 0; i < quadrant_count; i++) {
542 double angle = kPiOver2 * i / (quadrant_count - 1);
543 double degrees = angle * 180.0 / kPi;
544 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
545 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
546 double rsin = sin(angle) * radii.height;
547 EXPECT_POINT_NEAR(vertices[i * 2],
548 Point(middle_left - rcos, middle_bottom + rsin))
549 << "vertex " << i << ", angle = " << degrees << ", " //
550 << "bounds = " << bounds << std::endl;
551 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
552 Point(middle_left - rcos, middle_top - rsin))
553 << "vertex " << i << ", angle = " << degrees << ", " //
554 << "bounds = " << bounds << std::endl;
555 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
556 Point(middle_right + rcos, middle_top - rsin))
557 << "vertex " << i << ", angle = " << degrees << ", " //
558 << "bounds = " << bounds << std::endl;
559 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
560 Point(middle_right + rcos, middle_bottom + rsin))
561 << "vertex " << i << ", angle = " << degrees << ", " //
562 << "bounds = " << bounds << std::endl;
563 }
564 };
565
566 // Both radii spanning the bounds should actually use the circle/ellipse
567 // generator, but their results should match the same math as the round
568 // rect generator.
569 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 10});
570
571 // One radius spanning the bounds, but not the other will not match the
572 // round rect math if the generator transfers to circle/ellipse
573 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 5});
574 test({}, Rect::MakeXYWH(0, 0, 20, 20), {5, 10});
575
576 test({}, Rect::MakeXYWH(0, 0, 20, 30), {2, 2});
577 test({}, Rect::MakeXYWH(0, 0, 30, 20), {2, 2});
578 test({}, Rect::MakeXYWH(5, 10, 20, 30), {2, 3});
579 test({}, Rect::MakeXYWH(16, 7, 30, 20), {2, 3});
580 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 30, 20),
581 {2, 3});
582 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 20, 30),
583 {2, 3});
584 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
585 Rect::MakeXYWH(5000, 10000, 3000, 2000), {50, 70});
586 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
587 Rect::MakeXYWH(5000, 10000, 2000, 3000), {50, 70});
588 }

References EXPECT_POINT_NEAR, impeller::Tessellator::FilledRoundRect(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [560/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | RoundCapLineTessellationVertices |
| ) |  |

Definition at line 382 of file tessellator_unittests.cc.

382 {
383 Tessellator tessellator;
384
385 auto test = [&tessellator](const Matrix& transform, const Point& p0,
386 const Point& p1, Scalar radius) {
387 auto generator = tessellator.RoundCapLine(transform, p0, p1, radius);
388 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
389
390 auto vertex_count = generator.GetVertexCount();
391 auto vertices = std::vector<Point>();
392 generator.GenerateVertices([&vertices](const Point& p) { //
393 vertices.push_back(p);
394 });
395 EXPECT_EQ(vertices.size(), vertex_count);
396 ASSERT_EQ(vertex_count % 4, 0u);
397
398 Point along = p1 - p0;
399 Scalar length = along.GetLength();
400 if (length > 0) {
401 along *= radius / length;
402 } else {
403 along = {radius, 0};
404 }
405 Point across = {-along.y, along.x};
406
407 auto quadrant_count = vertex_count / 4;
408 for (size_t i = 0; i < quadrant_count; i++) {
409 double angle = kPiOver2 * i / (quadrant_count - 1);
410 double degrees = angle * 180.0 / kPi;
411 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
412 Point relative_along =
413 along * ((i == quadrant_count - 1) ? 0.0f : cos(angle));
414 Point relative_across = across * sin(angle);
415 EXPECT_POINT_NEAR(vertices[i * 2], //
416 p0 - relative_along + relative_across)
417 << "vertex " << i << ", angle = " << degrees << ", " //
418 << "line = " << p0 << " => " << p1 << ", " //
419 << "radius = " << radius << std::endl;
420 EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
421 p0 - relative_along - relative_across)
422 << "vertex " << i << ", angle = " << degrees << ", " //
423 << "line = " << p0 << " => " << p1 << ", " //
424 << "radius = " << radius << std::endl;
425 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
426 p1 + relative_along - relative_across)
427 << "vertex " << i << ", angle = " << degrees << ", " //
428 << "line = " << p0 << " => " << p1 << ", " //
429 << "radius = " << radius << std::endl;
430 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
431 p1 + relative_along + relative_across)
432 << "vertex " << i << ", angle = " << degrees << ", " //
433 << "line = " << p0 << " => " << p1 << ", " //
434 << "radius = " << radius << std::endl;
435 }
436 };
437
438 // Empty line should actually use the circle generator, but its
439 // results should match the same math as the round cap generator.
440 test({}, {0, 0}, {0, 0}, 10);
441
442 test({}, {0, 0}, {10, 0}, 2);
443 test({}, {10, 0}, {0, 0}, 2);
444 test({}, {0, 0}, {10, 10}, 2);
445
446 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
447 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
448 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
449
450 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
451 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
452 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
453 }
impeller::TPoint::y
Type y
Definition: point.h:32

References EXPECT_POINT_NEAR, impeller::TPoint< T >::GetLength(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), p1, impeller::Tessellator::RoundCapLine(), transform, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [561/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | StrokedCircleTessellationVertices |
| ) |  |

Definition at line 234 of file tessellator_unittests.cc.

234 {
235 Tessellator tessellator;
236
237 auto test = [&tessellator](const Matrix& transform, const Point& center,
238 Scalar radius, Scalar half_width) {
239 ASSERT_GT(radius, half_width);
240 auto generator =
241 tessellator.StrokedCircle(transform, center, radius, half_width);
242 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
243
244 auto vertex_count = generator.GetVertexCount();
245 auto vertices = std::vector<Point>();
246 generator.GenerateVertices([&vertices](const Point& p) { //
247 vertices.push_back(p);
248 });
249 EXPECT_EQ(vertices.size(), vertex_count);
250 ASSERT_EQ(vertex_count % 4, 0u);
251
252 auto quadrant_count = vertex_count / 8;
253
254 // Test outer points first
255 for (size_t i = 0; i < quadrant_count; i++) {
256 double angle = kPiOver2 * i / (quadrant_count - 1);
257 double degrees = angle * 180.0 / kPi;
258 double rsin = sin(angle) * (radius + half_width);
259 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
260 double rcos =
261 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
262 EXPECT_POINT_NEAR(vertices[i * 2],
263 Point(center.x - rcos, center.y - rsin))
264 << "vertex " << i << ", angle = " << degrees << std::endl;
265 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2],
266 Point(center.x + rsin, center.y - rcos))
267 << "vertex " << i << ", angle = " << degrees << std::endl;
268 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2],
269 Point(center.x + rcos, center.y + rsin))
270 << "vertex " << i << ", angle = " << degrees << std::endl;
271 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2],
272 Point(center.x - rsin, center.y + rcos))
273 << "vertex " << i << ", angle = " << degrees << std::endl;
274 }
275
276 // Then test innerer points
277 for (size_t i = 0; i < quadrant_count; i++) {
278 double angle = kPiOver2 * i / (quadrant_count - 1);
279 double degrees = angle * 180.0 / kPi;
280 double rsin = sin(angle) * (radius - half_width);
281 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
282 double rcos =
283 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
284 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
285 Point(center.x - rcos, center.y - rsin))
286 << "vertex " << i << ", angle = " << degrees << std::endl;
287 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2 + 1],
288 Point(center.x + rsin, center.y - rcos))
289 << "vertex " << i << ", angle = " << degrees << std::endl;
290 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2 + 1],
291 Point(center.x + rcos, center.y + rsin))
292 << "vertex " << i << ", angle = " << degrees << std::endl;
293 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2 + 1],
294 Point(center.x - rsin, center.y + rcos))
295 << "vertex " << i << ", angle = " << degrees << std::endl;
296 }
297 };
298
299 test({}, {}, 2.0, 1.0);
300 test({}, {}, 2.0, 0.5);
301 test({}, {10, 10}, 2.0, 1.0);
302 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0, 1.0);
303 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0, 10.0);
304 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::Tessellator::StrokedCircle(), and transform.

## ◆ TEST() [562/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellateConvex |
| ) |  |

Definition at line 97 of file tessellator_unittests.cc.

97 {
98 {
99 std::vector<Point> points;
100 std::vector<uint16_t> indices;
101 // Sanity check simple rectangle.
102 Tessellator::TessellateConvexInternal(
103 flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 10, 10)), points,
104 indices, 1.0);
105
106 // Note: the origin point is repeated but not referenced in the indices
107 // below
108 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
109 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
110 EXPECT_EQ(points, expected);
111 EXPECT_EQ(indices, expected_indices);
112 }
113
114 {
115 std::vector<Point> points;
116 std::vector<uint16_t> indices;
117 Tessellator::TessellateConvexInternal(
118 flutter::DlPath(flutter::DlPathBuilder{}
119 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
120 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
121 .TakePath()),
122 points, indices, 1.0);
123
124 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
125 {0, 0}, {20, 20}, {30, 20}, {30, 30},
126 {20, 30}, {20, 20}};
127 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
128 EXPECT_EQ(points, expected);
129 EXPECT_EQ(indices, expected_indices);
130 }
131 }

References impeller::TRect< Scalar >::MakeLTRB(), points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [563/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellateConvexUnclosedPath |
| ) |  |

Definition at line 134 of file tessellator_unittests.cc.

134 {
135 std::vector<Point> points;
136 std::vector<uint16_t> indices;
137
138 // Create a rectangle that lacks an explicit close.
139 flutter::DlPath path = flutter::DlPathBuilder{}
140 .LineTo({100, 0})
141 .LineTo({100, 100})
142 .LineTo({0, 100})
143 .TakePath();
144 Tessellator::TessellateConvexInternal(flutter::DlPath(path), points, indices,
145 1.0);
146
147 std::vector<Point> expected = {
148 {0, 0}, {100, 0}, {100, 100}, {0, 100}, {0, 0}};
149 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
150 EXPECT_EQ(points, expected);
151 EXPECT_EQ(indices, expected_indices);
152 }

References impeller::LineTo(), points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [564/574]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellatorBuilderReturnsCorrectResultStatus |
| ) |  |

Definition at line 17 of file tessellator_unittests.cc.

17 {
18 // Zero points.
19 {
20 TessellatorLibtess t;
21 auto path = flutter::DlPathBuilder{} //
22 .SetFillType(FillType::kOdd)
23 .TakePath();
24 TessellatorLibtess::Result result = t.Tessellate(
25 path, 1.0f,
26 [](const float* vertices, size_t vertices_count,
27 const uint16_t* indices, size_t indices_count) { return true; });
28
29 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
30 }
31
32 // One point.
33 {
34 TessellatorLibtess t;
35 auto path = flutter::DlPathBuilder{}
36 .LineTo({0, 0})
37 .SetFillType(FillType::kOdd)
38 .TakePath();
39 TessellatorLibtess::Result result = t.Tessellate(
40 path, 1.0f,
41 [](const float* vertices, size_t vertices_count,
42 const uint16_t* indices, size_t indices_count) { return true; });
43
44 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
45 }
46
47 // Two points.
48 {
49 TessellatorLibtess t;
50 auto path = flutter::DlPathBuilder{}
51 .MoveTo({0, 0})
52 .LineTo({0, 1})
53 .SetFillType(FillType::kOdd)
54 .TakePath();
55 TessellatorLibtess::Result result = t.Tessellate(
56 path, 1.0f,
57 [](const float* vertices, size_t vertices_count,
58 const uint16_t* indices, size_t indices_count) { return true; });
59
60 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
61 }
62
63 // Many points.
64 {
65 TessellatorLibtess t;
66 flutter::DlPathBuilder builder;
67 for (int i = 0; i < 1000; i++) {
68 auto coord = i * 1.0f;
69 builder.MoveTo({coord, coord}).LineTo({coord + 1, coord + 1});
70 }
71 auto path = builder.SetFillType(FillType::kOdd).TakePath();
72 TessellatorLibtess::Result result = t.Tessellate(
73 path, 1.0f,
74 [](const float* vertices, size_t vertices_count,
75 const uint16_t* indices, size_t indices_count) { return true; });
76
77 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
78 }
79
80 // Closure fails.
81 {
82 TessellatorLibtess t;
83 auto path = flutter::DlPathBuilder{}
84 .MoveTo({0, 0})
85 .LineTo({0, 1})
86 .SetFillType(FillType::kOdd)
87 .TakePath();
88 TessellatorLibtess::Result result = t.Tessellate(
89 path, 1.0f,
90 [](const float* vertices, size_t vertices_count,
91 const uint16_t* indices, size_t indices_count) { return false; });
92
93 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
94 }
95 }

References impeller::TessellatorLibtess::kInputError, impeller::kOdd, impeller::TessellatorLibtess::kSuccess, impeller::LineTo(), and impeller::TessellatorLibtess::Tessellate().

## ◆ TEST() [565/574]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutex |
| ) |  |

Definition at line 36 of file base_unittests.cc.

36 {
37 Foo f = {};
38
39 // f.a = 100; <--- Static analysis error.
40 f.mtx.Lock();
41 f.a = 100;
42 f.mtx.Unlock();
43 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [566/574]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutexLock |
| ) |  |

Definition at line 45 of file base_unittests.cc.

45 {
46 Foo f = {};
47
48 // f.a = 100; <--- Static analysis error.
49 auto a = Lock(f.mtx);
50 f.a = 100;
51 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [567/574]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutex |
| ) |  |

Definition at line 53 of file base_unittests.cc.

53 {
54 RWFoo f = {};
55
56 // f.a = 100; <--- Static analysis error.
57 f.mtx.LockWriter();
58 f.a = 100;
59 f.mtx.UnlockWriter();
60 // int b = f.a; <--- Static analysis error.
61 f.mtx.LockReader();
62 [[maybe_unused]] int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
63 f.mtx.UnlockReader();
64 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [568/574]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutexLock |
| ) |  |

Definition at line 66 of file base_unittests.cc.

66 {
67 RWFoo f = {};
68
69 // f.a = 100; <--- Static analysis error.
70 {
71 auto write_lock = WriterLock{f.mtx};
72 f.a = 100;
73 }
74
75 // int b = f.a; <--- Static analysis error.
76 {
77 auto read_lock = ReaderLock(f.mtx);
78 [[maybe_unused]] int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
79 }
80
81 // f.mtx.UnlockReader(); <--- Static analysis error.
82 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [569/574]

impeller::testing::TEST | ( | TrigTest | ,
|  | MultiplyByScalarRadius |
| ) |  |

Definition at line 65 of file trig_unittests.cc.

65 {
66 for (int i = 0; i <= 360; i++) {
67 for (int i = 1; i <= 10; i++) {
68 Scalar radius = i * 5.0f;
69 EXPECT_EQ(Trig(Degrees(i)) * radius,
70 Point(radius * std::cos(i * kPi / 180),
71 radius * std::sin(i * kPi / 180)))
72 << "at " << i << " degrees and radius " << radius;
73 }
74 }
75 }

References impeller::kPi.

## ◆ TEST() [570/574]

impeller::testing::TEST | ( | TrigTest | ,
|  | TrigAngles |
| ) |  |

Definition at line 15 of file trig_unittests.cc.

15 {
16 {
17 Trig trig(Degrees(0.0));
18 EXPECT_EQ(trig.cos, 1.0);
19 EXPECT_EQ(trig.sin, 0.0);
20 }
21
22 {
23 Trig trig(Radians(0.0));
24 EXPECT_EQ(trig.cos, 1.0);
25 EXPECT_EQ(trig.sin, 0.0);
26 }
27
28 {
29 Trig trig(Degrees(30.0));
30 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
31 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
32 }
33
34 {
35 Trig trig(Radians(kPi / 6.0));
36 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
37 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
38 }
39
40 {
41 Trig trig(Degrees(60.0));
42 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
43 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
44 }
45
46 {
47 Trig trig(Radians(kPi / 3.0));
48 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
49 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
50 }
51
52 {
53 Trig trig(Degrees(90.0));
54 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
55 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
56 }
57
58 {
59 Trig trig(Radians(kPi / 2.0));
60 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
61 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
62 }
63 }

References impeller::Trig::cos, impeller::kEhCloseEnough, impeller::kPi, and impeller::Trig::sin.

## ◆ TEST() [571/574]

impeller::testing::TEST | ( | TypographerTest | ,
|  | RectanglePackerFillsRows |
| ) |  |

Definition at line 413 of file typographer_unittests.cc.

413 {
414 auto skyline = RectanglePacker::Factory(257, 256);
415
416 // Fill up the first row.
417 IPoint16 loc;
418 for (auto i = 0u; i < 16; i++) {
419 skyline->AddRect(16, 16, &loc);
420 }
421 // Last rectangle still in first row.
422 EXPECT_EQ(loc.x(), 256 - 16);
423 EXPECT_EQ(loc.y(), 0);
424
425 // Fill up second row.
426 for (auto i = 0u; i < 16; i++) {
427 skyline->AddRect(16, 16, &loc);
428 }
429
430 EXPECT_EQ(loc.x(), 256 - 16);
431 EXPECT_EQ(loc.y(), 16);
432 }

References impeller::RectanglePacker::Factory(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST() [572/574]

impeller::testing::TEST | ( | UniqueHandleGLES | ,
|  | MakeUntracked |
| ) |  |

Definition at line 26 of file unique_handle_gles_unittests.cc.

26 {
27 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
28
29 EXPECT_CALL(*mock_gles_impl, GenTextures(1, _)).Times(1);
30
31 std::shared_ptr<MockGLES> mock_gled =
32 MockGLES::Init(std::move(mock_gles_impl));
33 ProcTableGLES::Resolver resolver = kMockResolverGLES;
34 auto proc_table = std::make_unique<ProcTableGLES>(resolver);
35 auto worker = std::make_shared<TestWorker>();
36 auto reactor = std::make_shared<ReactorGLES>(std::move(proc_table));
37 reactor->AddWorker(worker);
38
39 UniqueHandleGLES handle =
40 UniqueHandleGLES::MakeUntracked(reactor, HandleType::kTexture);
41 EXPECT_FALSE(handle.Get().IsDead());
42 }

References impeller::UniqueHandleGLES::Get(), impeller::HandleGLES::IsDead(), impeller::kTexture, and impeller::UniqueHandleGLES::MakeUntracked().

## ◆ TEST() [573/574]

impeller::testing::TEST | ( | WangsFormulaTest | ,
|  | Cubic |
| ) |  |

Definition at line 12 of file wangs_formula_unittests.cc.

12 {
13 Point p0{300, 0};
14 Point p1{0, 0};
15 Point p2{0, 0};
16 Point p3{0, 300};
17 Scalar result = ComputeCubicSubdivisions(1.0, p0, p1, p2, p3);
18 EXPECT_FLOAT_EQ(result, 30.f);
19 }
impeller::ComputeCubicSubdivisions
Scalar ComputeCubicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Point p3)
Definition: wangs_formula.cc:18

References impeller::ComputeCubicSubdivisions(), p1, and p2.

## ◆ TEST() [574/574]

impeller::testing::TEST | ( | WangsFormulaTest | ,
|  | Quadratic |
| ) |  |

Definition at line 21 of file wangs_formula_unittests.cc.

21 {
22 Point p0{15, 0};
23 Point p1{0, 0};
24 Point p2{0, 20};
25 Scalar result = ComputeQuadradicSubdivisions(1.0, p0, p1, p2);
26 EXPECT_FLOAT_EQ(result, 5.f);
27 }
impeller::ComputeQuadradicSubdivisions
Scalar ComputeQuadradicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2)
Definition: wangs_formula.cc:31

References impeller::ComputeQuadradicSubdivisions(), p1, and p2.

## ◆ TEST_F()

impeller::testing::TEST_F | ( | GoldenTests | ,
|  | ConicalGradient |
| ) |  |

Definition at line 80 of file golden_tests.cc.

80 {
81 flutter::DisplayListBuilder builder;
82 flutter::DlPaint paint;
83 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
84
85 flutter::DlColor colors[2] = {flutter::DlColor::RGBA(1, 0, 0, 1),
86 flutter::DlColor::RGBA(0, 0, 1, 1)};
87 Scalar stops[2] = {0, 1};
88
89 paint.setColorSource(flutter::DlColorSource::MakeConical(
90 /*start_center=*/{125, 125}, //
91 /*start_radius=*/125, {180, 180}, //
92 /*end_radius=*/0, //
93 /*stop_count=*/2, //
94 /*colors=*/colors, //
95 /*stops=*/stops, //
96 /*tile_mode=*/flutter::DlTileMode::kClamp //
97 ));
98
99 builder.DrawRect(DlRect::MakeXYWH(10, 10, 250, 250), paint);
100
101 auto aiks_context =
102 AiksContext(Screenshotter().GetPlayground().GetContext(), nullptr);
103 auto screenshot = Screenshotter().MakeScreenshot(
104 aiks_context,
105 DisplayListToTexture(builder.Build(), {240, 240}, aiks_context));
106 ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
107 }
impeller::DisplayListToTexture
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1220

References impeller::DisplayListToTexture(), and impeller::testing::Screenshotter::MakeScreenshot().

## ◆ TEST_P() [1/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | AdvancedBlendColorFilterWithDestinationOpacity |
| ) |  |

Definition at line 907 of file aiks_dl_blend_unittests.cc.

907 {
908 DisplayListBuilder builder;
909
910 builder.DrawPaint(DlPaint(DlColor::kWhite()));
911
912 DlPaint save_paint;
913 save_paint.setOpacity(0.3);
914 save_paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kTransparent(),
915 DlBlendMode::kSaturation));
916 builder.SaveLayer(std::nullopt, &save_paint);
917 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300),
918 DlPaint(DlColor::kMaroon()));
919 builder.DrawRect(DlRect::MakeXYWH(200, 200, 300, 300),
920 DlPaint(DlColor::kBlue()));
921 builder.Restore();
922
923 // Should be solid red as the destructive color filter floods the clip.
924 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
925 }

## ◆ TEST_P() [2/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ArcWithZeroSweepAndBlur |
| ) |  |

Definition at line 839 of file aiks_dl_path_unittests.cc.

839 {
840 DisplayListBuilder builder;
841 builder.Scale(GetContentScale().x, GetContentScale().y);
842
843 DlPaint paint;
844 paint.setColor(DlColor::kRed());
845
846 std::vector<DlColor> colors = {DlColor::RGBA(1.0, 0.0, 0.0, 1.0),
847 DlColor::RGBA(0.0, 0.0, 0.0, 1.0)};
848 std::vector<Scalar> stops = {0.0, 1.0};
849
850 paint.setColorSource(
851 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
852 stops.data(), DlTileMode::kMirror));
853 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
854
855 DlPathBuilder path_builder;
856 path_builder.AddArc(DlRect::MakeXYWH(10, 10, 100, 100), //
857 DlDegrees(0), DlDegrees(0));
858 builder.DrawPath(path_builder.TakePath(), paint);
859
860 // Check that this empty picture can be created without crashing.
861 builder.Build();
862 }

References x.

## ◆ TEST_P() [3/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownBackdropId |
| ) |  |

Definition at line 177 of file canvas_unittests.cc.

177 {
178 ContentContext context(GetContext(), nullptr);
179 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
180 GTEST_SKIP() << "Test requires device with framebuffer fetch";
181 }
182 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
183 /*requires_readback=*/true);
184 // 3 backdrop filters all with same id.
185 std::unordered_map<int64_t, BackdropData> data;
186 data[1] = BackdropData{.backdrop_count = 3};
187 canvas->SetBackdropData(data, 3);
188
189 auto blur =
190 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
191
192 EXPECT_TRUE(canvas->RequiresReadback());
193 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
194 {.color = Color::Azure()});
195 canvas->SaveLayer({}, std::nullopt, blur.get(),
196 ContentBoundsPromise::kContainsContents,
197 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
198 /*backdrop_id=*/1);
199 canvas->Restore();
200 EXPECT_FALSE(canvas->RequiresReadback());
201
202 canvas->SaveLayer({}, std::nullopt, blur.get(),
203 ContentBoundsPromise::kContainsContents,
204 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
205 /*backdrop_id=*/1);
206 canvas->Restore();
207 EXPECT_FALSE(canvas->RequiresReadback());
208
209 canvas->SaveLayer({}, std::nullopt, blur.get(),
210 ContentBoundsPromise::kContainsContents,
211 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
212 /*backdrop_id=*/1);
213 canvas->Restore();
214 EXPECT_FALSE(canvas->RequiresReadback());
215 }
impeller::testing::CreateTestCanvas
std::unique_ptr< Canvas > CreateTestCanvas(ContentContext &context, std::optional< Rect > cull_rect=std::nullopt, bool requires_readback=false)
Definition: canvas_unittests.cc:27

References impeller::Color::Azure(), impeller::BackdropData::backdrop_count, CreateTestCanvas(), data, impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [4/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownBackdropIdMixed |
| ) |  |

Definition at line 217 of file canvas_unittests.cc.

217 {
218 ContentContext context(GetContext(), nullptr);
219 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
220 GTEST_SKIP() << "Test requires device with framebuffer fetch";
221 }
222 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
223 /*requires_readback=*/true);
224 // 3 backdrop filters, 2 with same id.
225 std::unordered_map<int64_t, BackdropData> data;
226 data[1] = BackdropData{.backdrop_count = 2};
227 canvas->SetBackdropData(data, 3);
228
229 auto blur =
230 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
231
232 EXPECT_TRUE(canvas->RequiresReadback());
233 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
234 {.color = Color::Azure()});
235 canvas->SaveLayer({}, std::nullopt, blur.get(),
236 ContentBoundsPromise::kContainsContents, 1, false);
237 canvas->Restore();
238 EXPECT_TRUE(canvas->RequiresReadback());
239
240 canvas->SaveLayer({}, std::nullopt, blur.get(),
241 ContentBoundsPromise::kContainsContents, 1, false, 1);
242 canvas->Restore();
243 EXPECT_FALSE(canvas->RequiresReadback());
244
245 canvas->SaveLayer({}, std::nullopt, blur.get(),
246 ContentBoundsPromise::kContainsContents, 1, false, 1);
247 canvas->Restore();
248 EXPECT_FALSE(canvas->RequiresReadback());
249 }

References impeller::Color::Azure(), impeller::BackdropData::backdrop_count, CreateTestCanvas(), data, impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [5/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownNormal |
| ) |  |

Definition at line 142 of file canvas_unittests.cc.

142 {
143 ContentContext context(GetContext(), nullptr);
144 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
145 GTEST_SKIP() << "Test requires device with framebuffer fetch";
146 }
147 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
148 /*requires_readback=*/true);
149 // 3 backdrop filters
150 canvas->SetBackdropData({}, 3);
151
152 auto blur =
153 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
154 flutter::DlRect rect = flutter::DlRect::MakeLTRB(0, 0, 50, 50);
155
156 EXPECT_TRUE(canvas->RequiresReadback());
157 canvas->DrawRect(rect, {.color = Color::Azure()});
158 canvas->SaveLayer({}, rect, blur.get(),
159 ContentBoundsPromise::kContainsContents,
160 /*total_content_depth=*/1);
161 canvas->Restore();
162 EXPECT_TRUE(canvas->RequiresReadback());
163
164 canvas->SaveLayer({}, rect, blur.get(),
165 ContentBoundsPromise::kContainsContents,
166 /*total_content_depth=*/1);
167 canvas->Restore();
168 EXPECT_TRUE(canvas->RequiresReadback());
169
170 canvas->SaveLayer({}, rect, blur.get(),
171 ContentBoundsPromise::kContainsContents,
172 /*total_content_depth=*/1);
173 canvas->Restore();
174 EXPECT_FALSE(canvas->RequiresReadback());
175 }
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25

References impeller::Color::Azure(), CreateTestCanvas(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [6/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownWithNestedSaveLayers |
| ) |  |

Definition at line 254 of file canvas_unittests.cc.

254 {
255 ContentContext context(GetContext(), nullptr);
256 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
257 GTEST_SKIP() << "Test requires device with framebuffer fetch";
258 }
259 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
260 /*requires_readback=*/true);
261
262 canvas->SetBackdropData({}, 2);
263
264 auto blur =
265 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
266
267 EXPECT_TRUE(canvas->RequiresReadback());
268 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
269 {.color = Color::Azure()});
270 canvas->SaveLayer({}, std::nullopt, blur.get(),
271 ContentBoundsPromise::kContainsContents,
272 /*total_content_depth=*/3);
273
274 // This filter is nested in the first saveLayer. We cannot restore to onscreen
275 // here.
276 canvas->SaveLayer({}, std::nullopt, blur.get(),
277 ContentBoundsPromise::kContainsContents,
278 /*total_content_depth=*/1);
279 canvas->Restore();
280 EXPECT_TRUE(canvas->RequiresReadback());
281
282 canvas->Restore();
283 EXPECT_TRUE(canvas->RequiresReadback());
284 }

References impeller::Color::Azure(), CreateTestCanvas(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [7/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropFilterOverUnclosedClip |
| ) |  |

Definition at line 2307 of file aiks_dl_basic_unittests.cc.

2307 {
2308 DisplayListBuilder builder;
2309
2310 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
2311 builder.Save();
2312 {
2313 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
2314
2315 builder.Save();
2316 {
2317 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
2318 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
2319 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
2320 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
2321 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
2322 }
2323 builder.Restore();
2324
2325 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
2326 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
2327 }
2328 builder.Restore();
2329 builder.DrawCircle(DlPoint(100, 100), 100,
2330 DlPaint().setColor(DlColor::kAqua()));
2331
2332 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2333 }

## ◆ TEST_P() [8/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropRestoreUsesCorrectCoverageForFirstRestoredClip |
| ) |  |

Definition at line 902 of file aiks_dl_unittests.cc.

902 {
903 DisplayListBuilder builder;
904
905 DlPaint paint;
906 // Add a difference clip that cuts out the bottom right corner
907 builder.ClipRect(DlRect::MakeLTRB(50, 50, 100, 100), DlClipOp::kDifference);
908
909 // Draw a red rectangle that's going to be completely covered by green later.
910 paint.setColor(DlColor::kRed());
911 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
912
913 // Add a clip restricting the backdrop filter to the top right corner.
914 auto count = builder.GetSaveCount();
915 builder.Save();
916 {
917 builder.ClipRect(DlRect::MakeLTRB(0, 0, 100, 100));
918 {
919 // Create a save layer with a backdrop blur filter.
920 auto backdrop_filter =
921 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal);
922 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter.get());
923 }
924 }
925 builder.RestoreToCount(count);
926
927 // Finally, overwrite all the previous stuff with green.
928 paint.setColor(DlColor::kGreen());
929 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
930
931 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
932 }

## ◆ TEST_P() [9/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlendModePlusAlphaColorFilterWideGamut |
| ) |  |

Definition at line 432 of file aiks_dl_blend_unittests.cc.

432 {
433 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
434 PixelFormat::kB10G10R10A10XR);
435 auto texture = CreateTextureForFixture("airplane.jpg",
436 /*enable_mipmapping=*/true);
437
438 DisplayListBuilder builder;
439 builder.Scale(GetContentScale().x, GetContentScale().y);
440
441 DlPaint paint;
442 paint.setColor(DlColor::RGBA(0.1, 0.2, 0.1, 1.0));
443 builder.DrawPaint(paint);
444
445 DlPaint save_paint;
446 save_paint.setColorFilter(
447 DlColorFilter::MakeBlend(DlColor::RGBA(1, 0, 0, 1), DlBlendMode::kPlus));
448 builder.SaveLayer(std::nullopt, &save_paint);
449
450 paint.setColor(DlColor::kRed());
451 builder.DrawRect(DlRect::MakeXYWH(100, 100, 400, 400), paint);
452
453 paint.setColor(DlColor::kWhite());
454
455 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
456 builder.DrawImageRect(
457 DlImageImpeller::Make(texture),
458 DlRect::MakeWH(texture->GetSize().width, texture->GetSize().height),
459 DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), //
460 rect.GetRight(), rect.GetBottom()),
461 DlImageSampling::kMipmapLinear, &paint);
462 builder.Restore();
463
464 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
465 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [10/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlendModePlusAlphaWideGamut |
| ) |  |

Definition at line 400 of file aiks_dl_blend_unittests.cc.

400 {
401 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
402 PixelFormat::kB10G10R10A10XR);
403 auto texture = CreateTextureForFixture("airplane.jpg",
404 /*enable_mipmapping=*/true);
405
406 DisplayListBuilder builder;
407 DlPaint paint;
408 builder.Scale(GetContentScale().x, GetContentScale().y);
409
410 paint.setColor(DlColor::RGBA(0.9, 1, 0.9, 1.0));
411 builder.DrawPaint(paint);
412 builder.SaveLayer(std::nullopt);
413
414 paint.setBlendMode(DlBlendMode::kPlus);
415 paint.setColor(DlColor::kRed());
416
417 builder.DrawRect(DlRect::MakeXYWH(100, 100, 400, 400), paint);
418 paint.setColor(DlColor::kWhite());
419
420 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
421 builder.DrawImageRect(
422 DlImageImpeller::Make(texture),
423 DlRect::MakeWH(texture->GetSize().width, texture->GetSize().height),
424 DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), //
425 rect.GetRight(), rect.GetBottom()),
426 DlImageSampling::kMipmapLinear, &paint);
427 builder.Restore();
428 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
429 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [11/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlendModeShouldCoverWholeScreen |
| ) |  |

Definition at line 82 of file aiks_dl_blend_unittests.cc.

82 {
83 DisplayListBuilder builder;
84 DlPaint paint;
85
86 paint.setColor(DlColor::kRed());
87 builder.DrawPaint(paint);
88
89 paint.setBlendMode(DlBlendMode::kSrcOver);
90 builder.SaveLayer(std::nullopt, &paint);
91
92 paint.setColor(DlColor::kWhite());
93 builder.DrawRect(DlRect::MakeXYWH(100, 100, 400, 400), paint);
94
95 paint.setBlendMode(DlBlendMode::kSrc);
96 builder.SaveLayer(std::nullopt, &paint);
97
98 paint.setColor(DlColor::kBlue());
99 builder.DrawRect(DlRect::MakeXYWH(200, 200, 200, 200), paint);
100
101 builder.Restore();
102 builder.Restore();
103
104 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
105 }

## ◆ TEST_P() [12/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurGradientWithOpacity |
| ) |  |

Definition at line 1436 of file aiks_dl_blur_unittests.cc.

1436 {
1437 DisplayListBuilder builder;
1438 builder.Scale(GetContentScale().x, GetContentScale().y);
1439
1440 std::vector<DlColor> colors = {DlColor(0xFFFF0000), DlColor(0xFF00FF00)};
1441 std::vector<Scalar> stops = {0.0, 1.0};
1442
1443 auto gradient = DlColorSource::MakeLinear(
1444 {0, 0}, {400, 400}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
1445
1446 DlPaint save_paint;
1447 save_paint.setOpacity(0.5);
1448 builder.SaveLayer(std::nullopt, &save_paint);
1449
1450 DlPaint paint;
1451 paint.setColorSource(gradient);
1452 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1453 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
1454
1455 builder.Restore();
1456
1457 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1458 }

References x.

## ◆ TEST_P() [13/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurHasNoEdge |
| ) |  |

Definition at line 531 of file aiks_dl_blur_unittests.cc.

531 {
532 Scalar sigma = 47.6;
533 auto callback = [&]() -> sk_sp<DisplayList> {
534 if (AiksTest::ImGuiBegin("Controls", nullptr,
535 ImGuiWindowFlags_AlwaysAutoResize)) {
536 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
537 ImGui::End();
538 }
539 DisplayListBuilder builder;
540 builder.Scale(GetContentScale().x, GetContentScale().y);
541 builder.DrawPaint({});
542
543 DlPaint paint;
544 paint.setColor(DlColor::kGreen());
545 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
546
547 builder.DrawRect(DlRect::MakeXYWH(300, 300, 200, 200), paint);
548 return builder.Build();
549 };
550
551 ASSERT_TRUE(OpenPlaygroundHere(callback));
552 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [14/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurredCircleWithStrokeWidth |
| ) |  |

Definition at line 1083 of file aiks_dl_path_unittests.cc.

1083 {
1084 DisplayListBuilder builder;
1085 DlPaint paint;
1086 paint.setColor(DlColor::kGreen());
1087 paint.setDrawStyle(DlDrawStyle::kStroke);
1088 paint.setStrokeWidth(30);
1089 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5));
1090
1091 builder.DrawCircle(DlPoint(200, 200), 100, paint);
1092
1093 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1094 }

## ◆ TEST_P() [15/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurredRectangleWithShader |
| ) |  |

Definition at line 1289 of file aiks_dl_blur_unittests.cc.

1289 {
1290 DisplayListBuilder builder;
1291 builder.Scale(GetContentScale().x, GetContentScale().y);
1292
1293 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1294 auto draw_line = [&builder, &paint](DlPoint a, DlPoint b) {
1295 DlPath line = DlPath::MakeLine(a, b);
1296 builder.DrawPath(line, paint);
1297 };
1298 paint.setStrokeWidth(5);
1299 paint.setDrawStyle(DlDrawStyle::kStroke);
1300 draw_line(DlPoint(dx + 100, dy + 100), DlPoint(dx + 200, dy + 200));
1301 draw_line(DlPoint(dx + 100, dy + 200), DlPoint(dx + 200, dy + 100));
1302 draw_line(DlPoint(dx + 150, dy + 100), DlPoint(dx + 200, dy + 150));
1303 draw_line(DlPoint(dx + 100, dy + 150), DlPoint(dx + 150, dy + 200));
1304 };
1305
1306 AiksContext renderer(GetContext(), nullptr);
1307 DisplayListBuilder recorder_builder;
1308 for (int x = 0; x < 5; ++x) {
1309 for (int y = 0; y < 5; ++y) {
1310 DlRect rect = DlRect::MakeXYWH(x * 20, y * 20, 20, 20);
1311 DlPaint paint;
1312 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1313 : DlColor::kBlue());
1314
1315 recorder_builder.DrawRect(rect, paint);
1316 }
1317 }
1318 auto texture =
1319 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1320
1321 auto image_source = DlColorSource::MakeImage(
1322 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1323 auto blur_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kDecal);
1324
1325 DlPaint paint;
1326 paint.setColor(DlColor::kDarkGreen());
1327 builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 600), paint);
1328
1329 paint.setColorSource(image_source);
1330 builder.DrawRect(DlRect::MakeLTRB(100, 100, 200, 200), paint);
1331
1332 paint.setColorSource(nullptr);
1333 paint.setColor(DlColor::kRed());
1334 builder.DrawRect(DlRect::MakeLTRB(300, 0, 600, 600), paint);
1335
1336 paint.setColorSource(image_source);
1337 paint.setImageFilter(blur_filter);
1338 builder.DrawRect(DlRect::MakeLTRB(400, 100, 500, 200), paint);
1339
1340 paint.setImageFilter(nullptr);
1341 paint_lines(0, 300, paint);
1342
1343 paint.setImageFilter(blur_filter);
1344 paint_lines(300, 300, paint);
1345
1346 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1347 }

References impeller::saturated::b, impeller::DisplayListToTexture(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [16/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanConvertTriangleFanToTriangles |
| ) |  |

Definition at line 159 of file aiks_dl_vertices_unittests.cc.

159 {
160 constexpr Scalar hexagon_radius = 125;
161 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
162 auto center_to_flat = 1.73 / 2 * hexagon_radius;
163
164 // clang-format off
165 std::vector<DlPoint> vertices = {
166 DlPoint(hex_start.x, hex_start.y),
167 DlPoint(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
168 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
169 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
170 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
171 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
172 DlPoint(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
173 DlPoint(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
174 DlPoint(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
175 };
176 // clang-format on
177 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
178 auto dl_vertices = flutter::DlVertices::Make(
179 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
180 nullptr, nullptr);
181 flutter::DisplayListBuilder builder;
182 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
183 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
184 }

## ◆ TEST_P() [17/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 428 of file aiks_dl_path_unittests.cc.

428 {
429 DisplayListBuilder builder;
430
431 // Starting at (50, 50), draw lines from:
432 // 1. (50, height)
433 // 2. (width, height)
434 // 3. (width, 50)
435 DlPathBuilder path_builder;
436 path_builder.MoveTo(DlPoint(50, 50));
437 path_builder.LineTo(DlPoint(50, 100));
438 path_builder.LineTo(DlPoint(100, 100));
439 path_builder.LineTo(DlPoint(100, 50));
440
441 DlPaint paint;
442 paint.setColor(DlColor::kRed());
443 paint.setDrawStyle(DlDrawStyle::kStroke);
444 paint.setStrokeWidth(10);
445
446 builder.DrawPath(path_builder.TakePath(), paint);
447
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449 }

## ◆ TEST_P() [18/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawAnOpenPathThatIsntARect |
| ) |  |

Definition at line 451 of file aiks_dl_path_unittests.cc.

451 {
452 DisplayListBuilder builder;
453
454 // Draw a stroked path that is explicitly closed to verify
455 // It doesn't become a rectangle.
456 DlPathBuilder path_builder;
457 path_builder.MoveTo(DlPoint(50, 50));
458 path_builder.LineTo(DlPoint(520, 120));
459 path_builder.LineTo(DlPoint(300, 310));
460 path_builder.LineTo(DlPoint(100, 50));
461 path_builder.Close();
462
463 DlPaint paint;
464 paint.setColor(DlColor::kRed());
465 paint.setDrawStyle(DlDrawStyle::kStroke);
466 paint.setStrokeWidth(10);
467
468 builder.DrawPath(path_builder.TakePath(), paint);
469
470 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
471 }

## ◆ TEST_P() [19/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawMultiContourConvexPath |
| ) |  |

Definition at line 811 of file aiks_dl_path_unittests.cc.

811 {
812 DlPathBuilder path_builder;
813 for (auto i = 0; i < 10; i++) {
814 if (i % 2 == 0) {
815 // We use the factory method to convert the circle to a path so that it
816 // uses the legacy conics for legacy golden output.
817 DlPath circle =
818 DlPath::MakeCircle(DlPoint(100 + 50 * i, 100 + 50 * i), 100);
819 path_builder.AddPath(circle);
820 path_builder.Close();
821 } else {
822 path_builder.MoveTo(DlPoint(100.f + 50.f * i - 100, 100.f + 50.f * i));
823 path_builder.LineTo(DlPoint(100.f + 50.f * i, 100.f + 50.f * i - 100));
824 path_builder.LineTo(DlPoint(100.f + 50.f * i - 100, //
825 100.f + 50.f * i - 100));
826 path_builder.Close();
827 }
828 }
829 DlPath path = path_builder.TakePath();
830
831 DisplayListBuilder builder;
832 DlPaint paint;
833 paint.setColor(DlColor::kRed().withAlpha(102));
834 builder.DrawPath(path, paint);
835
836 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }

## ◆ TEST_P() [20/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaint |
| ) |  |

Definition at line 470 of file aiks_dl_basic_unittests.cc.

470 {
471 auto medium_turquoise =
472 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
473
474 DisplayListBuilder builder;
475 builder.Scale(0.2, 0.2);
476 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
477 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
478 }

## ◆ TEST_P() [21/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintMultipleTimes |
| ) |  |

Definition at line 480 of file aiks_dl_basic_unittests.cc.

480 {
481 auto medium_turquoise =
482 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
483 auto orange_red =
484 DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
485
486 DisplayListBuilder builder;
487 builder.Scale(0.2, 0.2);
488 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
489 builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
490 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
491 }

## ◆ TEST_P() [22/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintMultipleTimesInteractive |
| ) |  |

Definition at line 682 of file aiks_dl_blend_unittests.cc.

682 {
683 auto modes = GetBlendModeSelection();
684
685 auto callback = [&]() -> sk_sp<DisplayList> {
686 static Color background = Color::MediumTurquoise();
687 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
688 static int current_blend_index = 3;
689
690 if (AiksTest::ImGuiBegin("Controls", nullptr,
691 ImGuiWindowFlags_AlwaysAutoResize)) {
692 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
693 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
694 ImGui::ListBox("Blend mode", &current_blend_index,
695 modes.blend_mode_names.data(),
696 modes.blend_mode_names.size());
697 ImGui::End();
698 }
699
700 DisplayListBuilder builder;
701 builder.Scale(0.2, 0.2);
702 DlPaint paint;
703 paint.setColor(DlColor(background.ToARGB()));
704 builder.DrawPaint(paint);
705
706 paint.setColor(DlColor(foreground.ToARGB()));
707 paint.setBlendMode(static_cast<DlBlendMode>(current_blend_index));
708 builder.DrawPaint(paint);
709 return builder.Build();
710 };
711 ASSERT_TRUE(OpenPlaygroundHere(callback));
712 }
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_dl_blend_unittests.cc:44

References GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::Color::MediumTurquoise(), impeller::Color::ToARGB(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [23/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintWithAdvancedBlend |
| ) |  |

Definition at line 107 of file aiks_dl_blend_unittests.cc.

107 {
108 DisplayListBuilder builder;
109
110 builder.Scale(0.2, 0.2);
111 DlPaint paint;
112 paint.setColor(DlColor::RGBA(
113 Color::MediumTurquoise().red, Color::MediumTurquoise().green,
114 Color::MediumTurquoise().blue, Color::MediumTurquoise().alpha));
115 builder.DrawPaint(paint);
116
117 paint.setColor(DlColor::RGBA(Color::OrangeRed().red, Color::OrangeRed().green,
118 Color::OrangeRed().blue, 0.5));
119 paint.setBlendMode(DlBlendMode::kHue);
120 builder.DrawPaint(paint);
121
122 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
123 }

References impeller::Color::MediumTurquoise(), and impeller::Color::OrangeRed().

## ◆ TEST_P() [24/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPerspectiveTransformWithClips |
| ) |  |

Definition at line 1534 of file aiks_dl_basic_unittests.cc.

1534 {
1535 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
1536 int time = 0;
1537 auto callback = [&]() -> sk_sp<DisplayList> {
1538 DisplayListBuilder builder;
1539
1540 builder.Save();
1541 {
1542 builder.Translate(300, 300);
1543
1544 // 1. Draw/restore a clip before drawing the image, which will get drawn
1545 // to the depth buffer behind the image.
1546 builder.Save();
1547 {
1548 DlPaint paint;
1549 paint.setColor(DlColor::kGreen());
1550 builder.DrawPaint(paint);
1551 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
1552 DlClipOp::kDifference);
1553
1554 paint.setColor(DlColor::kBlack());
1555 builder.DrawPaint(paint);
1556 }
1557 builder.Restore(); // Restore rectangle difference clip.
1558
1559 builder.Save();
1560 {
1561 // 2. Draw an oval clip that applies to the image, which will get drawn
1562 // in front of the image on the depth buffer.
1563 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
1564
1565 Matrix result =
1566 Matrix(1.0, 0.0, 0.0, 0.0, //
1567 0.0, 1.0, 0.0, 0.0, //
1568 0.0, 0.0, 1.0, 0.003, //
1569 0.0, 0.0, 0.0, 1.0) *
1570 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
1571
1572 // 3. Draw the rotating image with a perspective transform.
1573 builder.Transform(result);
1574
1575 auto image =
1576 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1577 auto position =
1578 -DlPoint(image->GetSize().width, image->GetSize().height) * 0.5;
1579 builder.DrawImage(image, position, {});
1580 }
1581 builder.Restore(); // Restore oval intersect clip.
1582
1583 // 4. Draw a semi-translucent blue circle atop all previous draws.
1584 DlPaint paint;
1585 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
1586 builder.DrawCircle(DlPoint(), 230, paint);
1587 }
1588 builder.Restore(); // Restore translation.
1589
1590 return builder.Build();
1591 };
1592 ASSERT_TRUE(OpenPlaygroundHere(callback));
1593 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::Transform().

## ◆ TEST_P() [25/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 405 of file aiks_dl_unittests.cc.

405 {
406 std::vector<DlPoint> points = {
407 {0, 0}, //
408 {100, 100}, //
409 {100, 0}, //
410 {0, 100}, //
411 {0, 0}, //
412 {48, 48}, //
413 {52, 52}, //
414 };
415 DlPaint paint_round;
416 paint_round.setColor(DlColor::kYellow().withAlpha(128));
417 paint_round.setStrokeCap(DlStrokeCap::kRound);
418 paint_round.setStrokeWidth(20);
419
420 DlPaint paint_square;
421 paint_square.setColor(DlColor::kYellow().withAlpha(128));
422 paint_square.setStrokeCap(DlStrokeCap::kSquare);
423 paint_square.setStrokeWidth(20);
424
425 DlPaint background;
426 background.setColor(DlColor::kBlack());
427
428 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
429 builder.DrawPaint(background);
430 builder.Translate(200, 200);
431
432 builder.DrawPoints(DlPointMode::kPoints, points.size(), points.data(),
433 paint_round);
434 builder.Translate(150, 0);
435 builder.DrawPoints(DlPointMode::kPoints, points.size(), points.data(),
436 paint_square);
437
438 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
439 }

References points.

## ◆ TEST_P() [26/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPointsWithTextureMap |
| ) |  |

Definition at line 441 of file aiks_dl_unittests.cc.

441 {
442 auto texture = DlImageImpeller::Make(
443 CreateTextureForFixture("table_mountain_nx.png",
444 /*enable_mipmapping=*/true));
445
446 std::vector<DlPoint> points = {
447 {0, 0}, //
448 {100, 100}, //
449 {100, 0}, //
450 {0, 100}, //
451 {0, 0}, //
452 {48, 48}, //
453 {52, 52}, //
454 };
455
456 auto image_src =
457 DlColorSource::MakeImage(texture, DlTileMode::kClamp, DlTileMode::kClamp);
458
459 DlPaint paint_round;
460 paint_round.setStrokeCap(DlStrokeCap::kRound);
461 paint_round.setColorSource(image_src);
462 paint_round.setStrokeWidth(200);
463
464 DlPaint paint_square;
465 paint_square.setStrokeCap(DlStrokeCap::kSquare);
466 paint_square.setColorSource(image_src);
467 paint_square.setStrokeWidth(200);
468
469 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
470 builder.Translate(200, 200);
471
472 builder.DrawPoints(DlPointMode::kPoints, points.size(), points.data(),
473 paint_round);
474 builder.Translate(150, 0);
475 builder.DrawPoints(DlPointMode::kPoints, points.size(), points.data(),
476 paint_square);
477
478 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
479 }

References impeller::DlImageImpeller::Make(), and points.

## ◆ TEST_P() [27/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawScaledPointsLargeScaleSmallRadius |
| ) |  |

Definition at line 840 of file aiks_dl_unittests.cc.

840 {
841 std::vector<DlPoint> point = {
842 {0, 0}, //
843 };
844
845 DlPaint paint;
846 paint.setStrokeCap(DlStrokeCap::kRound);
847 paint.setColor(DlColor::kRed());
848 paint.setStrokeWidth(100 * 0.000001);
849
850 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
851 builder.Translate(200, 200);
852 builder.Scale(1000000, 1000000);
853
854 builder.DrawPoints(DlPointMode::kPoints, point.size(), point.data(), paint);
855 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
856 }

## ◆ TEST_P() [28/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawScaledPointsSmallScaleLargeRadius |
| ) |  |

Definition at line 820 of file aiks_dl_unittests.cc.

820 {
821 std::vector<DlPoint> point = {
822 {0, 0}, //
823 };
824
825 DlPaint paint;
826 paint.setStrokeCap(DlStrokeCap::kRound);
827 paint.setColor(DlColor::kRed());
828 paint.setStrokeWidth(100 * 1000000);
829
830 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
831 builder.Translate(200, 200);
832 builder.Scale(0.000001, 0.000001);
833
834 builder.DrawPoints(DlPointMode::kPoints, point.size(), point.data(), paint);
835
836 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }

## ◆ TEST_P() [29/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanEmptyPictureConvertToImage |
| ) |  |

Definition at line 961 of file aiks_dl_unittests.cc.

961 {
962 DisplayListBuilder recorder_builder;
963
964 DisplayListBuilder builder;
965 AiksContext renderer(GetContext(), nullptr);
966
967 DlPaint paint;
968 paint.setColor(DlColor::kTransparent());
969 builder.DrawPaint(paint);
970
971 auto result_image =
972 DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer);
973 if (result_image) {
974 recorder_builder.DrawImage(DlImageImpeller::Make(result_image), DlPoint(),
975 {});
976
977 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
978 recorder_builder.DrawRect(DlRect::MakeWH(1000, 1000), paint);
979 }
980
981 ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build()));
982 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [30/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformFullScreenMSAA |
| ) |  |

Definition at line 1875 of file aiks_dl_basic_unittests.cc.

1875 {
1876 DisplayListBuilder builder;
1877
1878 DlPaint paint;
1879 paint.setColor(DlColor::kRed());
1880 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1881
1882 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1883 }

## ◆ TEST_P() [31/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBounds |
| ) |  |

Definition at line 1896 of file aiks_dl_basic_unittests.cc.

1896 {
1897 DisplayListBuilder builder;
1898
1899 DlPaint save;
1900 save.setColor(DlColor::kBlack());
1901
1902 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1903 builder.SaveLayer(save_bounds, &save);
1904
1905 DlPaint paint;
1906 paint.setColor(DlColor::kRed());
1907 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1908 paint.setColor(DlColor::kGreen());
1909 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1910 paint.setColor(DlColor::kBlue());
1911 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1912
1913 builder.Restore();
1914
1915 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1916 }

## ◆ TEST_P() [32/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated |
| ) |  |

Definition at line 1797 of file aiks_dl_basic_unittests.cc.

1798 {
1799 DisplayListBuilder builder;
1800
1801 DlPaint red;
1802 red.setColor(DlColor::kRed());
1803
1804 DlPaint green;
1805 green.setColor(DlColor::kGreen());
1806
1807 DlPaint blue;
1808 blue.setColor(DlColor::kBlue());
1809
1810 DlPaint save;
1811 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1812
1813 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1814 builder.SaveLayer(huge_bounds, &save);
1815
1816 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1817 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1818 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1819
1820 builder.Restore();
1821
1822 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1823 }

## ◆ TEST_P() [33/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSkew |
| ) |  |

Definition at line 1885 of file aiks_dl_basic_unittests.cc.

1885 {
1886 DisplayListBuilder builder;
1887
1888 DlPaint red;
1889 red.setColor(DlColor::kRed());
1890 builder.Skew(2, 5);
1891 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1892
1893 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1894 }

## ◆ TEST_P() [34/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPictureConvertToImage |
| ) |  |

Definition at line 934 of file aiks_dl_unittests.cc.

934 {
935 DisplayListBuilder recorder_canvas;
936 DlPaint paint;
937 paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0));
938 recorder_canvas.DrawRect(DlRect::MakeXYWH(100.0, 100.0, 600, 600), paint);
939 paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0));
940 recorder_canvas.DrawRect(DlRect::MakeXYWH(200.0, 200.0, 600, 600), paint);
941
942 DisplayListBuilder canvas;
943 AiksContext renderer(GetContext(), nullptr);
944 paint.setColor(DlColor::kTransparent());
945 canvas.DrawPaint(paint);
946
947 auto image =
948 DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer);
949 if (image) {
950 canvas.DrawImage(DlImageImpeller::Make(image), DlPoint(), {});
951 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2));
952 canvas.DrawRect(DlRect::MakeWH(1000, 1000), paint);
953 }
954
955 ASSERT_TRUE(OpenPlaygroundHere(canvas.Build()));
956 }

References impeller::DisplayListToTexture(), and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [35/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderAdvancedBlendColorFilterWithSaveLayer |
| ) |  |

Definition at line 61 of file aiks_dl_blend_unittests.cc.

61 {
62 DisplayListBuilder builder;
63
64 DlRect layer_rect = DlRect::MakeXYWH(0, 0, 500, 500);
65 builder.ClipRect(layer_rect);
66
67 DlPaint save_paint;
68 save_paint.setColorFilter(DlColorFilter::MakeBlend(
69 DlColor::RGBA(0, 1, 0, 0.5), DlBlendMode::kDifference));
70 builder.SaveLayer(layer_rect, &save_paint);
71
72 DlPaint paint;
73 paint.setColor(DlColor::kBlack());
74 builder.DrawPaint(paint);
75 paint.setColor(DlColor::kWhite());
76 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300), paint);
77 builder.Restore();
78
79 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
80 }

## ◆ TEST_P() [36/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlur |
| ) |  |

Definition at line 242 of file aiks_dl_blur_unittests.cc.

242 {
243 DisplayListBuilder builder;
244
245 DlPaint paint;
246 paint.setColor(DlColor::kCornflowerBlue());
247 builder.DrawCircle(DlPoint(100, 100), 50, paint);
248
249 paint.setColor(DlColor::kGreenYellow());
250 builder.DrawCircle(DlPoint(300, 200), 100, paint);
251
252 paint.setColor(DlColor::kDarkMagenta());
253 builder.DrawCircle(DlPoint(140, 170), 75, paint);
254
255 paint.setColor(DlColor::kOrangeRed());
256 builder.DrawCircle(DlPoint(180, 120), 100, paint);
257
258 DlRoundRect rrect =
259 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(75, 50, 375, 275), 20, 20);
260 builder.ClipRoundRect(rrect);
261
262 DlPaint save_paint;
263 save_paint.setBlendMode(DlBlendMode::kSrc);
264 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
265 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
266 builder.Restore();
267
268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
269 }

## ◆ TEST_P() [37/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurHugeSigma |
| ) |  |

Definition at line 352 of file aiks_dl_blur_unittests.cc.

352 {
353 DisplayListBuilder builder;
354
355 DlPaint paint;
356 paint.setColor(DlColor::kGreen());
357 builder.DrawCircle(DlPoint(400, 400), 300, paint);
358
359 DlPaint save_paint;
360 save_paint.setBlendMode(DlBlendMode::kSrc);
361
362 auto backdrop_filter =
363 DlImageFilter::MakeBlur(999999, 999999, DlTileMode::kClamp);
364 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
365 builder.Restore();
366
367 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
368 }

## ◆ TEST_P() [38/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurInteractive |
| ) |  |

Definition at line 205 of file aiks_dl_blur_unittests.cc.

205 {
206 auto callback = [&]() -> sk_sp<DisplayList> {
207 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
208 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
209 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
210
211 DisplayListBuilder builder;
212 DlPaint paint;
213 paint.setColor(DlColor::kCornflowerBlue());
214 builder.DrawCircle(DlPoint(100, 100), 50, paint);
215
216 paint.setColor(DlColor::kGreenYellow());
217 builder.DrawCircle(DlPoint(300, 200), 100, paint);
218
219 paint.setColor(DlColor::kDarkMagenta());
220 builder.DrawCircle(DlPoint(140, 170), 75, paint);
221
222 paint.setColor(DlColor::kOrangeRed());
223 builder.DrawCircle(DlPoint(180, 120), 100, paint);
224
225 DlRoundRect rrect =
226 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(a.x, a.y, b.x, b.y), 20, 20);
227 builder.ClipRoundRect(rrect);
228
229 DlPaint save_paint;
230 save_paint.setBlendMode(DlBlendMode::kSrc);
231
232 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
233 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
234 builder.Restore();
235
236 return builder.Build();
237 };
238
239 ASSERT_TRUE(OpenPlaygroundHere(callback));
240 }
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:51

References impeller::saturated::b, impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [39/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurWithSingleBackdropId |
| ) |  |

Definition at line 271 of file aiks_dl_blur_unittests.cc.

271 {
272 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
273
274 DisplayListBuilder builder;
275
276 DlPaint paint;
277 builder.DrawImage(image, DlPoint(50.0, 50.0),
278 DlImageSampling::kNearestNeighbor, &paint);
279
280 DlRoundRect rrect =
281 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(50, 250, 100, 100), 20, 20);
282 builder.Save();
283 builder.ClipRoundRect(rrect);
284
285 DlPaint save_paint;
286 save_paint.setBlendMode(DlBlendMode::kSrc);
287 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
288 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
289 /*backdrop_id=*/1);
290 builder.Restore();
291 builder.Restore();
292
293 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
294 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [40/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBoundedBlur |
| ) |  |

Definition at line 370 of file aiks_dl_blur_unittests.cc.

370 {
371 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
372
373 DisplayListBuilder builder;
374
375 DlPaint paint;
376 builder.DrawImage(image, DlPoint(0.0, 0.0), DlImageSampling::kNearestNeighbor,
377 &paint);
378
379 DlPaint save_paint;
380 save_paint.setBlendMode(DlBlendMode::kSrcOver);
381 builder.Save();
382
383 // Subcase 1: The 1st branch of downsampling, where the coverage hint is
384 // non-null but was ignored during snapshotting.
385
386 builder.Scale(1.1, 1.2);
387 builder.Rotate(10);
388 DlRect rect1 = DlRect::MakeLTRB(70, 70, 313, 170);
389 builder.ClipRect(rect1);
390 auto backdrop_filter1 =
391 DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal, /*bounds=*/rect1);
392 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter1.get());
393 builder.Restore();
394 builder.Restore();
395
396 // Subcase 2: The 2nd branch of downsampling, where the coverage hint is null
397 // or was already used during snapshotting.
398
399 builder.Scale(1.1, 1.2);
400 builder.Rotate(10);
401 DlRect rect2 = DlRect::MakeLTRB(55, 190, 298, 290);
402 builder.ClipRect(rect2);
403 auto backdrop_filter2 =
404 DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal, /*bounds=*/rect2);
405 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter2.get());
406 builder.Restore();
407 builder.Restore();
408
409 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
410 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [41/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedBackdropFilter |
| ) |  |

Definition at line 1495 of file aiks_dl_basic_unittests.cc.

1495 {
1496 DisplayListBuilder builder;
1497
1498 builder.Scale(GetContentScale().x, GetContentScale().y);
1499
1500 // Draw something interesting in the background.
1501 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1502 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
1503 std::vector<Scalar> stops = {
1504 0.0,
1505 1.0,
1506 };
1507 DlPaint paint;
1508 paint.setColorSource(DlColorSource::MakeLinear(
1509 /*start_point=*/DlPoint(0, 0), //
1510 /*end_point=*/DlPoint(100, 100), //
1511 /*stop_count=*/2, //
1512 /*colors=*/colors.data(), //
1513 /*stops=*/stops.data(), //
1514 /*tile_mode=*/DlTileMode::kRepeat //
1515 ));
1516
1517 builder.DrawPaint(paint);
1518
1519 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
1520 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
1521
1522 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
1523 // the same.
1524 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
1525
1526 DlPaint save_paint;
1527 auto backdrop_filter = DlImageFilter::MakeColorFilter(
1528 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
1529 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
1530
1531 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1532 }

References x.

## ◆ TEST_P() [42/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedBlur |
| ) |  |

Definition at line 412 of file aiks_dl_blur_unittests.cc.

412 {
413 DisplayListBuilder builder;
414 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
415
416 DlPaint paint;
417 paint.setColor(DlColor::kGreen());
418 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
419 builder.DrawCircle(DlPoint(400, 400), 200, paint);
420 builder.Restore();
421
422 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
423 }

## ◆ TEST_P() [43/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedLayers |
| ) |  |

Definition at line 2130 of file aiks_dl_basic_unittests.cc.

2130 {
2131 DisplayListBuilder builder;
2132
2133 DlPaint paint;
2134 paint.setColor(DlColor::kWhite());
2135 builder.DrawPaint(paint);
2136
2137 // Draw a green circle on the screen.
2138 {
2139 // Increase the clip depth for the savelayer to contend with.
2140 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
2141 builder.ClipPath(path);
2142
2143 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
2144 DlPaint save_paint;
2145 builder.SaveLayer(bounds, &save_paint);
2146
2147 // Fill the layer with white.
2148 paint.setColor(DlColor::kWhite());
2149 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
2150 // Fill the layer with green, but do so with a color blend that can't be
2151 // collapsed into the parent pass.
2152 paint.setColor(DlColor::kGreen());
2153 paint.setBlendMode(DlBlendMode::kHardLight);
2154 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
2155 }
2156
2157 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2158 }

## ◆ TEST_P() [44/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedRuntimeEffects |
| ) |  |

Definition at line 52 of file aiks_dl_runtime_effect_unittests.cc.

52 {
53 struct FragUniforms {
54 Vector2 iResolution;
55 Scalar iTime;
56 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
57 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
58 uniform_data->resize(sizeof(FragUniforms));
59 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
60
61 DlPaint paint;
62 auto effect =
63 MakeRuntimeEffect(this, "runtime_stage_example.frag.iplr", uniform_data);
64 ABSL_ASSERT_OK(effect);
65 paint.setColorSource(effect.value());
66
67 DisplayListBuilder builder;
68 builder.Save();
69 builder.ClipRoundRect(
70 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 400, 400), 10.0, 10.0),
71 DlClipOp::kIntersect);
72 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
73 builder.Restore();
74
75 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
76 }

## ◆ TEST_P() [45/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClips |
| ) |  |

Definition at line 864 of file aiks_dl_path_unittests.cc.

864 {
865 DisplayListBuilder builder;
866 DlPaint paint;
867 paint.setColor(DlColor::kFuchsia());
868
869 builder.ClipPath(DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 500, 500)));
870 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
871
872 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
873 }

## ◆ TEST_P() [46/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderColoredRect |
| ) |  |

Definition at line 30 of file aiks_dl_basic_unittests.cc.

30 {
31 DisplayListBuilder builder;
32 DlPaint paint;
33 paint.setColor(DlColor::kBlue());
34 builder.DrawPath(DlPath::MakeRectXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
35 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
36 }

## ◆ TEST_P() [47/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderColorFilterWithInvertColors |
| ) |  |

Definition at line 131 of file aiks_dl_basic_unittests.cc.

131 {
132 DisplayListBuilder builder;
133 DlPaint paint;
134 paint.setColor(DlColor::kRed());
135 paint.setColorFilter(
136 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
137 paint.setInvertColors(true);
138
139 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
140 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
141 }

## ◆ TEST_P() [48/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderColorFilterWithInvertColorsDrawPaint |
| ) |  |

Definition at line 143 of file aiks_dl_basic_unittests.cc.

143 {
144 DisplayListBuilder builder;
145 DlPaint paint;
146 paint.setColor(DlColor::kRed());
147 paint.setColorFilter(
148 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
149 paint.setInvertColors(true);
150
151 builder.DrawPaint(paint);
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153 }

## ◆ TEST_P() [49/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradient |
| ) |  |

Definition at line 655 of file aiks_dl_gradient_unittests.cc.

655 {
656 Scalar size = 256;
657 DisplayListBuilder builder;
658 DlPaint paint;
659 paint.setColor(DlColor::kWhite());
660 builder.DrawRect(DlRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
661 std::vector<DlColor> colors = {
662 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
663 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
664 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
665 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
666 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
667 std::array<std::tuple<DlPoint, float, DlPoint, float>, 8> array{
668 std::make_tuple(DlPoint(size / 2.f, size / 2.f), 0.f,
669 DlPoint(size / 2.f, size / 2.f), size / 2.f),
670 std::make_tuple(DlPoint(size / 2.f, size / 2.f), size / 4.f,
671 DlPoint(size / 2.f, size / 2.f), size / 2.f),
672 std::make_tuple(DlPoint(size / 4.f, size / 4.f), 0.f,
673 DlPoint(size / 2.f, size / 2.f), size / 2.f),
674 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 2.f,
675 DlPoint(size / 2.f, size / 2.f), 0),
676 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 4.f,
677 DlPoint(size / 2.f, size / 2.f), size / 2.f),
678 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 16.f,
679 DlPoint(size / 2.f, size / 2.f), size / 8.f),
680 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 8.f,
681 DlPoint(size / 2.f, size / 2.f), size / 16.f),
682 std::make_tuple(DlPoint(size / 8.f, size / 8.f), size / 8.f,
683 DlPoint(size / 2.f, size / 2.f), size / 8.f),
684 };
685 for (int i = 0; i < 8; i++) {
686 builder.Save();
687 builder.Translate((i % 3) * size, i / 3 * size);
688 paint.setColorSource(DlColorSource::MakeConical(
689 /*start_center=*/std::get<2>(array[i]),
690 /*start_radius=*/std::get<3>(array[i]),
691 /*end_center=*/std::get<0>(array[i]),
692 /*end_radius=*/std::get<1>(array[i]),
693 /*stop_count=*/stops.size(),
694 /*colors=*/colors.data(),
695 /*stops=*/stops.data(),
696 /*tile_mode=*/DlTileMode::kClamp));
697 builder.DrawRect(DlRect::MakeXYWH(0, 0, size, size), paint);
698 builder.Restore();
699 }
700 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
701 }

## ◆ TEST_P() [50/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradientWithDitheringEnabled |
| ) |  |

Definition at line 174 of file aiks_dl_gradient_unittests.cc.

174 {
175 CanRenderConicalGradientWithDithering(this);
176 }
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:155

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [51/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradientWithIncompleteStops |
| ) |  |

Definition at line 316 of file aiks_dl_gradient_unittests.cc.

316 {
317 CanRenderGradientWithIncompleteStops(this,
318 DlColorSourceType::kConicalGradient);
319 }

## ◆ TEST_P() [52/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderCurvedStrokes |
| ) |  |

Definition at line 71 of file aiks_dl_path_unittests.cc.

71 {
72 DisplayListBuilder builder;
73 DlPaint paint;
74 paint.setColor(DlColor::kRed());
75 paint.setStrokeWidth(25);
76 paint.setDrawStyle(DlDrawStyle::kStroke);
77
78 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
79
80 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
81 }

## ◆ TEST_P() [53/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDestructiveSaveLayer |
| ) |  |

Definition at line 383 of file aiks_dl_unittests.cc.

383 {
384 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
385
386 DlPaint paint;
387 paint.setColor(DlColor::kRed());
388 builder.DrawPaint(paint);
389 // Draw an empty savelayer with a destructive blend mode, which will replace
390 // the entire red screen with fully transparent black, except for the green
391 // circle drawn within the layer.
392
393 DlPaint save_paint;
394 save_paint.setBlendMode(DlBlendMode::kSrc);
395 builder.SaveLayer(std::nullopt, &save_paint);
396
397 DlPaint draw_paint;
398 draw_paint.setColor(DlColor::kGreen());
399 builder.DrawCircle(DlPoint(300, 300), 100, draw_paint);
400 builder.Restore();
401
402 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
403 }

## ◆ TEST_P() [54/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferenceClips |
| ) |  |

Definition at line 35 of file aiks_dl_clip_unittests.cc.

35 {
36 DisplayListBuilder builder;
37 builder.Translate(400, 400);
38
39 // Limit drawing to face circle with a clip.
40 builder.ClipPath(DlPath::MakeCircle(DlPoint(0, 0), 200));
41 builder.Save();
42
43 // Cut away eyes/mouth using difference clips.
44 builder.ClipPath(DlPath::MakeCircle(DlPoint(-100, -50), 30),
45 DlClipOp::kDifference);
46 builder.ClipPath(DlPath::MakeCircle(DlPoint(100, -50), 30),
47 DlClipOp::kDifference);
48
49 DlPathBuilder path_builder;
50 path_builder.MoveTo(DlPoint(-100, 50));
51 path_builder.QuadraticCurveTo(DlPoint(0, 150), DlPoint(100, 50));
52 builder.ClipPath(path_builder.TakePath(), DlClipOp::kDifference);
53
54 // Draw a huge yellow rectangle to prove the clipping works.
55 DlPaint paint;
56 paint.setColor(DlColor::kYellow());
57 builder.DrawRect(DlRect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
58
59 // Remove the difference clips and draw hair that partially covers the eyes.
60 builder.Restore();
61 paint.setColor(DlColor::kMaroon());
62 DlPathBuilder path_builder_2;
63 path_builder_2.MoveTo(DlPoint(200, -200));
64 path_builder_2.LineTo(DlPoint(-200, -200));
65 path_builder_2.LineTo(DlPoint(-200, -40));
66 path_builder_2.CubicCurveTo(DlPoint(0, -40), DlPoint(0, -80),
67 DlPoint(200, -80));
68
69 builder.DrawPath(path_builder_2.TakePath(), paint);
70
71 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
72 }

## ◆ TEST_P() [55/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferencePaths |
| ) |  |

Definition at line 395 of file aiks_dl_path_unittests.cc.

395 {
396 DisplayListBuilder builder;
397
398 DlPaint paint;
399 paint.setColor(DlColor::kRed());
400
401 RoundingRadii radii = {
402 .top_left = {50, 25},
403 .top_right = {25, 50},
404 .bottom_left = {25, 50},
405 .bottom_right = {50, 25},
406 };
407 DlPathBuilder path_builder;
408 DlRoundRect rrect =
409 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 200, 200), radii);
410 // We use the factory method to convert the rrect and circle to a path so
411 // that they use the legacy conics for legacy golden output.
412 path_builder.AddPath(DlPath::MakeRoundRect(rrect));
413 path_builder.AddPath(DlPath::MakeCircle(DlPoint(200, 200), 50));
414 path_builder.SetFillType(DlPathFillType::kOdd);
415 DlPath path = path_builder.TakePath();
416
417 builder.DrawImage(
418 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
419 DlPoint{10, 10}, {});
420 builder.DrawPath(path, paint);
421
422 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
423 }

References impeller::DlImageImpeller::Make(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [56/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferentShapesWithSameColorSource |
| ) |  |

Definition at line 417 of file aiks_dl_basic_unittests.cc.

417 {
418 DisplayListBuilder builder;
419 DlPaint paint;
420
421 DlColor colors[2] = {
422 DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
423 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
424 };
425 DlScalar stops[2] = {
426 0.0,
427 1.0,
428 };
429
430 paint.setColorSource(DlColorSource::MakeLinear(
431 /*start_point=*/DlPoint(0, 0), //
432 /*end_point=*/DlPoint(100, 100), //
433 /*stop_count=*/2, //
434 /*colors=*/colors, //
435 /*stops=*/stops, //
436 /*tile_mode=*/DlTileMode::kRepeat //
437 ));
438
439 builder.Save();
440 builder.Translate(100, 100);
441 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
442 builder.Restore();
443
444 builder.Save();
445 builder.Translate(100, 400);
446 builder.DrawCircle(DlPoint(100, 100), 100, paint);
447 builder.Restore();
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449 }
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23

## ◆ TEST_P() [57/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrame |
| ) |  |

Definition at line 384 of file aiks_dl_text_unittests.cc.

384 {
385 DisplayListBuilder builder;
386
387 DlPaint paint;
388 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
389 builder.DrawPaint(paint);
390
391 ASSERT_TRUE(RenderTextInCanvasSkia(
392 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
393 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
394 }
impeller::testing::RenderTextInCanvasSkia
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &font_fixture, const TextRenderOptions &options={}, const std::optional< SkFont > &font=std::nullopt)
Definition: aiks_dl_text_unittests.cc:46
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_dl_text_unittests.cc:377

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [58/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrameWithAlpha |
| ) |  |

Definition at line 412 of file aiks_dl_text_unittests.cc.

412 {
413 DisplayListBuilder builder;
414
415 DlPaint paint;
416 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
417 builder.DrawPaint(paint);
418
419 ASSERT_TRUE(RenderTextInCanvasSkia(
420 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
421 {.color = DlColor::kBlack().modulateOpacity(0.5)}));
422 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
423 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [59/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrameWithBlur |
| ) |  |

Definition at line 396 of file aiks_dl_text_unittests.cc.

396 {
397 DisplayListBuilder builder;
398
399 builder.Scale(GetContentScale().x, GetContentScale().y);
400 DlPaint paint;
401 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
402 builder.DrawPaint(paint);
403
404 ASSERT_TRUE(RenderTextInCanvasSkia(
405 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
406 TextRenderOptions{
407 .color = DlColor::kBlue(),
408 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
409 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
410 }

References impeller::testing::TextRenderOptions::color, kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [60/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderFilledConicPaths |
| ) |  |

Definition at line 159 of file aiks_dl_path_unittests.cc.

159 {
160 DisplayListBuilder builder;
161 builder.Scale(GetContentScale().x, GetContentScale().y);
162
163 DlPaint paint;
164 paint.setColor(DlColor::kRed());
165 paint.setDrawStyle(DlDrawStyle::kFill);
166
167 DlPaint reference_paint;
168 reference_paint.setColor(DlColor::kGreen());
169 reference_paint.setDrawStyle(DlDrawStyle::kFill);
170
171 DlPathBuilder path_builder;
172 DlPathBuilder reference_builder;
173
174 // weight of 1.0 is just a quadratic bezier
175 path_builder.MoveTo(DlPoint(100, 100));
176 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
177 reference_builder.MoveTo(DlPoint(300, 100));
178 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
179
180 // weight of sqrt(2)/2 is a circular section
181 path_builder.MoveTo(DlPoint(100, 200));
182 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
183 reference_builder.MoveTo(DlPoint(300, 200));
184 auto magic = DlPathBuilder::kArcApproximationMagic;
185 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
186 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
187 DlPoint(400, 200));
188
189 // weight of .01 is nearly a straight line
190 path_builder.MoveTo(DlPoint(100, 300));
191 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.01f);
192 reference_builder.MoveTo(DlPoint(300, 300));
193 reference_builder.LineTo(DlPoint(350, 300.5));
194 reference_builder.LineTo(DlPoint(400, 300));
195
196 // weight of 100.0 is nearly a triangle
197 path_builder.MoveTo(DlPoint(100, 400));
198 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
199 reference_builder.MoveTo(DlPoint(300, 400));
200 reference_builder.LineTo(DlPoint(350, 450));
201 reference_builder.LineTo(DlPoint(400, 400));
202
203 builder.DrawPath(path_builder.TakePath(), paint);
204 builder.DrawPath(reference_builder.TakePath(), reference_paint);
205
206 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
207 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [61/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundAdvancedBlendWithMaskBlur |
| ) |  |

Definition at line 184 of file aiks_dl_blur_unittests.cc.

184 {
185 // This case triggers the ForegroundAdvancedBlend path. The color filter
186 // should apply to the color only, and respect the alpha mask.
187 DisplayListBuilder builder;
188 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
189
190 DlPaint paint;
191 paint.setColor(
192 DlColor::RGBA(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1.0f));
193
194 Sigma sigma = Radius(20);
195 paint.setMaskFilter(
196 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
197 paint.setColorFilter(
198 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kColor));
199 builder.DrawCircle(DlPoint(400, 400), 200, paint);
200 builder.Restore();
201
202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
203 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [62/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundBlendWithMaskBlur |
| ) |  |

Definition at line 165 of file aiks_dl_blur_unittests.cc.

165 {
166 // This case triggers the ForegroundPorterDuffBlend path. The color filter
167 // should apply to the color only, and respect the alpha mask.
168 DisplayListBuilder builder;
169 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
170
171 DlPaint paint;
172 paint.setColor(DlColor::kWhite());
173
174 Sigma sigma = Radius(20);
175 paint.setMaskFilter(
176 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
177 paint.setColorFilter(
178 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kSrc));
179 builder.DrawCircle(DlPoint(400, 400), 200, paint);
180
181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [63/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderGradientDecalWithBackground |
| ) |  |

Definition at line 703 of file aiks_dl_gradient_unittests.cc.

703 {
704 std::vector<DlColor> colors = {
705 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
706 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
707 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
708 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
709 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
710
711 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
712 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
713 stops.data(), DlTileMode::kDecal),
714 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
715 stops.data(), DlTileMode::kDecal),
716 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
717 stops.data(), DlTileMode::kDecal),
718 };
719
720 DisplayListBuilder builder;
721 DlPaint paint;
722 paint.setColor(DlColor::kWhite());
723 builder.DrawRect(DlRect::MakeLTRB(0, 0, 605, 205), paint);
724 for (int i = 0; i < 3; i++) {
725 builder.Save();
726 builder.Translate(i * 200.0f, 0);
727 paint.setColorSource(color_sources[i]);
728 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
729 builder.Restore();
730 }
731 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
732 }

## ◆ TEST_P() [64/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderGroupOpacity |
| ) |  |

Definition at line 34 of file aiks_dl_opacity_unittests.cc.

34 {
35 DisplayListBuilder builder;
36
37 DlPaint red;
38 red.setColor(DlColor::kRed());
39 DlPaint green;
40 green.setColor(DlColor::kGreen().modulateOpacity(0.5));
41 DlPaint blue;
42 blue.setColor(DlColor::kBlue());
43
44 DlPaint alpha;
45 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
46
47 builder.SaveLayer(std::nullopt, &alpha);
48 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
49 builder.DrawRect(DlRect::MakeXYWH(200, 200, 100, 100), green);
50 builder.DrawRect(DlRect::MakeXYWH(400, 400, 100, 100), blue);
51 builder.Restore();
52
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54 }

## ◆ TEST_P() [65/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderGroupOpacityToSavelayer |
| ) |  |

Definition at line 56 of file aiks_dl_opacity_unittests.cc.

56 {
57 DisplayListBuilder builder;
58
59 DlPaint red;
60 red.setColor(DlColor::kRed());
61
62 DlPaint alpha;
63 alpha.setColor(DlColor::kRed().modulateOpacity(0.7));
64
65 // Create a saveLayer that will forward its opacity to another
66 // saveLayer, to verify that we correctly distribute opacity.
67 DlRect bounds = DlRect::MakeLTRB(0, 0, 500, 500);
68 builder.SaveLayer(bounds, &alpha);
69 builder.SaveLayer(bounds, &alpha);
70 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), red);
71 builder.DrawRect(DlRect::MakeXYWH(0, 0, 450, 450), red);
72 builder.Restore();
73 builder.Restore();
74
75 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
76 }

## ◆ TEST_P() [66/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderImage |
| ) |  |

Definition at line 107 of file aiks_dl_basic_unittests.cc.

107 {
108 DisplayListBuilder builder;
109 DlPaint paint;
110 paint.setColor(DlColor::kRed());
111 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
112 builder.DrawImage(image, DlPoint(100.0, 100.0),
113 DlImageSampling::kNearestNeighbor, &paint);
114 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
115 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [67/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderImageRect |
| ) |  |

Definition at line 277 of file aiks_dl_basic_unittests.cc.

277 {
278 DisplayListBuilder builder;
279 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
280
281 DlISize image_half_size =
282 DlISize(image->GetSize().width * 0.5f, image->GetSize().height * 0.5f);
283
284 // Render the bottom right quarter of the source image in a stretched rect.
285 auto source_rect = DlRect::MakeSize(image_half_size);
286 source_rect =
287 source_rect.Shift(image_half_size.width, image_half_size.height);
288
289 builder.DrawImageRect(image, source_rect,
290 DlRect::MakeXYWH(100, 100, 600, 600),
291 DlImageSampling::kNearestNeighbor);
292 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
293 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [68/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderInvertedImageWithColorFilter |
| ) |  |

Definition at line 117 of file aiks_dl_basic_unittests.cc.

117 {
118 DisplayListBuilder builder;
119 DlPaint paint;
120 paint.setColor(DlColor::kRed());
121 paint.setColorFilter(
122 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
123 paint.setInvertColors(true);
124 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
125
126 builder.DrawImage(image, DlPoint(100.0, 100.0),
127 DlImageSampling::kNearestNeighbor, &paint);
128 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
129 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [69/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderItalicizedText |
| ) |  |

Definition at line 364 of file aiks_dl_text_unittests.cc.

364 {
365 DisplayListBuilder builder;
366
367 DlPaint paint;
368 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
369 builder.DrawPaint(paint);
370
371 ASSERT_TRUE(RenderTextInCanvasSkia(
372 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
373 "HomemadeApple.ttf"));
374 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
375 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [70/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientClamp |
| ) |  |

Definition at line 55 of file aiks_dl_gradient_unittests.cc.

55 {
56 CanRenderLinearGradient(this, DlTileMode::kClamp);
57 }

## ◆ TEST_P() [71/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientDecal |
| ) |  |

Definition at line 64 of file aiks_dl_gradient_unittests.cc.

64 {
65 CanRenderLinearGradient(this, DlTileMode::kDecal);
66 }

## ◆ TEST_P() [72/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientDecalWithColorFilter |
| ) |  |

Definition at line 68 of file aiks_dl_gradient_unittests.cc.

68 {
69 DisplayListBuilder builder;
70 Point scale = GetContentScale();
71 builder.Scale(scale.x, scale.y);
72 DlPaint paint;
73 builder.Translate(100.0f, 0);
74
75 std::vector<DlColor> colors = {
76 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
77 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
78 std::vector<Scalar> stops = {0.0, 1.0};
79
80 paint.setColorSource(DlColorSource::MakeLinear(
81 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kDecal));
82 // Overlay the gradient with 25% green. This should appear as the entire
83 // rectangle being drawn with 25% green, including the border area outside the
84 // decal gradient.
85 paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kGreen().withAlpha(64),
86 DlBlendMode::kSrcOver));
87 paint.setColor(DlColor::kWhite());
88 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
89 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
90 }

References impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [73/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsClamp |
| ) |  |

Definition at line 361 of file aiks_dl_gradient_unittests.cc.

361 {
362 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
363 }

## ◆ TEST_P() [74/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsDecal |
| ) |  |

Definition at line 370 of file aiks_dl_gradient_unittests.cc.

370 {
371 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
372 }

## ◆ TEST_P() [75/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsMirror |
| ) |  |

Definition at line 367 of file aiks_dl_gradient_unittests.cc.

367 {
368 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
369 }

## ◆ TEST_P() [76/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsRepeat |
| ) |  |

Definition at line 364 of file aiks_dl_gradient_unittests.cc.

364 {
365 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
366 }

## ◆ TEST_P() [77/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsUnevenStops |
| ) |  |

Definition at line 405 of file aiks_dl_gradient_unittests.cc.

405 {
406 auto callback = [&]() -> sk_sp<DisplayList> {
407 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
408 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
409 DlTileMode::kMirror, DlTileMode::kDecal};
410
411 static int selected_tile_mode = 0;
412 static Matrix matrix;
413 if (AiksTest::ImGuiBegin("Controls", nullptr,
414 ImGuiWindowFlags_AlwaysAutoResize)) {
415 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
416 sizeof(tile_mode_names) / sizeof(char*));
417 std::string label = "##1";
418 for (int i = 0; i < 4; i++) {
419 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
420 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
421 label[2]++;
422 }
423 ImGui::End();
424 }
425
426 DisplayListBuilder builder;
427 DlPaint paint;
428 builder.Translate(100.0, 100.0);
429 auto tile_mode = tile_modes[selected_tile_mode];
430
431 std::vector<DlColor> colors = {
432 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
433 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
434 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
435 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
436 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
437 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
438 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
439 std::vector<Scalar> stops = {
440 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
441 };
442
443 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
444 stops.size(), colors.data(),
445 stops.data(), tile_mode));
446
447 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
448 return builder.Build();
449 };
450 ASSERT_TRUE(OpenPlaygroundHere(callback));
451 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [78/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientMaskBlur |
| ) |  |

Definition at line 453 of file aiks_dl_gradient_unittests.cc.

453 {
454 DisplayListBuilder builder;
455
456 std::vector<DlColor> colors = {
457 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
458 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
459 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed()};
460 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
461 0.6, 0.7, 0.8, 0.9, 1.0};
462
463 DlPaint paint;
464 paint.setColor(DlColor::kWhite());
465 paint.setColorSource(DlColorSource::MakeLinear(
466 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
467 DlTileMode::kClamp));
468 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
469
470 builder.DrawCircle(DlPoint(300, 300), 200, paint);
471 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
472
473 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
474 }

## ◆ TEST_P() [79/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientMirror |
| ) |  |

Definition at line 61 of file aiks_dl_gradient_unittests.cc.

61 {
62 CanRenderLinearGradient(this, DlTileMode::kMirror);
63 }

## ◆ TEST_P() [80/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientRepeat |
| ) |  |

Definition at line 58 of file aiks_dl_gradient_unittests.cc.

58 {
59 CanRenderLinearGradient(this, DlTileMode::kRepeat);
60 }

## ◆ TEST_P() [81/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWayManyColorsClamp |
| ) |  |

Definition at line 401 of file aiks_dl_gradient_unittests.cc.

401 {
402 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
403 }

## ◆ TEST_P() [82/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithDitheringEnabled |
| ) |  |

Definition at line 108 of file aiks_dl_gradient_unittests.cc.

108 {
109 CanRenderLinearGradientWithDithering(this);
110 }
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:92

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [83/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithIncompleteStops |
| ) |  |

Definition at line 308 of file aiks_dl_gradient_unittests.cc.

308 {
309 CanRenderGradientWithIncompleteStops(this,
310 DlColorSourceType::kLinearGradient);
311 }

## ◆ TEST_P() [84/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithOverlappingStopsClamp |
| ) |  |

Definition at line 203 of file aiks_dl_gradient_unittests.cc.

203 {
204 CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp);
205 }

## ◆ TEST_P() [85/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMaskBlurHugeSigma |
| ) |  |

Definition at line 153 of file aiks_dl_blur_unittests.cc.

153 {
154 DisplayListBuilder builder;
155
156 DlPaint paint;
157 paint.setColor(DlColor::kGreen());
158 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 99999));
159 builder.DrawCircle(DlPoint(400, 400), 300, paint);
160 builder.Restore();
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }

## ◆ TEST_P() [86/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropId |
| ) |  |

Definition at line 296 of file aiks_dl_blur_unittests.cc.

296 {
297 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
298
299 DisplayListBuilder builder;
300
301 DlPaint paint;
302 builder.DrawImage(image, DlPoint(50.0, 50.0),
303 DlImageSampling::kNearestNeighbor, &paint);
304
305 for (int i = 0; i < 6; i++) {
306 DlRoundRect rrect = DlRoundRect::MakeRectXY(
307 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
308 builder.Save();
309 builder.ClipRoundRect(rrect);
310
311 DlPaint save_paint;
312 save_paint.setBlendMode(DlBlendMode::kSrc);
313 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
314 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
315 /*backdrop_id=*/1);
316 builder.Restore();
317 builder.Restore();
318 }
319
320 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
321 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [87/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters |
| ) |  |

Definition at line 323 of file aiks_dl_blur_unittests.cc.

324 {
325 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
326
327 DisplayListBuilder builder;
328
329 DlPaint paint;
330 builder.DrawImage(image, DlPoint(50.0, 50.0),
331 DlImageSampling::kNearestNeighbor, &paint);
332
333 for (int i = 0; i < 6; i++) {
334 DlRoundRect rrect = DlRoundRect::MakeRectXY(
335 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
336 builder.Save();
337 builder.ClipRoundRect(rrect);
338
339 DlPaint save_paint;
340 save_paint.setBlendMode(DlBlendMode::kSrc);
341 auto backdrop_filter =
342 DlImageFilter::MakeBlur(30 + i, 30, DlTileMode::kClamp);
343 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
344 /*backdrop_id=*/1);
345 builder.Restore();
346 builder.Restore();
347 }
348
349 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
350 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [88/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers |
| ) |  |

Definition at line 1400 of file aiks_dl_blur_unittests.cc.

1401 {
1402 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1403
1404 DisplayListBuilder builder;
1405
1406 DlPaint paint;
1407 builder.DrawImage(image, DlPoint(50.0, 50.0),
1408 DlImageSampling::kNearestNeighbor, &paint);
1409
1410 for (int i = 0; i < 6; i++) {
1411 if (i != 0) {
1412 DlPaint paint;
1413 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1414 builder.SaveLayer(std::nullopt, &paint);
1415 }
1416 DlRoundRect rrect = DlRoundRect::MakeRectXY(
1417 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1418 builder.Save();
1419 builder.ClipRoundRect(rrect);
1420
1421 DlPaint save_paint;
1422 save_paint.setBlendMode(DlBlendMode::kSrc);
1423 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1424 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
1425 /*backdrop_id=*/1);
1426 builder.Restore();
1427 builder.Restore();
1428 if (i != 0) {
1429 builder.Restore();
1430 }
1431 }
1432
1433 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1434 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [89/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderNestedBackdropBlur |
| ) |  |

Definition at line 1464 of file aiks_dl_blur_unittests.cc.

1464 {
1465 int64_t count = 0;
1466 auto callback = [&]() -> sk_sp<DisplayList> {
1467 DisplayListBuilder builder;
1468
1469 Scalar freq = 1.0;
1470 Scalar amp = 50.0;
1471 Scalar offset = amp * sin(freq * 2.0 * M_PI * count / 60.0);
1472
1473 // Draw some background content to be blurred.
1474 DlPaint paint;
1475 paint.setColor(DlColor::kCornflowerBlue());
1476 builder.DrawCircle(DlPoint(100 + offset, 100), 50, paint);
1477 paint.setColor(DlColor::kGreenYellow());
1478 builder.DrawCircle(DlPoint(300, 200 + offset), 100, paint);
1479 paint.setColor(DlColor::kDarkMagenta());
1480 builder.DrawCircle(DlPoint(140, 170), 75, paint);
1481 paint.setColor(DlColor::kOrangeRed());
1482 builder.DrawCircle(DlPoint(180 + offset, 120 + offset), 100, paint);
1483
1484 // This is the first backdrop blur, simulating the navigation transition.
1485 auto backdrop_filter1 = DlImageFilter::MakeBlur(15, 15, DlTileMode::kClamp);
1486 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter1.get());
1487
1488 // Draw the semi-transparent container from the second screen.
1489 DlPaint transparent_paint;
1490 transparent_paint.setColor(DlColor::kWhite().withAlpha(0.1 * 255));
1491 builder.DrawPaint(transparent_paint);
1492
1493 {
1494 // This is the second, nested backdrop blur.
1495 auto backdrop_filter2 =
1496 DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
1497 builder.Save();
1498 builder.ClipRect(DlRect::MakeXYWH(150, 150, 300, 300));
1499 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter2.get());
1500 builder.Restore(); // Restore from SaveLayer
1501 builder.Restore(); // Restore from ClipRect
1502 }
1503
1504 builder.Restore(); // Restore from the first SaveLayer
1505
1506 count++;
1507 return builder.Build();
1508 };
1509 ASSERT_TRUE(OpenPlaygroundHere(callback));
1510 }

## ◆ TEST_P() [90/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderNestedClips |
| ) |  |

Definition at line 20 of file aiks_dl_clip_unittests.cc.

20 {
21 DisplayListBuilder builder;
22 DlPaint paint;
23 paint.setColor(DlColor::kFuchsia());
24
25 builder.Save();
26 builder.ClipPath(DlPath::MakeCircle(DlPoint(200, 400), 300));
27 builder.Restore();
28 builder.ClipPath(DlPath::MakeCircle(DlPoint(600, 400), 300));
29 builder.ClipPath(DlPath::MakeCircle(DlPoint(400, 600), 300));
30 builder.DrawRect(DlRect::MakeXYWH(200, 200, 400, 400), paint);
31
32 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
33 }

## ◆ TEST_P() [91/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderOverlappingMultiContourPath |
| ) |  |

Definition at line 914 of file aiks_dl_path_unittests.cc.

914 {
915 DisplayListBuilder builder;
916
917 DlPaint paint;
918 paint.setColor(DlColor::kRed());
919
920 RoundingRadii radii = {
921 .top_left = DlSize(50, 50),
922 .top_right = DlSize(50, 50),
923 .bottom_left = DlSize(50, 50),
924 .bottom_right = DlSize(50, 50),
925 };
926
927 const Scalar kTriangleHeight = 100;
928 DlRoundRect rrect = DlRoundRect::MakeRectRadii(
929 DlRect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
930 kTriangleHeight, kTriangleHeight),
931 radii //
932 );
933 // We use the factory method to convert the rrect to a path so that it
934 // uses the legacy conics for legacy golden output.
935 DlPath rrect_path = DlPath::MakeRoundRect(rrect);
936
937 builder.Translate(200, 200);
938 // Form a path similar to the Material drop slider value indicator. Both
939 // shapes should render identically side-by-side.
940 {
941 DlPathBuilder path_builder;
942 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
943 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
944 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
945 path_builder.Close();
946 path_builder.AddPath(rrect_path);
947
948 builder.DrawPath(path_builder.TakePath(), paint);
949 }
950 builder.Translate(100, 0);
951
952 {
953 DlPathBuilder path_builder;
954 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
955 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
956 path_builder.LineTo(DlPoint(0, -10));
957 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
958 path_builder.Close();
959 path_builder.AddPath(rrect_path);
960
961 builder.DrawPath(path_builder.TakePath(), paint);
962 }
963
964 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
965 }

References impeller::RoundingRadii::top_left.

## ◆ TEST_P() [92/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderQuadraticStrokeWithInstantTurn |
| ) |  |

Definition at line 139 of file aiks_dl_path_unittests.cc.

139 {
140 DisplayListBuilder builder;
141
142 DlPaint paint;
143 paint.setColor(DlColor::kRed());
144 paint.setStrokeWidth(50);
145 paint.setDrawStyle(DlDrawStyle::kStroke);
146 paint.setStrokeCap(DlStrokeCap::kRound);
147
148 // Should draw a diagonal pill shape. If flat on either end, the stroke is
149 // rendering wrong.
150 DlPathBuilder path_builder;
151 path_builder.MoveTo(DlPoint(250, 250));
152 path_builder.QuadraticCurveTo(DlPoint(100, 100), DlPoint(250, 250));
153
154 builder.DrawPath(path_builder.TakePath(), paint);
155
156 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
157 }

## ◆ TEST_P() [93/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradient |
| ) |  |

Definition at line 476 of file aiks_dl_gradient_unittests.cc.

476 {
477 auto callback = [&]() -> sk_sp<DisplayList> {
478 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
479 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
480 DlTileMode::kMirror, DlTileMode::kDecal};
481
482 static int selected_tile_mode = 0;
483 static Matrix matrix;
484 if (AiksTest::ImGuiBegin("Controls", nullptr,
485 ImGuiWindowFlags_AlwaysAutoResize)) {
486 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
487 sizeof(tile_mode_names) / sizeof(char*));
488 std::string label = "##1";
489 for (int i = 0; i < 4; i++) {
490 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
491 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
492 label[2]++;
493 }
494 ImGui::End();
495 }
496
497 DisplayListBuilder builder;
498 DlPaint paint;
499 builder.Translate(100.0, 100.0);
500 auto tile_mode = tile_modes[selected_tile_mode];
501
502 std::vector<DlColor> colors = {
503 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
504 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
505 std::vector<Scalar> stops = {0.0, 1.0};
506
507 paint.setColorSource(DlColorSource::MakeRadial(
508 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
509
510 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
511 return builder.Build();
512 };
513 ASSERT_TRUE(OpenPlaygroundHere(callback));
514 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [94/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientManyColors |
| ) |  |

Definition at line 516 of file aiks_dl_gradient_unittests.cc.

516 {
517 auto callback = [&]() -> sk_sp<DisplayList> {
518 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
519 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
520 DlTileMode::kMirror, DlTileMode::kDecal};
521
522 static int selected_tile_mode = 0;
523 static Matrix matrix = {
524 1, 0, 0, 0, //
525 0, 1, 0, 0, //
526 0, 0, 1, 0, //
527 0, 0, 0, 1 //
528 };
529 if (AiksTest::ImGuiBegin("Controls", nullptr,
530 ImGuiWindowFlags_AlwaysAutoResize)) {
531 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
532 sizeof(tile_mode_names) / sizeof(char*));
533 std::string label = "##1";
534 for (int i = 0; i < 4; i++) {
535 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
536 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
537 label[2]++;
538 }
539 ImGui::End();
540 }
541
542 DisplayListBuilder builder;
543 DlPaint paint;
544 builder.Translate(100.0, 100.0);
545 auto tile_mode = tile_modes[selected_tile_mode];
546
547 std::vector<DlColor> colors = {
548 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
549 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
550 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
551 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
552 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
553 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
554 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
555 std::vector<Scalar> stops = {
556 0.0,
557 (1.0 / 6.0) * 1,
558 (1.0 / 6.0) * 2,
559 (1.0 / 6.0) * 3,
560 (1.0 / 6.0) * 4,
561 (1.0 / 6.0) * 5,
562 1.0,
563 };
564
565 paint.setColorSource(DlColorSource::MakeRadial(
566 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
567
568 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
569 return builder.Build();
570 };
571 ASSERT_TRUE(OpenPlaygroundHere(callback));
572 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [95/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientWithDitheringEnabled |
| ) |  |

Definition at line 128 of file aiks_dl_gradient_unittests.cc.

128 {
129 CanRenderRadialGradientWithDithering(this);
130 }
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:112

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [96/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientWithIncompleteStops |
| ) |  |

Definition at line 312 of file aiks_dl_gradient_unittests.cc.

312 {
313 CanRenderGradientWithIncompleteStops(this,
314 DlColorSourceType::kRadialGradient);
315 }

## ◆ TEST_P() [97/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRoundedRectWithNonUniformRadii |
| ) |  |

Definition at line 451 of file aiks_dl_basic_unittests.cc.

451 {
452 DisplayListBuilder builder;
453 DlPaint paint;
454 paint.setColor(DlColor::kRed());
455
456 RoundingRadii radii = {
457 .top_left = DlSize(50, 25),
458 .top_right = DlSize(25, 50),
459 .bottom_left = DlSize(25, 50),
460 .bottom_right = DlSize(50, 25),
461 };
462 DlRoundRect rrect =
463 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 500, 500), radii);
464
465 builder.DrawRoundRect(rrect, paint);
466
467 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
468 }

References impeller::RoundingRadii::top_left.

## ◆ TEST_P() [98/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRuntimeEffectFilter |
| ) |  |

Definition at line 100 of file aiks_dl_runtime_effect_unittests.cc.

100 {
101 auto runtime_stages_result =
102 OpenAssetAsRuntimeStage("runtime_stage_filter_example.frag.iplr");
103 ABSL_ASSERT_OK(runtime_stages_result);
104 std::shared_ptr<RuntimeStage> runtime_stage =
105 runtime_stages_result
106 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
107 ASSERT_TRUE(runtime_stage);
108 ASSERT_TRUE(runtime_stage->IsDirty());
109
110 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
111 nullptr,
112 };
113 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
114 uniform_data->resize(sizeof(Vector2));
115
116 DlPaint paint;
117 paint.setColor(DlColor::kAqua());
118 paint.setImageFilter(DlImageFilter::MakeRuntimeEffect(
119 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
120 uniform_data));
121
122 DisplayListBuilder builder;
123 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
124
125 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
126 }
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:33

References flutter::DlRuntimeEffectImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [99/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSimpleClips |
| ) |  |

Definition at line 315 of file aiks_dl_basic_unittests.cc.

315 {
316 DisplayListBuilder builder;
317 builder.Scale(GetContentScale().x, GetContentScale().y);
318 DlPaint paint;
319
320 paint.setColor(DlColor::kWhite());
321 builder.DrawPaint(paint);
322
323 auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
324 builder.Save();
325 builder.Translate(x, y);
326 {
327 builder.Save();
328 builder.ClipRect(DlRect::MakeLTRB(50, 50, 150, 150));
329 builder.DrawPaint(paint);
330 builder.Restore();
331 }
332 {
333 builder.Save();
334 builder.ClipOval(DlRect::MakeLTRB(200, 50, 300, 150));
335 builder.DrawPaint(paint);
336 builder.Restore();
337 }
338 {
339 builder.Save();
340 builder.ClipRoundRect(
341 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(50, 200, 150, 300), 20, 20));
342 builder.DrawPaint(paint);
343 builder.Restore();
344 }
345 {
346 builder.Save();
347 builder.ClipRoundRect(DlRoundRect::MakeRectXY(
348 DlRect::MakeLTRB(200, 230, 300, 270), 20, 20));
349 builder.DrawPaint(paint);
350 builder.Restore();
351 }
352 {
353 builder.Save();
354 builder.ClipRoundRect(DlRoundRect::MakeRectXY(
355 DlRect::MakeLTRB(230, 200, 270, 300), 20, 20));
356 builder.DrawPaint(paint);
357 builder.Restore();
358 }
359 builder.Restore();
360 };
361
362 paint.setColor(DlColor::kBlue());
363 draw(paint, 0, 0);
364
365 DlColor gradient_colors[7] = {
366 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
367 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
368 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
369 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
370 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
371 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
372 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
373 };
374 Scalar stops[7] = {
375 0.0,
376 (1.0 / 6.0) * 1,
377 (1.0 / 6.0) * 2,
378 (1.0 / 6.0) * 3,
379 (1.0 / 6.0) * 4,
380 (1.0 / 6.0) * 5,
381 1.0,
382 };
383 auto texture = CreateTextureForFixture("airplane.jpg",
384 /*enable_mipmapping=*/true);
385 auto image = DlImageImpeller::Make(texture);
386
387 paint.setColorSource(DlColorSource::MakeRadial(
388 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
389 draw(paint, 0, 300);
390
391 paint.setColorSource(
392 DlColorSource::MakeImage(image, DlTileMode::kRepeat, DlTileMode::kRepeat,
393 DlImageSampling::kNearestNeighbor));
394 draw(paint, 300, 0);
395
396 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
397 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [100/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokedConicPaths |
| ) |  |

Definition at line 209 of file aiks_dl_path_unittests.cc.

209 {
210 DisplayListBuilder builder;
211 builder.Scale(GetContentScale().x, GetContentScale().y);
212
213 DlPaint paint;
214 paint.setColor(DlColor::kRed());
215 paint.setStrokeWidth(10);
216 paint.setDrawStyle(DlDrawStyle::kStroke);
217 paint.setStrokeCap(DlStrokeCap::kRound);
218 paint.setStrokeJoin(DlStrokeJoin::kRound);
219
220 DlPaint reference_paint;
221 reference_paint.setColor(DlColor::kGreen());
222 reference_paint.setStrokeWidth(10);
223 reference_paint.setDrawStyle(DlDrawStyle::kStroke);
224 reference_paint.setStrokeCap(DlStrokeCap::kRound);
225 reference_paint.setStrokeJoin(DlStrokeJoin::kRound);
226
227 DlPathBuilder path_builder;
228 DlPathBuilder reference_builder;
229
230 // weight of 1.0 is just a quadratic bezier
231 path_builder.MoveTo(DlPoint(100, 100));
232 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
233 reference_builder.MoveTo(DlPoint(300, 100));
234 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
235
236 // weight of sqrt(2)/2 is a circular section
237 path_builder.MoveTo(DlPoint(100, 200));
238 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
239 reference_builder.MoveTo(DlPoint(300, 200));
240 auto magic = DlPathBuilder::kArcApproximationMagic;
241 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
242 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
243 DlPoint(400, 200));
244
245 // weight of .0 is a straight line
246 path_builder.MoveTo(DlPoint(100, 300));
247 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.0f);
248 reference_builder.MoveTo(DlPoint(300, 300));
249 reference_builder.LineTo(DlPoint(400, 300));
250
251 // weight of 100.0 is nearly a triangle
252 path_builder.MoveTo(DlPoint(100, 400));
253 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
254 reference_builder.MoveTo(DlPoint(300, 400));
255 reference_builder.LineTo(DlPoint(350, 450));
256 reference_builder.LineTo(DlPoint(400, 400));
257
258 builder.DrawPath(path_builder.TakePath(), paint);
259 builder.DrawPath(reference_builder.TakePath(), reference_paint);
260
261 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
262 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [101/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokedTextFrame |
| ) |  |

Definition at line 128 of file aiks_dl_text_unittests.cc.

128 {
129 DisplayListBuilder builder;
130
131 DlPaint paint;
132 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
133 builder.DrawPaint(paint);
134
135 ASSERT_TRUE(RenderTextInCanvasSkia(
136 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
137 "Roboto-Regular.ttf",
138 {
139 .stroke = true,
140 }));
141 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
142 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [102/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokePathThatEndsAtSharpTurn |
| ) |  |

Definition at line 107 of file aiks_dl_path_unittests.cc.

107 {
108 DisplayListBuilder builder;
109 DlPaint paint;
110 paint.setColor(DlColor::kRed());
111 paint.setStrokeWidth(200);
112 paint.setDrawStyle(DlDrawStyle::kStroke);
113
114 DlPath path = DlPath::MakeArc(DlRect::MakeXYWH(100, 100, 200, 200), //
115 DlDegrees(0), DlDegrees(90), false);
116
117 builder.DrawPath(path, paint);
118
119 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
120 }

## ◆ TEST_P() [103/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokePathWithCubicLine |
| ) |  |

Definition at line 122 of file aiks_dl_path_unittests.cc.

122 {
123 DisplayListBuilder builder;
124
125 DlPaint paint;
126 paint.setColor(DlColor::kRed());
127 paint.setStrokeWidth(20);
128 paint.setDrawStyle(DlDrawStyle::kStroke);
129
130 DlPathBuilder path_builder;
131 path_builder.MoveTo(DlPoint(0, 200));
132 path_builder.CubicCurveTo(DlPoint(50, 400), DlPoint(350, 0),
133 DlPoint(400, 200));
134
135 builder.DrawPath(path_builder.TakePath(), paint);
136 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
137 }

## ◆ TEST_P() [104/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokes |
| ) |  |

Definition at line 58 of file aiks_dl_path_unittests.cc.

58 {
59 DisplayListBuilder builder;
60 DlPaint paint;
61 paint.setColor(DlColor::kRed());
62 paint.setStrokeWidth(20);
63 paint.setDrawStyle(DlDrawStyle::kStroke);
64
65 builder.DrawPath(DlPath::MakeLine(DlPoint(200, 100), DlPoint(800, 100)),
66 paint);
67
68 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
69 }

## ◆ TEST_P() [105/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientClamp |
| ) |  |

Definition at line 595 of file aiks_dl_gradient_unittests.cc.

595 {
596 CanRenderSweepGradient(this, DlTileMode::kClamp);
597 }

## ◆ TEST_P() [106/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientDecal |
| ) |  |

Definition at line 604 of file aiks_dl_gradient_unittests.cc.

604 {
605 CanRenderSweepGradient(this, DlTileMode::kDecal);
606 }

## ◆ TEST_P() [107/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsClamp |
| ) |  |

Definition at line 642 of file aiks_dl_gradient_unittests.cc.

642 {
643 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
644 }

## ◆ TEST_P() [108/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsDecal |
| ) |  |

Definition at line 651 of file aiks_dl_gradient_unittests.cc.

651 {
652 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
653 }

## ◆ TEST_P() [109/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsMirror |
| ) |  |

Definition at line 648 of file aiks_dl_gradient_unittests.cc.

648 {
649 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
650 }

## ◆ TEST_P() [110/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsRepeat |
| ) |  |

Definition at line 645 of file aiks_dl_gradient_unittests.cc.

645 {
646 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
647 }

## ◆ TEST_P() [111/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientMirror |
| ) |  |

Definition at line 601 of file aiks_dl_gradient_unittests.cc.

601 {
602 CanRenderSweepGradient(this, DlTileMode::kMirror);
603 }

## ◆ TEST_P() [112/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientRepeat |
| ) |  |

Definition at line 598 of file aiks_dl_gradient_unittests.cc.

598 {
599 CanRenderSweepGradient(this, DlTileMode::kRepeat);
600 }

## ◆ TEST_P() [113/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientWithDitheringEnabled |
| ) |  |

Definition at line 151 of file aiks_dl_gradient_unittests.cc.

151 {
152 CanRenderSweepGradientWithDithering(this);
153 }
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:132

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [114/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientWithIncompleteStops |
| ) |  |

Definition at line 320 of file aiks_dl_gradient_unittests.cc.

320 {
321 CanRenderGradientWithIncompleteStops(this, DlColorSourceType::kSweepGradient);
322 }

## ◆ TEST_P() [115/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrame |
| ) |  |

Definition at line 99 of file aiks_dl_text_unittests.cc.

99 {
100 DisplayListBuilder builder;
101
102 DlPaint paint;
103 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
104 builder.DrawPaint(paint);
105 ASSERT_TRUE(RenderTextInCanvasSkia(
106 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
107 "Roboto-Regular.ttf"));
108
109 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
110 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [116/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithFractionScaling |
| ) |  |

Definition at line 253 of file aiks_dl_text_unittests.cc.

253 {
254 Scalar fine_scale = 0.f;
255 bool is_subpixel = false;
256 auto callback = [&]() -> sk_sp<DisplayList> {
257 if (AiksTest::ImGuiBegin("Controls", nullptr,
258 ImGuiWindowFlags_AlwaysAutoResize)) {
259 ImGui::SliderFloat("Fine Scale", &fine_scale, -1, 1);
260 ImGui::Checkbox("subpixel", &is_subpixel);
261 ImGui::End();
262 }
263
264 DisplayListBuilder builder;
265 DlPaint paint;
266 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
267 builder.DrawPaint(paint);
268 Scalar scale = 2.625 + fine_scale;
269 builder.Scale(scale, scale);
270 RenderTextInCanvasSkia(GetContext(), builder,
271 "the quick brown fox jumped over the lazy dog!.?",
272 "Roboto-Regular.ttf",
273 TextRenderOptions{.is_subpixel = is_subpixel});
274 return builder.Build();
275 };
276
277 ASSERT_TRUE(OpenPlaygroundHere(callback));
278 }
is_subpixel
bool is_subpixel
Definition: text_contents_unittests.cc:28

References impeller::testing::TextRenderOptions::is_subpixel, is_subpixel, and RenderTextInCanvasSkia().

## ◆ TEST_P() [117/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithHalfScaling |
| ) |  |

Definition at line 160 of file aiks_dl_text_unittests.cc.

160 {
161 DisplayListBuilder builder;
162
163 DlPaint paint;
164 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
165 builder.DrawPaint(paint);
166 builder.Scale(0.5, 0.5);
167
168 ASSERT_TRUE(RenderTextInCanvasSkia(
169 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
170 "Roboto-Regular.ttf"));
171 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
172 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [118/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithInvertedTransform |
| ) |  |

Definition at line 112 of file aiks_dl_text_unittests.cc.

112 {
113 DisplayListBuilder builder;
114
115 DlPaint paint;
116 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
117 builder.DrawPaint(paint);
118 builder.Translate(1000, 0);
119 builder.Scale(-1, 1);
120
121 ASSERT_TRUE(RenderTextInCanvasSkia(
122 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
123 "Roboto-Regular.ttf"));
124
125 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
126 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [119/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithScalingOverflow |
| ) |  |

Definition at line 224 of file aiks_dl_text_unittests.cc.

224 {
225 Scalar scale = 60.0;
226 Scalar offsetx = -500.0;
227 Scalar offsety = 700.0;
228 auto callback = [&]() -> sk_sp<DisplayList> {
229 if (AiksTest::ImGuiBegin("Controls", nullptr,
230 ImGuiWindowFlags_AlwaysAutoResize)) {
231 ImGui::SliderFloat("scale", &scale, 1.f, 300.f);
232 ImGui::SliderFloat("offsetx", &offsetx, -600.f, 100.f);
233 ImGui::SliderFloat("offsety", &offsety, 600.f, 2048.f);
234 ImGui::End();
235 }
236 DisplayListBuilder builder;
237 builder.Scale(GetContentScale().x, GetContentScale().y);
238 DlPaint paint;
239 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
240 builder.DrawPaint(paint);
241 builder.Scale(scale, scale);
242
243 RenderTextInCanvasSkia(
244 GetContext(), builder, "test", "Roboto-Regular.ttf",
245 TextRenderOptions{
246 .position = DlPoint(offsetx / scale, offsety / scale),
247 });
248 return builder.Build();
249 };
250 ASSERT_TRUE(OpenPlaygroundHere(callback));
251 }

References impeller::testing::TextRenderOptions::position, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [120/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextInSaveLayer |
| ) |  |

Definition at line 425 of file aiks_dl_text_unittests.cc.

425 {
426 DisplayListBuilder builder;
427
428 DlPaint paint;
429 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
430 builder.DrawPaint(paint);
431
432 builder.Translate(100, 100);
433 builder.Scale(0.5, 0.5);
434
435 // Blend the layer with the parent pass using kClear to expose the coverage.
436 paint.setBlendMode(DlBlendMode::kClear);
437 builder.SaveLayer(std::nullopt, &paint);
438 ASSERT_TRUE(RenderTextInCanvasSkia(
439 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
440 "Roboto-Regular.ttf"));
441 builder.Restore();
442
443 // Render the text again over the cleared coverage rect.
444 ASSERT_TRUE(RenderTextInCanvasSkia(
445 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
446 "Roboto-Regular.ttf"));
447
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [121/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextOutsideBoundaries |
| ) |  |

Definition at line 451 of file aiks_dl_text_unittests.cc.

451 {
452 DisplayListBuilder builder;
453 builder.Translate(200, 150);
454
455 // Construct the text blob.
456 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
457 ASSERT_NE(mapping, nullptr);
458
459 Scalar font_size = 80;
460 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
461 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
462
463 DlPaint text_paint;
464 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
465
466 struct {
467 DlPoint position;
468 const char* text;
469 } text[] = {{DlPoint(0, 0), "0F0F0F0"},
470 {DlPoint(1, 2), "789"},
471 {DlPoint(1, 3), "456"},
472 {DlPoint(1, 4), "123"},
473 {DlPoint(0, 6), "0F0F0F0"}};
474 for (auto& t : text) {
475 builder.Save();
476 builder.Translate(t.position.x * font_size * 2,
477 t.position.y * font_size * 1.1);
478 {
479 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
480 ASSERT_NE(blob, nullptr);
481 auto frame = MakeTextFrameFromTextBlobSkia(blob);
482 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
483 }
484 builder.Restore();
485 }
486
487 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
488 }
font_size
Scalar font_size
Definition: text_contents_unittests.cc:27

References font_size, flutter::DlTextImpeller::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [122/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextStrokeWidth |
| ) |  |

Definition at line 144 of file aiks_dl_text_unittests.cc.

144 {
145 DisplayListBuilder builder;
146
147 DlPaint paint;
148 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
149 builder.DrawPaint(paint);
150
151 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
152 "Roboto-Medium.ttf",
153 {
154 .stroke = true,
155 .stroke_width = 4,
156 }));
157 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
158 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [123/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextWithLargePerspectiveTransform |
| ) |  |

Definition at line 548 of file aiks_dl_text_unittests.cc.

548 {
549 // Verifies that text scales are clamped to work around
550 // https://github.com/flutter/flutter/issues/136112 .
551
552 DisplayListBuilder builder;
553
554 DlPaint save_paint;
555 builder.SaveLayer(std::nullopt, &save_paint);
556 builder.Transform(Matrix(2000, 0, 0, 0, //
557 0, 2000, 0, 0, //
558 0, 0, -1, 9000, //
559 0, 0, -1, 7000 //
560 ));
561
562 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
563 "Roboto-Regular.ttf"));
564 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
565 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [124/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextWithPerspectiveTransformInSublist |
| ) |  |

Definition at line 567 of file aiks_dl_text_unittests.cc.

567 {
568 DisplayListBuilder text_builder;
569 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
570 "Roboto-Regular.ttf"));
571 auto text_display_list = text_builder.Build();
572
573 DisplayListBuilder builder;
574
575 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
576 0.0, 2.0, 0.0, 0.0, //
577 0.0, 0.0, 1.0, 0.0, //
578 0.0, 0.002, 0.0, 1.0);
579
580 DlPaint save_paint;
581 DlRect window_bounds =
582 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
583 builder.SaveLayer(window_bounds, &save_paint);
584 builder.Transform(matrix);
585 builder.DrawDisplayList(text_display_list, 1.0f);
586 builder.Restore();
587
588 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
589 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [125/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderThickCurvedStrokes |
| ) |  |

Definition at line 83 of file aiks_dl_path_unittests.cc.

83 {
84 DisplayListBuilder builder;
85 DlPaint paint;
86 paint.setColor(DlColor::kRed());
87 paint.setStrokeWidth(100);
88 paint.setDrawStyle(DlDrawStyle::kStroke);
89
90 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
91
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

## ◆ TEST_P() [126/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderThinCurvedStrokes |
| ) |  |

Definition at line 95 of file aiks_dl_path_unittests.cc.

95 {
96 DisplayListBuilder builder;
97 DlPaint paint;
98 paint.setColor(DlColor::kRed());
99 paint.setStrokeWidth(0.01);
100 paint.setDrawStyle(DlDrawStyle::kStroke);
101
102 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
103
104 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
105 }

## ◆ TEST_P() [127/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTightConicPath |
| ) |  |

Definition at line 346 of file aiks_dl_path_unittests.cc.

346 {
347 DisplayListBuilder builder;
348 builder.Scale(GetContentScale().x, GetContentScale().y);
349
350 DlPaint paint;
351 paint.setColor(DlColor::kRed());
352 paint.setDrawStyle(DlDrawStyle::kFill);
353
354 DlPaint reference_paint;
355 reference_paint.setColor(DlColor::kGreen());
356 reference_paint.setDrawStyle(DlDrawStyle::kFill);
357
358 DlPathBuilder path_builder;
359
360 path_builder.MoveTo(DlPoint(100, 100));
361 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 100), 5.0f);
362
363 DlPathBuilder reference_builder;
364 PathTessellator::Conic component{DlPoint(300, 100), //
365 DlPoint(350, 450), //
366 DlPoint(400, 100), //
367 5.0f};
368 reference_builder.MoveTo(component.p1);
369 constexpr int N = 100;
370 for (int i = 1; i < N; i++) {
371 reference_builder.LineTo(component.Solve(static_cast<Scalar>(i) / N));
372 }
373 reference_builder.LineTo(component.p2);
374
375 DlPaint line_paint;
376 line_paint.setColor(DlColor::kYellow());
377 line_paint.setDrawStyle(DlDrawStyle::kStroke);
378 line_paint.setStrokeWidth(1.0f);
379
380 // Draw some lines to provide a spacial reference for the curvature of
381 // the tips of the direct rendering and the manually tessellated versions.
382 builder.DrawLine(DlPoint(145, 100), DlPoint(145, 450), line_paint);
383 builder.DrawLine(DlPoint(155, 100), DlPoint(155, 450), line_paint);
384 builder.DrawLine(DlPoint(345, 100), DlPoint(345, 450), line_paint);
385 builder.DrawLine(DlPoint(355, 100), DlPoint(355, 450), line_paint);
386 builder.DrawLine(DlPoint(100, 392.5f), DlPoint(400, 392.5f), line_paint);
387
388 // Draw the two paths (direct and manually tessellated) on top of the lines.
389 builder.DrawPath(path_builder.TakePath(), paint);
390 builder.DrawPath(reference_builder.TakePath(), reference_paint);
391
392 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
393 }

References x.

## ◆ TEST_P() [128/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureClamp |
| ) |  |

Definition at line 256 of file aiks_dl_basic_unittests.cc.

256 {
257 CanRenderTiledTexture(this, DlTileMode::kClamp);
258 }

## ◆ TEST_P() [129/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureClampWithTranslate |
| ) |  |

Definition at line 272 of file aiks_dl_basic_unittests.cc.

272 {
273 CanRenderTiledTexture(this, DlTileMode::kClamp,
274 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
275 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [130/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureDecal |
| ) |  |

Definition at line 268 of file aiks_dl_basic_unittests.cc.

268 {
269 CanRenderTiledTexture(this, DlTileMode::kDecal);
270 }

## ◆ TEST_P() [131/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureMirror |
| ) |  |

Definition at line 264 of file aiks_dl_basic_unittests.cc.

264 {
265 CanRenderTiledTexture(this, DlTileMode::kMirror);
266 }

## ◆ TEST_P() [132/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureRepeat |
| ) |  |

Definition at line 260 of file aiks_dl_basic_unittests.cc.

260 {
261 CanRenderTiledTexture(this, DlTileMode::kRepeat);
262 }

## ◆ TEST_P() [133/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTinyOverlappingSubpasses |
| ) |  |

This is a regression check for https://github.com/flutter/engine/pull/41129 The entire screen is green if successful. If failing, no frames will render, or the entire screen will be transparent black.

Definition at line 358 of file aiks_dl_unittests.cc.

358 {
359 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
360
361 DlPaint paint;
362 paint.setColor(DlColor::kRed());
363 builder.DrawPaint(paint);
364
365 // Draw two overlapping subpixel circles.
366 builder.SaveLayer(std::nullopt);
367
368 DlPaint yellow_paint;
369 yellow_paint.setColor(DlColor::kYellow());
370 builder.DrawCircle(DlPoint(100, 100), 0.1, yellow_paint);
371 builder.Restore();
372 builder.SaveLayer(std::nullopt);
373 builder.DrawCircle(DlPoint(100, 100), 0.1, yellow_paint);
374 builder.Restore();
375
376 DlPaint draw_paint;
377 draw_paint.setColor(DlColor::kGreen());
378 builder.DrawPaint(draw_paint);
379
380 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
381 }

## ◆ TEST_P() [134/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderWideStrokedRectPathWithoutOverlap |
| ) |  |

Definition at line 98 of file aiks_dl_basic_unittests.cc.

98 {
99 ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
100 GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
101 const DlPaint& paint) {
102 // Draw the rect as a Path
103 builder.DrawPath(DlPath::MakeRect(rect), paint);
104 })));
105 }

## ◆ TEST_P() [135/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderWideStrokedRectWithoutOverlap |
| ) |  |

Definition at line 89 of file aiks_dl_basic_unittests.cc.

89 {
90 ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
91 GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
92 const DlPaint& paint) {
93 // Draw the rect directly
94 builder.DrawRect(rect, paint);
95 })));
96 }

## ◆ TEST_P() [136/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderWithContiguousClipRestores |
| ) |  |

Definition at line 74 of file aiks_dl_clip_unittests.cc.

74 {
75 DisplayListBuilder builder;
76
77 // Cover the whole canvas with red.
78 DlPaint paint;
79 paint.setColor(DlColor::kRed());
80 builder.DrawPaint(paint);
81
82 builder.Save();
83
84 // Append two clips, the second resulting in empty coverage.
85 builder.ClipRect(DlRect::MakeXYWH(100, 100, 100, 100));
86 builder.ClipRect(DlRect::MakeXYWH(300, 300, 100, 100));
87
88 // Restore to no clips.
89 builder.Restore();
90
91 // Replace the whole canvas with green.
92 paint.setColor(DlColor::kGreen());
93 builder.DrawPaint(paint);
94
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

## ◆ TEST_P() [137/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanSaveLayerStandalone |
| ) |  |

Definition at line 399 of file aiks_dl_basic_unittests.cc.

399 {
400 DisplayListBuilder builder;
401
402 DlPaint red;
403 red.setColor(DlColor::kRed());
404
405 DlPaint alpha;
406 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
407
408 builder.SaveLayer(std::nullopt, &alpha);
409
410 builder.DrawCircle(DlPoint(125, 125), 125, red);
411
412 builder.Restore();
413
414 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
415 }

## ◆ TEST_P() [138/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCanPushPopCTM |
| ) |  |

Definition at line 113 of file canvas_unittests.cc.

113 {
114 ContentContext context(GetContext(), nullptr);
115 auto canvas = CreateTestCanvas(context);
116
117 ASSERT_EQ(canvas->GetSaveCount(), 1u);
118 ASSERT_EQ(canvas->Restore(), false);
119
120 canvas->Translate(Size{100, 100});
121 canvas->Save(10);
122 ASSERT_EQ(canvas->GetSaveCount(), 2u);
123 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
124 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
125 ASSERT_TRUE(canvas->Restore());
126 ASSERT_EQ(canvas->GetSaveCount(), 1u);
127 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
128 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
129 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [139/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCTMCanBeUpdated |
| ) |  |

Definition at line 131 of file canvas_unittests.cc.

131 {
132 ContentContext context(GetContext(), nullptr);
133 auto canvas = CreateTestCanvas(context);
134
135 Matrix identity;
136 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
137 canvas->Translate(Size{100, 100});
138 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
139 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
140 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [140/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearBlend |
| ) |  |

Definition at line 485 of file aiks_dl_blend_unittests.cc.

485 {
486 DisplayListBuilder builder;
487
488 DlPaint blue;
489 blue.setColor(DlColor::kBlue());
490 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), blue);
491
492 DlPaint clear;
493 clear.setBlendMode(DlBlendMode::kClear);
494
495 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
496
497 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
498 }

## ◆ TEST_P() [141/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearBlendWithBlur |
| ) |  |

Definition at line 516 of file aiks_dl_blur_unittests.cc.

516 {
517 DisplayListBuilder builder;
518 DlPaint paint;
519 paint.setColor(DlColor::kBlue());
520 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
521
522 DlPaint clear;
523 clear.setBlendMode(DlBlendMode::kClear);
524 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
525
526 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
527
528 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
529 }

## ◆ TEST_P() [142/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearColorOptimizationWhenSubpassIsBiggerThanParentPass |
| ) |  |

Definition at line 1741 of file aiks_dl_basic_unittests.cc.

1741 {
1742 SetWindowSize({400, 400});
1743 DisplayListBuilder builder;
1744
1745 builder.Scale(GetContentScale().x, GetContentScale().y);
1746
1747 DlPaint paint;
1748 paint.setColor(DlColor::kRed());
1749 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1750
1751 paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1752 DlImageSampling::kLinear));
1753 builder.SaveLayer(std::nullopt, &paint);
1754 // Draw a rectangle that would fully cover the parent pass size, but not
1755 // the subpass that it is rendered in.
1756 paint.setColor(DlColor::kGreen());
1757 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1758 // Draw a bigger rectangle to force the subpass to be bigger.
1759
1760 paint.setColor(DlColor::kRed());
1761 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1762 builder.Restore();
1763
1764 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1765 }

References x.

## ◆ TEST_P() [143/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBackdropFilterWithShader |
| ) |  |

Definition at line 417 of file aiks_dl_runtime_effect_unittests.cc.

417 {
418 struct FragUniforms {
419 Vector2 uSize;
420 } frag_uniforms = {.uSize = Vector2(400, 400)};
421 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
422 uniform_data->resize(sizeof(FragUniforms));
423 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
424
425 auto runtime_stages_result =
426 OpenAssetAsRuntimeStage("runtime_stage_border.frag.iplr");
427 ABSL_ASSERT_OK(runtime_stages_result);
428 std::shared_ptr<RuntimeStage> runtime_stage =
429 runtime_stages_result
430 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
431 ASSERT_TRUE(runtime_stage);
432 ASSERT_TRUE(runtime_stage->IsDirty());
433
434 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
435 nullptr,
436 };
437
438 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
439 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
440 uniform_data);
441
442 DisplayListBuilder builder;
443
444 // Draw a background so the backdrop filter has something to affect
445 DlPaint background_paint;
446 background_paint.setColor(DlColor::kWhite());
447 builder.DrawPaint(background_paint);
448
449 // Draw some pattern to verify the filter effect
450 DlPaint pattern_paint;
451 pattern_paint.setColor(DlColor::kRed());
452 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), pattern_paint);
453 pattern_paint.setColor(DlColor::kBlue());
454 builder.DrawRect(DlRect::MakeXYWH(200, 200, 200, 200), pattern_paint);
455
456 builder.Save();
457
458 // Replicate the clip rect (inset by 66)
459 // Assuming a 400x400 screen, inset 66 gives roughly 66, 66, 268, 268
460 builder.ClipRect(DlRect::MakeXYWH(66, 66, 268, 268));
461
462 DlPaint save_paint;
463 // The Flutter code uses a backdrop filter layer.
464 // In DisplayList, this corresponds to SaveLayer with a backdrop filter.
465 builder.SaveLayer(std::nullopt, &save_paint, runtime_filter.get());
466
467 // The child was empty in the Flutter example, so we don't draw anything
468 // inside the SaveLayer
469
470 builder.Restore(); // Restore SaveLayer
471 builder.Restore(); // Restore Save (Clip)
472
473 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
474 }

References flutter::DlRuntimeEffectImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [144/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectly |
| ) |  |

Definition at line 499 of file aiks_dl_blur_unittests.cc.

499 {
500 DisplayListBuilder builder;
501 builder.Translate(0, -400);
502 DlPaint paint;
503
504 Sigma sigma = Radius{120 * 3};
505 paint.setMaskFilter(
506 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
507 paint.setColor(DlColor::kRed());
508
509 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
510 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
511 builder.DrawPath(path, paint);
512
513 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
514 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [145/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectlyInteractive |
| ) |  |

Definition at line 475 of file aiks_dl_blur_unittests.cc.

475 {
476 auto callback = [&]() -> sk_sp<DisplayList> {
477 static PlaygroundPoint playground_point(Point(400, 400), 20,
478 Color::Green());
479 auto point = DrawPlaygroundPoint(playground_point);
480
481 DisplayListBuilder builder;
482 auto location = point - Point(400, 400);
483 builder.Translate(location.x, location.y);
484
485 DlPaint paint;
486 Sigma sigma = Radius{120 * 3};
487 paint.setMaskFilter(
488 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
489 paint.setColor(DlColor::kRed());
490
491 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
492 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
493 builder.DrawPath(path, paint);
494 return builder.Build();
495 };
496 ASSERT_TRUE(OpenPlaygroundHere(callback));
497 }
location
uint32_t location
Definition: compiler_unittests.cc:129
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:11

References impeller::DrawPlaygroundPoint(), impeller::Color::Green(), location, and impeller::Sigma::sigma.

## ◆ TEST_P() [146/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClipsUseCurrentTransform |
| ) |  |

Definition at line 98 of file aiks_dl_clip_unittests.cc.

98 {
99 std::array<DlColor, 5> colors = {DlColor::kWhite(), DlColor::kBlack(),
100 DlColor::kSkyBlue(), DlColor::kRed(),
101 DlColor::kYellow()};
102 DisplayListBuilder builder;
103 DlPaint paint;
104
105 builder.Translate(300, 300);
106 for (int i = 0; i < 15; i++) {
107 builder.Scale(0.8, 0.8);
108
109 paint.setColor(colors[i % colors.size()]);
110 builder.ClipPath(DlPath::MakeCircle(DlPoint(0, 0), 300));
111 builder.DrawRect(DlRect::MakeXYWH(-300, -300, 600, 600), paint);
112 }
113 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
114 }

## ◆ TEST_P() [147/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CollapsedDrawPaintInSubpass |
| ) |  |

Definition at line 41 of file aiks_dl_unittests.cc.

41 {
42 DisplayListBuilder builder;
43
44 DlPaint paint;
45 paint.setColor(DlColor::kYellow());
46 paint.setBlendMode(DlBlendMode::kSrc);
47 builder.DrawPaint(paint);
48
49 DlPaint save_paint;
50 save_paint.setBlendMode(DlBlendMode::kMultiply);
51 builder.SaveLayer(std::nullopt, &save_paint);
52
53 DlPaint draw_paint;
54 draw_paint.setColor(DlColor::kCornflowerBlue().modulateOpacity(0.75f));
55 builder.DrawPaint(draw_paint);
56
57 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
58 }

## ◆ TEST_P() [148/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CollapsedDrawPaintInSubpassBackdropFilter |
| ) |  |

Definition at line 60 of file aiks_dl_unittests.cc.

60 {
61 // Bug: https://github.com/flutter/flutter/issues/131576
62 DisplayListBuilder builder;
63
64 DlPaint paint;
65 paint.setColor(DlColor::kYellow());
66 paint.setBlendMode(DlBlendMode::kSrc);
67 builder.DrawPaint(paint);
68
69 auto filter = DlImageFilter::MakeBlur(20.0, 20.0, DlTileMode::kDecal);
70 builder.SaveLayer(std::nullopt, nullptr, filter.get());
71
72 DlPaint draw_paint;
73 draw_paint.setColor(DlColor::kCornflowerBlue());
74 builder.DrawPaint(draw_paint);
75
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77 }

## ◆ TEST_P() [149/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorFilterAdvancedBlend |
| ) |  |

Definition at line 250 of file aiks_dl_blend_unittests.cc.

250 {
251 bool has_color_filter = true;
252 auto callback = [&]() -> sk_sp<DisplayList> {
253 if (AiksTest::ImGuiBegin("Controls", nullptr,
254 ImGuiWindowFlags_AlwaysAutoResize)) {
255 ImGui::Checkbox("has color filter", &has_color_filter);
256 ImGui::End();
257 }
258
259 DisplayListBuilder builder;
260 builder.Scale(GetContentScale().x, GetContentScale().y);
261
262 auto src_image =
263 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
264 auto dst_image =
265 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
266
267 std::vector<DlBlendMode> blend_modes = {
268 DlBlendMode::kScreen, DlBlendMode::kOverlay,
269 DlBlendMode::kDarken, DlBlendMode::kLighten,
270 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
271 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
272 DlBlendMode::kDifference, DlBlendMode::kExclusion,
273 DlBlendMode::kMultiply, DlBlendMode::kHue,
274 DlBlendMode::kSaturation, DlBlendMode::kColor,
275 DlBlendMode::kLuminosity,
276 };
277
278 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
279 builder.Save();
280 builder.Translate((i % 5) * 200, (i / 5) * 200);
281 builder.Scale(0.4, 0.4);
282 {
283 DlPaint dstPaint;
284 builder.DrawImage(dst_image, DlPoint(0, 0),
285 DlImageSampling::kMipmapLinear, &dstPaint);
286 }
287 {
288 DlPaint srcPaint;
289 srcPaint.setBlendMode(blend_modes[i]);
290 if (has_color_filter) {
291 std::shared_ptr<const DlColorFilter> color_filter =
292 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
293 DlBlendMode::kSrcIn);
294 srcPaint.setColorFilter(color_filter);
295 }
296 builder.DrawImage(src_image, DlPoint(0, 0),
297 DlImageSampling::kMipmapLinear, &srcPaint);
298 }
299 builder.Restore();
300 }
301 return builder.Build();
302 };
303 ASSERT_TRUE(OpenPlaygroundHere(callback));
304 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [150/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorFilterAdvancedBlendNoFbFetch |
| ) |  |

Definition at line 309 of file aiks_dl_blend_unittests.cc.

309 {
310 if (GetParam() != PlaygroundBackend::kMetal) {
311 GTEST_SKIP()
312 << "This backend doesn't yet support setting device capabilities.";
313 }
314 if (!WillRenderSomething()) {
315 GTEST_SKIP() << "This test requires playgrounds.";
316 }
317
318 std::shared_ptr<const Capabilities> old_capabilities =
319 GetContext()->GetCapabilities();
320 auto mock_capabilities = std::make_shared<MockCapabilities>();
321 EXPECT_CALL(*mock_capabilities, SupportsFramebufferFetch())
322 .Times(::testing::AtLeast(1))
323 .WillRepeatedly(::testing::Return(false));
324 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
325 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
326 FLT_FORWARD(mock_capabilities, old_capabilities,
327 GetDefaultDepthStencilFormat);
328 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
329 FLT_FORWARD(mock_capabilities, old_capabilities,
330 SupportsImplicitResolvingMSAA);
331 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
332 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
333 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
334 FLT_FORWARD(mock_capabilities, old_capabilities,
335 SupportsTextureToTextureBlits);
336 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
337 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan);
338 FLT_FORWARD(mock_capabilities, old_capabilities,
339 SupportsDecalSamplerAddressMode);
340 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsPrimitiveRestart);
341 FLT_FORWARD(mock_capabilities, old_capabilities, GetMinimumUniformAlignment);
342 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
343
344 bool has_color_filter = true;
345 auto callback = [&]() -> sk_sp<DisplayList> {
346 if (AiksTest::ImGuiBegin("Controls", nullptr,
347 ImGuiWindowFlags_AlwaysAutoResize)) {
348 ImGui::Checkbox("has color filter", &has_color_filter);
349 ImGui::End();
350 }
351
352 DisplayListBuilder builder;
353 builder.Scale(GetContentScale().x, GetContentScale().y);
354
355 auto src_image =
356 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
357 auto dst_image =
358 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
359
360 std::vector<DlBlendMode> blend_modes = {
361 DlBlendMode::kScreen, DlBlendMode::kOverlay,
362 DlBlendMode::kDarken, DlBlendMode::kLighten,
363 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
364 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
365 DlBlendMode::kDifference, DlBlendMode::kExclusion,
366 DlBlendMode::kMultiply, DlBlendMode::kHue,
367 DlBlendMode::kSaturation, DlBlendMode::kColor,
368 DlBlendMode::kLuminosity,
369 };
370
371 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
372 builder.Save();
373 builder.Translate((i % 5) * 200, (i / 5) * 200);
374 builder.Scale(0.4, 0.4);
375 {
376 DlPaint dstPaint;
377 builder.DrawImage(dst_image, DlPoint(0, 0),
378 DlImageSampling::kMipmapLinear, &dstPaint);
379 }
380 {
381 DlPaint srcPaint;
382 srcPaint.setBlendMode(blend_modes[i]);
383 if (has_color_filter) {
384 std::shared_ptr<const DlColorFilter> color_filter =
385 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
386 DlBlendMode::kMultiply);
387 srcPaint.setColorFilter(color_filter);
388 }
389 builder.DrawImage(src_image, DlPoint(0, 0),
390 DlImageSampling::kMipmapLinear, &srcPaint);
391 }
392 builder.Restore();
393 }
394 return builder.Build();
395 };
396 ASSERT_TRUE(OpenPlaygroundHere(callback));
397 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::kMetal, impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [151/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorFilterBlend |
| ) |  |

Definition at line 198 of file aiks_dl_blend_unittests.cc.

198 {
199 bool has_color_filter = true;
200 auto callback = [&]() -> sk_sp<DisplayList> {
201 if (AiksTest::ImGuiBegin("Controls", nullptr,
202 ImGuiWindowFlags_AlwaysAutoResize)) {
203 ImGui::Checkbox("has color filter", &has_color_filter);
204 ImGui::End();
205 }
206
207 DisplayListBuilder builder;
208 builder.Scale(GetContentScale().x, GetContentScale().y);
209
210 auto src_image =
211 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
212 auto dst_image =
213 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
214
215 std::vector<DlBlendMode> blend_modes = {
216 DlBlendMode::kSrc, DlBlendMode::kSrcATop, DlBlendMode::kSrcOver,
217 DlBlendMode::kSrcIn, DlBlendMode::kSrcOut, DlBlendMode::kDst,
218 DlBlendMode::kDstATop, DlBlendMode::kDstOver, DlBlendMode::kDstIn,
219 DlBlendMode::kDstOut, DlBlendMode::kClear, DlBlendMode::kXor};
220
221 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
222 builder.Save();
223 builder.Translate((i % 5) * 200, (i / 5) * 200);
224 builder.Scale(0.4, 0.4);
225 {
226 DlPaint dstPaint;
227 builder.DrawImage(dst_image, DlPoint(0, 0),
228 DlImageSampling::kMipmapLinear, &dstPaint);
229 }
230 {
231 DlPaint srcPaint;
232 srcPaint.setBlendMode(blend_modes[i]);
233 if (has_color_filter) {
234 std::shared_ptr<const DlColorFilter> color_filter =
235 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
236 DlBlendMode::kSrcIn);
237 srcPaint.setColorFilter(color_filter);
238 }
239 builder.DrawImage(src_image, DlPoint(0, 0),
240 DlImageSampling::kMipmapLinear, &srcPaint);
241 }
242 builder.Restore();
243 }
244 return builder.Build();
245 };
246 ASSERT_TRUE(OpenPlaygroundHere(callback));
247 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [152/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorMatrixFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 79 of file aiks_dl_unittests.cc.

79 {
80 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
81 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
82
83 const float matrix[20] = {
84 -1.0, 0, 0, 1.0, 0, //
85 0, -1.0, 0, 1.0, 0, //
86 0, 0, -1.0, 1.0, 0, //
87 1.0, 1.0, 1.0, 1.0, 0 //
88 };
89 auto filter = DlColorFilter::MakeMatrix(matrix);
90
91 DlPaint paint;
92 paint.setColorFilter(filter);
93 builder.SaveLayer(std::nullopt, &paint);
94
95 builder.Translate(500, 300);
96 builder.Rotate(120); // 120 deg
97
98 DlPaint draw_paint;
99 draw_paint.setColor(DlColor::kBlue());
100 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), draw_paint);
101
102 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
103 }

## ◆ TEST_P() [153/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorWheel |
| ) |  |

color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 -> cyan domain: r >= 0 (because modulo used is non euclidean)

Definition at line 773 of file aiks_dl_blend_unittests.cc.

773 {
774 // Compare with https://fiddle.skia.org/c/@BlendModes
775
776 BlendModeSelection blend_modes = GetBlendModeSelection();
777
778 auto draw_color_wheel = [](DisplayListBuilder& builder) -> void {
779 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
780 /// cyan domain: r >= 0 (because modulo used is non euclidean)
781 auto color_wheel_sampler = [](Radians r) {
782 Scalar x = r.radians / k2Pi + 1;
783
784 // https://www.desmos.com/calculator/6nhjelyoaj
785 auto color_cycle = [](Scalar x) {
786 Scalar cycle = std::fmod(x, 6.0f);
787 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
788 };
789 return Color(color_cycle(6 * x + 1), //
790 color_cycle(6 * x - 1), //
791 color_cycle(6 * x - 3), //
792 1);
793 };
794
795 DlPaint paint;
796 paint.setBlendMode(DlBlendMode::kSrcOver);
797
798 // Draw a fancy color wheel for the backdrop.
799 // https://www.desmos.com/calculator/xw7kafthwd
800 const int max_dist = 900;
801 for (int i = 0; i <= 900; i++) {
802 Radians r(kPhi / k2Pi * i);
803 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
804 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
805
806 auto color = color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
807 paint.setColor(
808 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
809 DlPoint position = DlPoint(distance * std::sin(r.radians),
810 -distance * std::cos(r.radians));
811
812 builder.DrawCircle(position, 9 + normalized_distance * 3, paint);
813 }
814 };
815
816 auto callback = [&]() -> sk_sp<DisplayList> {
817 // UI state.
818 static bool cache_the_wheel = true;
819 static int current_blend_index = 3;
820 static float dst_alpha = 1;
821 static float src_alpha = 1;
822 static DlColor color0 = DlColor::kRed();
823 static DlColor color1 = DlColor::kGreen();
824 static DlColor color2 = DlColor::kBlue();
825
826 if (AiksTest::ImGuiBegin("Controls", nullptr,
827 ImGuiWindowFlags_AlwaysAutoResize)) {
828 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
829 ImGui::ListBox("Blending mode", &current_blend_index,
830 blend_modes.blend_mode_names.data(),
831 blend_modes.blend_mode_names.size());
832 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
833 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
834 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
835 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
836 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
837 ImGui::End();
838 }
839
840 DisplayListBuilder builder;
841
842 DlPaint paint;
843 paint.setColor(DlColor::kWhite().withAlpha(dst_alpha * 255));
844 paint.setBlendMode(DlBlendMode::kSrc);
845 builder.SaveLayer(std::nullopt, &paint);
846 {
847 DlPaint paint;
848 paint.setColor(DlColor::kWhite());
849 builder.DrawPaint(paint);
850
851 builder.SaveLayer(std::nullopt, nullptr);
852 builder.Scale(GetContentScale().x, GetContentScale().y);
853 builder.Translate(500, 400);
854 builder.Scale(3, 3);
855 draw_color_wheel(builder);
856 builder.Restore();
857 }
858 builder.Restore();
859
860 builder.Scale(GetContentScale().x, GetContentScale().y);
861 builder.Translate(500, 400);
862 builder.Scale(3, 3);
863
864 // Draw 3 circles to a subpass and blend it in.
865 DlPaint save_paint;
866 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
867 save_paint.setBlendMode(static_cast<DlBlendMode>(
868 blend_modes.blend_mode_values[current_blend_index]));
869 builder.SaveLayer(std::nullopt, &save_paint);
870 {
871 DlPaint paint;
872 paint.setBlendMode(DlBlendMode::kPlus);
873 const Scalar x = std::sin(k2Pi / 3);
874 const Scalar y = -std::cos(k2Pi / 3);
875 paint.setColor(color0);
876 builder.DrawCircle(DlPoint(-x * 45, y * 45), 65, paint);
877 paint.setColor(color1);
878 builder.DrawCircle(DlPoint(0, -45), 65, paint);
879 paint.setColor(color2);
880 builder.DrawCircle(DlPoint(x * 45, y * 45), 65, paint);
881 }
882 builder.Restore();
883
884 return builder.Build();
885 };
886
887 ASSERT_TRUE(OpenPlaygroundHere(callback));
888 }
impeller::saturated::distance
SI distance
Definition: saturated_math.h:57
impeller::kPhi
constexpr float kPhi
Definition: constants.h:54

References impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::saturated::distance, GetBlendModeSelection(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, impeller::kPhi, impeller::Radians::radians, and x.

## ◆ TEST_P() [154/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposeBackdropRuntimeOuterBlurInner |
| ) |  |

Definition at line 299 of file aiks_dl_runtime_effect_unittests.cc.

299 {
300 auto runtime_stages_result =
301 OpenAssetAsRuntimeStage("runtime_stage_filter_circle.frag.iplr");
302 ABSL_ASSERT_OK(runtime_stages_result);
303 std::shared_ptr<RuntimeStage> runtime_stage =
304 runtime_stages_result
305 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
306 ASSERT_TRUE(runtime_stage);
307 ASSERT_TRUE(runtime_stage->IsDirty());
308 Scalar sigma = 20.0;
309
310 auto callback = [&]() -> sk_sp<DisplayList> {
311 if (AiksTest::ImGuiBegin("Controls", nullptr,
312 ImGuiWindowFlags_AlwaysAutoResize)) {
313 ImGui::SliderFloat("sigma", &sigma, 0, 20);
314 ImGui::End();
315 }
316 DisplayListBuilder builder;
317 DlPaint background;
318 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
319 builder.DrawPaint(background);
320
321 auto blur_filter =
322 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
323
324 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
325 nullptr,
326 };
327 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
328 uniform_data->resize(sizeof(Vector2));
329
330 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
331 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
332 uniform_data);
333
334 auto backdrop_filter = DlImageFilter::MakeCompose(/*outer=*/runtime_filter,
335 /*inner=*/blur_filter);
336
337 DlPaint paint;
338 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
339 builder.DrawImage(image, DlPoint(100.0, 100.0),
340 DlImageSampling::kNearestNeighbor, &paint);
341
342 DlPaint save_paint;
343 save_paint.setBlendMode(DlBlendMode::kSrc);
344 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
345 builder.Restore();
346
347 DlPaint green;
348 green.setColor(DlColor::kGreen());
349 builder.DrawLine({100, 100}, {200, 100}, green);
350 builder.DrawLine({100, 100}, {100, 200}, green);
351
352 return builder.Build();
353 };
354
355 ASSERT_TRUE(OpenPlaygroundHere(callback));
356 }

References impeller::AiksPlayground::ImGuiBegin(), flutter::DlRuntimeEffectImpeller::Make(), impeller::DlImageImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [155/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposeBackdropRuntimeOuterBlurInnerSmallSigma |
| ) |  |

Definition at line 358 of file aiks_dl_runtime_effect_unittests.cc.

358 {
359 auto runtime_stages_result =
360 OpenAssetAsRuntimeStage("runtime_stage_filter_circle.frag.iplr");
361 ABSL_ASSERT_OK(runtime_stages_result);
362 std::shared_ptr<RuntimeStage> runtime_stage =
363 runtime_stages_result
364 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
365 ASSERT_TRUE(runtime_stage);
366 ASSERT_TRUE(runtime_stage->IsDirty());
367 Scalar sigma = 5.0;
368
369 auto callback = [&]() -> sk_sp<DisplayList> {
370 if (AiksTest::ImGuiBegin("Controls", nullptr,
371 ImGuiWindowFlags_AlwaysAutoResize)) {
372 ImGui::SliderFloat("sigma", &sigma, 0, 20);
373 ImGui::End();
374 }
375 DisplayListBuilder builder;
376 DlPaint background;
377 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
378 builder.DrawPaint(background);
379
380 auto blur_filter =
381 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
382
383 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
384 nullptr,
385 };
386 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
387 uniform_data->resize(sizeof(Vector2));
388
389 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
390 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
391 uniform_data);
392
393 auto backdrop_filter = DlImageFilter::MakeCompose(/*outer=*/runtime_filter,
394 /*inner=*/blur_filter);
395
396 DlPaint paint;
397 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
398 builder.DrawImage(image, DlPoint(100.0, 100.0),
399 DlImageSampling::kNearestNeighbor, &paint);
400
401 DlPaint save_paint;
402 save_paint.setBlendMode(DlBlendMode::kSrc);
403 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
404 builder.Restore();
405
406 DlPaint green;
407 green.setColor(DlColor::kGreen());
408 builder.DrawLine({100, 100}, {200, 100}, green);
409 builder.DrawLine({100, 100}, {100, 200}, green);
410
411 return builder.Build();
412 };
413
414 ASSERT_TRUE(OpenPlaygroundHere(callback));
415 }

References impeller::AiksPlayground::ImGuiBegin(), flutter::DlRuntimeEffectImpeller::Make(), impeller::DlImageImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [156/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposePaintBlurInner |
| ) |  |

Definition at line 450 of file aiks_dl_blur_unittests.cc.

450 {
451 DisplayListBuilder builder;
452
453 DlPaint background;
454 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
455 builder.DrawPaint(background);
456
457 DlPaint paint;
458 paint.setColor(DlColor::kGreen());
459 float matrix[] = {
460 0, 1, 0, 0, 0, //
461 1, 0, 0, 0, 0, //
462 0, 0, 1, 0, 0, //
463 0, 0, 0, 1, 0 //
464 };
465 std::shared_ptr<DlImageFilter> color_filter =
466 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
467 std::shared_ptr<DlImageFilter> blur =
468 DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal);
469 paint.setImageFilter(DlImageFilter::MakeCompose(color_filter, blur));
470 builder.DrawCircle(DlPoint(400, 400), 200, paint);
471
472 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
473 }

## ◆ TEST_P() [157/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposePaintBlurOuter |
| ) |  |

Definition at line 425 of file aiks_dl_blur_unittests.cc.

425 {
426 DisplayListBuilder builder;
427
428 DlPaint background;
429 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
430 builder.DrawPaint(background);
431
432 DlPaint paint;
433 paint.setColor(DlColor::kGreen());
434 float matrix[] = {
435 0, 1, 0, 0, 0, //
436 1, 0, 0, 0, 0, //
437 0, 0, 1, 0, 0, //
438 0, 0, 0, 1, 0 //
439 };
440 std::shared_ptr<DlImageFilter> color_filter =
441 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
442 std::shared_ptr<DlImageFilter> blur =
443 DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal);
444 paint.setImageFilter(DlImageFilter::MakeCompose(blur, color_filter));
445 builder.DrawCircle(DlPoint(400, 400), 200, paint);
446
447 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
448 }

## ◆ TEST_P() [158/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposePaintRuntimeInner |
| ) |  |

Definition at line 211 of file aiks_dl_runtime_effect_unittests.cc.

211 {
212 auto runtime_stages_result =
213 OpenAssetAsRuntimeStage("runtime_stage_filter_warp.frag.iplr");
214 ABSL_ASSERT_OK(runtime_stages_result);
215 std::shared_ptr<RuntimeStage> runtime_stage =
216 runtime_stages_result
217 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
218 ASSERT_TRUE(runtime_stage);
219 ASSERT_TRUE(runtime_stage->IsDirty());
220 Scalar xoffset = 50;
221 Scalar yoffset = 50;
222 Scalar xscale = 0.7;
223 Scalar yscale = 0.7;
224 bool compare = false;
225
226 auto callback = [&]() -> sk_sp<DisplayList> {
227 if (AiksTest::ImGuiBegin("Controls", nullptr,
228 ImGuiWindowFlags_AlwaysAutoResize)) {
229 ImGui::SliderFloat("xoffset", &xoffset, -50, 50);
230 ImGui::SliderFloat("yoffset", &yoffset, -50, 50);
231 ImGui::SliderFloat("xscale", &xscale, 0, 1);
232 ImGui::SliderFloat("yscale", &yscale, 0, 1);
233 ImGui::Checkbox("compare", &compare);
234 ImGui::End();
235 }
236 DisplayListBuilder builder;
237 DlPaint background;
238 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
239 builder.DrawPaint(background);
240
241 DlPaint paint;
242 paint.setColor(DlColor::kGreen());
243 float matrix[] = {
244 0, 1, 0, 0, 0, //
245 1, 0, 0, 0, 0, //
246 0, 0, 1, 0, 0, //
247 0, 0, 0, 1, 0 //
248 };
249 std::shared_ptr<DlImageFilter> color_filter =
250 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
251
252 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
253 nullptr,
254 };
255 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
256 uniform_data->resize(sizeof(Vector2));
257
258 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
259 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
260 uniform_data);
261
262 builder.Translate(xoffset, yoffset);
263 builder.Scale(xscale, yscale);
264
265 paint.setImageFilter(
266 DlImageFilter::MakeCompose(color_filter, runtime_filter));
267 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
268 builder.DrawImage(image, DlPoint(100.0, 100.0),
269 DlImageSampling::kNearestNeighbor, &paint);
270
271 if (compare) {
272 paint.setImageFilter(
273 DlImageFilter::MakeCompose(runtime_filter, color_filter));
274 builder.DrawImage(image, DlPoint(800.0, 100.0),
275 DlImageSampling::kNearestNeighbor, &paint);
276
277 paint.setImageFilter(runtime_filter);
278 builder.DrawImage(image, DlPoint(100.0, 800.0),
279 DlImageSampling::kNearestNeighbor, &paint);
280 }
281
282 DlPaint green;
283 green.setColor(DlColor::kGreen());
284 builder.DrawLine({100, 100}, {200, 100}, green);
285 builder.DrawLine({100, 100}, {100, 200}, green);
286 if (compare) {
287 builder.DrawLine({800, 100}, {900, 100}, green);
288 builder.DrawLine({800, 100}, {800, 200}, green);
289 builder.DrawLine({100, 800}, {200, 800}, green);
290 builder.DrawLine({100, 800}, {100, 900}, green);
291 }
292
293 return builder.Build();
294 };
295
296 ASSERT_TRUE(OpenPlaygroundHere(callback));
297 }

References impeller::AiksPlayground::ImGuiBegin(), flutter::DlRuntimeEffectImpeller::Make(), impeller::DlImageImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [159/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ComposePaintRuntimeOuter |
| ) |  |

Definition at line 158 of file aiks_dl_runtime_effect_unittests.cc.

158 {
159 DisplayListBuilder builder;
160 DlPaint background;
161 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
162 builder.DrawPaint(background);
163
164 DlPaint paint;
165 paint.setColor(DlColor::kGreen());
166 float matrix[] = {
167 0, 1, 0, 0, 0, //
168 1, 0, 0, 0, 0, //
169 0, 0, 1, 0, 0, //
170 0, 0, 0, 1, 0 //
171 };
172 std::shared_ptr<DlImageFilter> color_filter =
173 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
174
175 auto runtime_stages_result =
176 OpenAssetAsRuntimeStage("runtime_stage_filter_warp.frag.iplr");
177 ABSL_ASSERT_OK(runtime_stages_result);
178 std::shared_ptr<RuntimeStage> runtime_stage =
179 runtime_stages_result
180 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
181 ASSERT_TRUE(runtime_stage);
182 ASSERT_TRUE(runtime_stage->IsDirty());
183
184 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
185 nullptr,
186 };
187 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
188 uniform_data->resize(sizeof(Vector2));
189
190 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
191 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
192 uniform_data);
193
194 builder.Translate(50, 50);
195 builder.Scale(0.7, 0.7);
196
197 paint.setImageFilter(
198 DlImageFilter::MakeCompose(runtime_filter, color_filter));
199 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
200 builder.DrawImage(image, DlPoint(100.0, 100.0),
201 DlImageSampling::kNearestNeighbor, &paint);
202
203 DlPaint green;
204 green.setColor(DlColor::kGreen());
205 builder.DrawLine({100, 100}, {200, 100}, green);
206 builder.DrawLine({100, 100}, {100, 200}, green);
207
208 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
209 }

References flutter::DlRuntimeEffectImpeller::Make(), impeller::DlImageImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [160/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoordinateConversionsAreCorrect |
| ) |  |

Definition at line 1839 of file aiks_dl_basic_unittests.cc.

1839 {
1840 DisplayListBuilder builder;
1841
1842 // Render a texture directly.
1843 {
1844 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1845
1846 builder.Save();
1847 builder.Translate(100, 200);
1848 builder.Scale(0.5, 0.5);
1849 builder.DrawImage(image, DlPoint(100.0, 100.0),
1850 DlImageSampling::kNearestNeighbor);
1851 builder.Restore();
1852 }
1853
1854 // Render an offscreen rendered texture.
1855 {
1856 DlPaint alpha;
1857 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1858
1859 builder.SaveLayer(std::nullopt, &alpha);
1860
1861 DlPaint paint;
1862 paint.setColor(DlColor::kRed());
1863 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1864 paint.setColor(DlColor::kGreen());
1865 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1866 paint.setColor(DlColor::kBlue());
1867 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1868
1869 builder.Restore();
1870 }
1871
1872 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1873 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [161/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoverageOriginShouldBeAccountedForInSubpasses |
| ) |  |

Definition at line 2020 of file aiks_dl_basic_unittests.cc.

2020 {
2021 auto callback = [&]() -> sk_sp<DisplayList> {
2022 DisplayListBuilder builder;
2023 builder.Scale(GetContentScale().x, GetContentScale().y);
2024
2025 DlPaint alpha;
2026 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
2027
2028 auto current = Point{25, 25};
2029 const auto offset = Point{25, 25};
2030 const auto size = Size(100, 100);
2031
2032 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
2033 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
2034 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
2035 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
2036
2037 DlPaint stroke_paint;
2038 stroke_paint.setColor(DlColor::kYellow());
2039 stroke_paint.setStrokeWidth(5);
2040 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
2041 builder.DrawRect(bounds, stroke_paint);
2042
2043 builder.SaveLayer(bounds, &alpha);
2044
2045 DlPaint paint;
2046 paint.setColor(DlColor::kRed());
2047 builder.DrawRect(
2048 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
2049
2050 paint.setColor(DlColor::kGreen());
2051 current += offset;
2052 builder.DrawRect(
2053 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
2054
2055 paint.setColor(DlColor::kBlue());
2056 current += offset;
2057 builder.DrawRect(
2058 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
2059
2060 builder.Restore();
2061
2062 return builder.Build();
2063 };
2064
2065 ASSERT_TRUE(OpenPlaygroundHere(callback));
2066 }

References impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [162/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DepthValuesForLineMode |
| ) |  |

Definition at line 984 of file aiks_dl_unittests.cc.

984 {
985 // Ensures that the additional draws created by line/polygon mode all
986 // have the same depth values.
987 DisplayListBuilder builder;
988
989 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 100);
990
991 builder.DrawPath(path, DlPaint()
992 .setColor(DlColor::kRed())
993 .setDrawStyle(DlDrawStyle::kStroke)
994 .setStrokeWidth(5));
995 builder.Save();
996 builder.ClipPath(path);
997
998 std::vector<DlPoint> points = {
999 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1000 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1001 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1002 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1003 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1004
1005 builder.DrawPoints(DlPointMode::kLines, points.size(), points.data(),
1006 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1007 builder.Restore();
1008
1009 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1010 }

References points.

## ◆ TEST_P() [163/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DepthValuesForPolygonMode |
| ) |  |

Definition at line 1012 of file aiks_dl_unittests.cc.

1012 {
1013 // Ensures that the additional draws created by line/polygon mode all
1014 // have the same depth values.
1015 DisplayListBuilder builder;
1016
1017 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 100);
1018
1019 builder.DrawPath(path, DlPaint()
1020 .setColor(DlColor::kRed())
1021 .setDrawStyle(DlDrawStyle::kStroke)
1022 .setStrokeWidth(5));
1023 builder.Save();
1024 builder.ClipPath(path);
1025
1026 std::vector<DlPoint> points = {
1027 DlPoint::MakeXY(0, -200), DlPoint::MakeXY(400, 200),
1028 DlPoint::MakeXY(0, -100), DlPoint::MakeXY(400, 300),
1029 DlPoint::MakeXY(0, 0), DlPoint::MakeXY(400, 400),
1030 DlPoint::MakeXY(0, 100), DlPoint::MakeXY(400, 500),
1031 DlPoint::MakeXY(0, 150), DlPoint::MakeXY(400, 600)};
1032
1033 builder.DrawPoints(DlPointMode::kPolygon, points.size(), points.data(),
1034 DlPaint().setColor(DlColor::kBlue()).setStrokeWidth(10));
1035 builder.Restore();
1036
1037 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1038 }

References points.

## ◆ TEST_P() [164/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DestructiveBlendColorFilterFloodsClip |
| ) |  |

Definition at line 890 of file aiks_dl_blend_unittests.cc.

890 {
891 DisplayListBuilder builder;
892
893 DlPaint paint;
894 paint.setColor(DlColor::kBlue());
895 builder.DrawPaint(paint);
896
897 DlPaint save_paint;
898 save_paint.setColorFilter(
899 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kSrc));
900 builder.SaveLayer(std::nullopt, &save_paint);
901 builder.Restore();
902
903 // Should be solid red as the destructive color filter floods the clip.
904 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
905 }

## ◆ TEST_P() [165/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DifferenceClipsMustRenderIdenticallyAcrossBackends |
| ) |  |

Definition at line 633 of file aiks_dl_text_unittests.cc.

633 {
634 DisplayListBuilder builder;
635
636 DlPaint paint;
637 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
638 paint.setColor(clear_color);
639 builder.DrawPaint(paint);
640
641 DlMatrix identity = {
642 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
643 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
644 };
645 builder.Save();
646 builder.Transform(identity);
647
648 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
649 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
650 paint.setColor(white);
651 builder.DrawRect(frame, paint);
652
653 builder.Save();
654 builder.ClipRect(frame, DlClipOp::kIntersect);
655
656 DlMatrix rect_xform = {
657 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
658 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
659 };
660 builder.Save();
661 builder.Transform(rect_xform);
662
663 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
664 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
665 paint.setColor(bluish);
666 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
667 builder.DrawRoundRect(rrect, paint);
668
669 builder.Save();
670 builder.ClipRect(rect, DlClipOp::kIntersect);
671 builder.Restore();
672
673 builder.Restore();
674
675 DlMatrix path_xform = {
676 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
677 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
678 };
679 builder.Save();
680 builder.Transform(path_xform);
681
682 DlPathBuilder path_builder;
683 path_builder.MoveTo(DlPoint(87.5, 349.5));
684 path_builder.LineTo(DlPoint(25.0, 29.5));
685 path_builder.LineTo(DlPoint(150.0, 118.0));
686 path_builder.LineTo(DlPoint(25.0, 118.0));
687 path_builder.LineTo(DlPoint(150.0, 29.5));
688 path_builder.Close();
689 DlPath path = path_builder.TakePath();
690
691 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
692 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
693 paint.setColor(fill_color);
694 paint.setDrawStyle(DlDrawStyle::kFill);
695 builder.DrawPath(path, paint);
696
697 paint.setColor(stroke_color);
698 paint.setStrokeWidth(2.0);
699 paint.setDrawStyle(DlDrawStyle::kStroke);
700 builder.DrawPath(path, paint);
701
702 builder.Restore();
703 builder.Restore();
704 builder.Restore();
705
706 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
707 }

## ◆ TEST_P() [166/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists |
| ) |  |

Definition at line 871 of file aiks_dl_unittests.cc.

871 {
872 flutter::DisplayListBuilder sub_builder(true);
873 sub_builder.DrawRect(DlRect::MakeXYWH(0, 0, 50, 50),
874 flutter::DlPaint(flutter::DlColor::kRed()));
875 auto display_list = sub_builder.Build();
876
877 AiksContext context(GetContext(), nullptr);
878 RenderTarget render_target =
879 context.GetContentContext().GetRenderTargetCache()->CreateOffscreen(
880 *context.GetContext(), {2400, 1800}, 1);
881
882 DisplayListBuilder builder;
883
884 builder.Scale(2.0, 2.0);
885 builder.Translate(-93.0, 0.0);
886
887 // clang-format off
888 builder.TransformFullPerspective(
889 0.8, -0.2, -0.1, -0.0,
890 0.0, 1.0, 0.0, 0.0,
891 1.4, 1.3, 1.0, 0.0,
892 63.2, 65.3, 48.6, 1.1
893 );
894 // clang-format on
895 builder.Translate(35.0, 75.0);
896 builder.DrawDisplayList(display_list, 1.0f);
897
898 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
899 }

References impeller::AiksContext::GetContentContext(), impeller::AiksContext::GetContext(), and impeller::ContentContext::GetRenderTargetCache().

## ◆ TEST_P() [167/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DisplayListToTextureAllocationFailure |
| ) |  |

Definition at line 1112 of file aiks_dl_unittests.cc.

1112 {
1113 ScopedValidationDisable disable_validations;
1114 DisplayListBuilder builder;
1115
1116 AiksContext aiks_context(GetContext(), nullptr);
1117 // Use intentionally invalid dimensions that would trigger an allocation
1118 // failure.
1119 auto texture =
1120 DisplayListToTexture(builder.Build(), ISize{0, 0}, aiks_context);
1121
1122 EXPECT_EQ(texture, nullptr);
1123 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [168/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DisplayListToTextureWithMipGeneration |
| ) |  |

Definition at line 1125 of file aiks_dl_unittests.cc.

1125 {
1126 DisplayListBuilder builder;
1127
1128 std::shared_ptr<DlImageFilter> filter =
1129 DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
1130 builder.SaveLayer(std::nullopt, nullptr, filter.get());
1131 builder.Restore();
1132
1133 AiksContext aiks_context(GetContext(), nullptr);
1134 // Use intentionally invalid dimensions that would trigger an allocation
1135 // failure.
1136 auto texture =
1137 DisplayListToTexture(builder.Build(), ISize{10, 10}, aiks_context,
1138 /*reset_host_buffer=*/true, /*generate_mips=*/true);
1139
1140 EXPECT_FALSE(texture->NeedsMipmapGeneration());
1141 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [169/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DlAtlasGeometryBlend |
| ) |  |

Definition at line 200 of file aiks_dl_atlas_unittests.cc.

200 {
201 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
202
203 std::vector<DlColor> colors;
204 colors.reserve(texture_coordinates.size());
205 for (auto i = 0u; i < texture_coordinates.size(); i++) {
206 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
207 }
208 DlAtlasGeometry geom(
209 atlas->impeller_texture(), transforms.data(), texture_coordinates.data(),
210 colors.data(), transforms.size(), BlendMode::kSrcOver, {}, std::nullopt);
211
212 EXPECT_TRUE(geom.ShouldUseBlend());
213 EXPECT_FALSE(geom.ShouldSkip());
214
215 ContentContext context(GetContext(), nullptr);
216 auto vertex_buffer =
217 geom.CreateBlendVertexBuffer(context.GetTransientsDataBuffer());
218
219 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
220 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
221 }

References impeller::DlAtlasGeometry::CreateBlendVertexBuffer(), impeller::ContentContext::GetTransientsDataBuffer(), impeller::kNone, impeller::kSrcOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [170/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DlAtlasGeometryColorButNoBlend |
| ) |  |

Definition at line 223 of file aiks_dl_atlas_unittests.cc.

223 {
224 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
225
226 std::vector<DlColor> colors;
227 colors.reserve(texture_coordinates.size());
228 for (auto i = 0u; i < texture_coordinates.size(); i++) {
229 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
230 }
231 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
232 texture_coordinates.data(), colors.data(),
233 transforms.size(), BlendMode::kSrc, {}, std::nullopt);
234
235 // Src blend mode means that colors would be ignored, even if provided.
236 EXPECT_FALSE(geom.ShouldUseBlend());
237 EXPECT_FALSE(geom.ShouldSkip());
238 }

References impeller::kSrc, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [171/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DlAtlasGeometryNoBlendRenamed |
| ) |  |

Definition at line 182 of file aiks_dl_atlas_unittests.cc.

182 {
183 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
184
185 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
186 texture_coordinates.data(), nullptr, transforms.size(),
187 BlendMode::kSrcOver, {}, std::nullopt);
188
189 EXPECT_FALSE(geom.ShouldUseBlend());
190 EXPECT_FALSE(geom.ShouldSkip());
191
192 ContentContext context(GetContext(), nullptr);
193 auto vertex_buffer =
194 geom.CreateSimpleVertexBuffer(context.GetTransientsDataBuffer());
195
196 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
197 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
198 }

References impeller::DlAtlasGeometry::CreateSimpleVertexBuffer(), impeller::ContentContext::GetTransientsDataBuffer(), impeller::kNone, impeller::kSrcOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [172/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DlAtlasGeometrySkip |
| ) |  |

Definition at line 240 of file aiks_dl_atlas_unittests.cc.

240 {
241 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
242
243 std::vector<DlColor> colors;
244 colors.reserve(texture_coordinates.size());
245 for (auto i = 0u; i < texture_coordinates.size(); i++) {
246 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
247 }
248 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
249 texture_coordinates.data(), colors.data(),
250 transforms.size(), BlendMode::kClear, {}, std::nullopt);
251 EXPECT_TRUE(geom.ShouldSkip());
252 }

References impeller::kClear, and impeller::DlAtlasGeometry::ShouldSkip().

## ◆ TEST_P() [173/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAdvancedBlendPartlyOffscreen |
| ) |  |

Definition at line 142 of file aiks_dl_blend_unittests.cc.

142 {
143 DisplayListBuilder builder;
144
145 DlPaint draw_paint;
146 draw_paint.setColor(DlColor::kBlue());
147 builder.DrawPaint(draw_paint);
148 builder.Scale(2, 2);
149 builder.ClipRect(DlRect::MakeLTRB(0, 0, 200, 200));
150
151 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
152 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
153 std::vector<Scalar> stops = {0.0, 1.0};
154
155 DlPaint paint;
156 DlMatrix matrix = DlMatrix::MakeScale({0.3, 0.3, 1.0});
157 paint.setColorSource(DlColorSource::MakeLinear(
158 /*start_point=*/{0, 0}, //
159 /*end_point=*/{100, 100}, //
160 /*stop_count=*/colors.size(), //
161 /*colors=*/colors.data(), //
162 /*stops=*/stops.data(), //
163 /*tile_mode=*/DlTileMode::kRepeat, //
164 /*matrix=*/&matrix //
165 ));
166 paint.setBlendMode(DlBlendMode::kLighten);
167
168 builder.DrawCircle(DlPoint(100, 100), 100, paint);
169 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
170 }

## ◆ TEST_P() [174/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasAdvancedAndTransform |
| ) |  |

Definition at line 136 of file aiks_dl_atlas_unittests.cc.

136 {
137 DisplayListBuilder builder;
138 // Draws the image as four squares stiched together.
139 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
140
141 builder.Scale(0.25, 0.25);
142 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
143 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
144 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
145
146 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
147 }

## ◆ TEST_P() [175/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasNoColor |
| ) |  |

Definition at line 59 of file aiks_dl_atlas_unittests.cc.

59 {
60 DisplayListBuilder builder;
61 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
62
63 builder.Scale(GetContentScale().x, GetContentScale().y);
64 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
65 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
66 DlImageSampling::kNearestNeighbor, nullptr);
67
68 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
69 }

References x.

## ◆ TEST_P() [176/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasNoColorFullSize |
| ) |  |

Definition at line 119 of file aiks_dl_atlas_unittests.cc.

119 {
120 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
121 auto size = atlas->impeller_texture()->GetSize();
122 std::vector<DlRect> texture_coordinates = {
123 DlRect::MakeLTRB(0, 0, size.width, size.height)};
124 std::vector<RSTransform> transforms = {MakeTranslation(0, 0)};
125
126 DisplayListBuilder builder;
127 builder.Scale(GetContentScale().x, GetContentScale().y);
128 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
129 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
130 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
131
132 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
133 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [177/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasPlusWideGamut |
| ) |  |

Definition at line 165 of file aiks_dl_atlas_unittests.cc.

165 {
166 DisplayListBuilder builder;
167 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
168 PixelFormat::kB10G10R10A10XR);
169
170 // Draws the image as four squares stiched together.
171 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
172 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
173 DlColor::kBlue(), DlColor::kYellow()};
174
175 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
176 colors.data(), /*count=*/4, DlBlendMode::kPlus,
177 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
178
179 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
180 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [178/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithColorAdvanced |
| ) |  |

Definition at line 71 of file aiks_dl_atlas_unittests.cc.

71 {
72 DisplayListBuilder builder;
73 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
74
75 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
76 DlColor::kBlue(), DlColor::kYellow()};
77
78 builder.Scale(GetContentScale().x, GetContentScale().y);
79 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
80 colors.data(), /*count=*/4, DlBlendMode::kModulate,
81 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
82
83 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
84 }

References x.

## ◆ TEST_P() [179/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithColorAdvancedAndTransform |
| ) |  |

Definition at line 150 of file aiks_dl_atlas_unittests.cc.

150 {
151 DisplayListBuilder builder;
152 // Draws the image as four squares stiched together.
153 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
154 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
155 DlColor::kBlue(), DlColor::kYellow()};
156
157 builder.Scale(0.25, 0.25);
158 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
159 colors.data(), /*count=*/4, DlBlendMode::kModulate,
160 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }

## ◆ TEST_P() [180/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithColorBurn |
| ) |  |

Definition at line 319 of file aiks_dl_atlas_unittests.cc.

319 {
320 DisplayListBuilder builder;
321 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
322
323 std::vector<DlColor> colors = {DlColor::kDarkGrey(), DlColor::kBlack(),
324 DlColor::kLightGrey(), DlColor::kWhite()};
325
326 builder.Scale(GetContentScale().x, GetContentScale().y);
327 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
328 colors.data(), /*count=*/4, DlBlendMode::kColorBurn,
329 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
330
331 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
332 }

References x.

## ◆ TEST_P() [181/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithColorSimple |
| ) |  |

Definition at line 86 of file aiks_dl_atlas_unittests.cc.

86 {
87 DisplayListBuilder builder;
88 // Draws the image as four squares stiched together.
89 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
90
91 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
92 DlColor::kBlue(), DlColor::kYellow()};
93
94 builder.Scale(GetContentScale().x, GetContentScale().y);
95 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
96 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
97 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
98
99 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
100 }

References x.

## ◆ TEST_P() [182/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithOpacity |
| ) |  |

Definition at line 102 of file aiks_dl_atlas_unittests.cc.

102 {
103 DisplayListBuilder builder;
104 // Draws the image as four squares stiched together slightly
105 // opaque
106 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
107
108 DlPaint paint;
109 paint.setAlpha(128);
110 builder.Scale(GetContentScale().x, GetContentScale().y);
111 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
112 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
113 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
114 &paint);
115
116 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
117 }

References x.

## ◆ TEST_P() [183/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawImageRectSrcOutsideBounds |
| ) |  |

Definition at line 295 of file aiks_dl_basic_unittests.cc.

295 {
296 DisplayListBuilder builder;
297 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
298
299 // Use a source rect that is partially outside the bounds of the image.
300 auto source_rect = DlRect::MakeXYWH(
301 image->GetSize().width * 0.25f, image->GetSize().height * 0.4f,
302 image->GetSize().width, image->GetSize().height);
303
304 auto dest_rect = DlRect::MakeXYWH(100, 100, 600, 600);
305
306 DlPaint paint;
307 paint.setColor(DlColor::kMidGrey());
308 builder.DrawRect(dest_rect, paint);
309
310 builder.DrawImageRect(image, source_rect, dest_rect,
311 DlImageSampling::kNearestNeighbor);
312 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
313 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [184/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawImageRectWithBlendColorFilter |
| ) |  |

Definition at line 254 of file aiks_dl_atlas_unittests.cc.

254 {
255 sk_sp<DlImageImpeller> texture =
256 DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
257
258 DisplayListBuilder builder;
259 DlPaint paint = DlPaint().setColorFilter(DlColorFilter::MakeBlend(
260 DlColor::kRed().withAlphaF(0.4), DlBlendMode::kSrcOver));
261
262 DlMatrix filter_matrix = DlMatrix();
263 auto filter = flutter::DlMatrixImageFilter(filter_matrix,
264 flutter::DlImageSampling::kLinear);
265 DlPaint paint_with_filter = paint;
266 paint_with_filter.setImageFilter(&filter);
267
268 // Compare porter-duff blend modes.
269 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
270 // Uses image filter to disable atlas conversion.
271 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
272 DlRect::MakeLTRB(0, 0, 500, 500), {},
273 &paint_with_filter);
274
275 // Uses atlas conversion.
276 builder.Translate(600, 0);
277 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
278 DlRect::MakeLTRB(0, 0, 500, 500), {}, &paint);
279
280 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
281 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [185/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawImageRectWithMatrixColorFilter |
| ) |  |

Definition at line 283 of file aiks_dl_atlas_unittests.cc.

283 {
284 sk_sp<DlImageImpeller> texture =
285 DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
286
287 DisplayListBuilder builder;
288 static const constexpr ColorMatrix kColorInversion = {
289 .array = {
290 -1.0, 0, 0, 1.0, 0, //
291 0, -1.0, 0, 1.0, 0, //
292 0, 0, -1.0, 1.0, 0, //
293 1.0, 1.0, 1.0, 1.0, 0 //
294 }};
295 DlPaint paint = DlPaint().setColorFilter(
296 DlColorFilter::MakeMatrix(kColorInversion.array));
297
298 DlMatrix filter_matrix = DlMatrix();
299 auto filter = flutter::DlMatrixImageFilter(filter_matrix,
300 flutter::DlImageSampling::kLinear);
301 DlPaint paint_with_filter = paint;
302 paint_with_filter.setImageFilter(&filter);
303
304 // Compare inverting color matrix filter.
305 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
306 // Uses image filter to disable atlas conversion.
307 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
308 DlRect::MakeLTRB(0, 0, 500, 500), {},
309 &paint_with_filter);
310
311 // Uses atlas conversion.
312 builder.Translate(600, 0);
313 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
314 DlRect::MakeLTRB(0, 0, 500, 500), {}, &paint);
315
316 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
317 }
impeller::kColorInversion
static constexpr const ColorMatrix kColorInversion
A color matrix which inverts colors.
Definition: color_filter.h:16
impeller::ColorMatrix::array
Scalar array[20]
Definition: color.h:118

References impeller::ColorMatrix::array, impeller::kColorInversion, and impeller::DlImageImpeller::Make().

## ◆ TEST_P() [186/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawLinesRenderCorrectly |
| ) |  |

Definition at line 553 of file aiks_dl_path_unittests.cc.

553 {
554 DisplayListBuilder builder;
555 builder.Scale(GetContentScale().x, GetContentScale().y);
556
557 DlPaint paint;
558 paint.setColor(DlColor::kBlue());
559 paint.setStrokeWidth(10);
560
561 auto draw = [&builder](DlPaint& paint) {
562 for (auto cap :
563 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
564 paint.setStrokeCap(cap);
565 DlPoint origin = {100, 100};
566 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
567 for (int d = 15; d < 90; d += 15) {
568 Matrix m = Matrix::MakeRotationZ(Degrees(d));
569 Point origin = {100, 100};
570 Point p0 = {50, 0};
571 Point p1 = {150, 0};
572 auto a = origin + m * p0;
573 auto b = origin + m * p1;
574
575 builder.DrawLine(a, b, paint);
576 }
577 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
578 builder.DrawCircle(origin, 35, paint);
579
580 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
581
582 builder.Translate(250, 0);
583 }
584 builder.Translate(-750, 250);
585 };
586
587 std::vector<DlColor> colors = {
588 DlColor::ARGB(1, 0x1f / 255.0, 0.0, 0x5c / 255.0),
589 DlColor::ARGB(1, 0x5b / 255.0, 0.0, 0x60 / 255.0),
590 DlColor::ARGB(1, 0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0),
591 DlColor::ARGB(1, 0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0),
592 DlColor::ARGB(1, 0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0),
593 DlColor::ARGB(1, 0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0),
594 DlColor::ARGB(1, 0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0)};
595 std::vector<Scalar> stops = {
596 0.0,
597 (1.0 / 6.0) * 1,
598 (1.0 / 6.0) * 2,
599 (1.0 / 6.0) * 3,
600 (1.0 / 6.0) * 4,
601 (1.0 / 6.0) * 5,
602 1.0,
603 };
604
605 auto texture = DlImageImpeller::Make(
606 CreateTextureForFixture("airplane.jpg",
607 /*enable_mipmapping=*/true));
608
609 draw(paint);
610
611 paint.setColorSource(DlColorSource::MakeRadial({100, 100}, 200, stops.size(),
612 colors.data(), stops.data(),
613 DlTileMode::kMirror));
614 draw(paint);
615
616 DlMatrix matrix = DlMatrix::MakeTranslation({-150, 75});
617 paint.setColorSource(DlColorSource::MakeImage(
618 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
619 DlImageSampling::kMipmapLinear, &matrix));
620 draw(paint);
621
622 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
623 }

References impeller::saturated::b, impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationZ(), p1, and x.

## ◆ TEST_P() [187/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawOpacityPeephole |
| ) |  |

Definition at line 18 of file aiks_dl_opacity_unittests.cc.

18 {
19 DisplayListBuilder builder;
20
21 DlPaint green;
22 green.setColor(DlColor::kGreen().modulateOpacity(0.5));
23
24 DlPaint alpha;
25 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
26
27 builder.SaveLayer(std::nullopt, &alpha);
28 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), green);
29 builder.Restore();
30
31 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
32 }

## ◆ TEST_P() [188/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintTransformsBounds |
| ) |  |

Definition at line 78 of file aiks_dl_runtime_effect_unittests.cc.

78 {
79 struct FragUniforms {
80 Size size;
81 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
82 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
83 uniform_data->resize(sizeof(FragUniforms));
84 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
85
86 DlPaint paint;
87 auto effect = MakeRuntimeEffect(this, "gradient.frag.iplr", uniform_data);
88 ABSL_ASSERT_OK(effect);
89 paint.setColorSource(effect.value());
90
91 DisplayListBuilder builder;
92 builder.Save();
93 builder.Scale(GetContentScale().x, GetContentScale().y);
94 builder.DrawPaint(paint);
95 builder.Restore();
96
97 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
98 }

References impeller::TSize< Scalar >::MakeWH(), and x.

## ◆ TEST_P() [189/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintWithAdvancedBlendOverFilter |
| ) |  |

Definition at line 125 of file aiks_dl_blend_unittests.cc.

125 {
126 DlPaint paint;
127 paint.setColor(DlColor::kBlack());
128 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 60));
129
130 DisplayListBuilder builder;
131 paint.setColor(DlColor::kWhite());
132 builder.DrawPaint(paint);
133 paint.setColor(DlColor::kBlack());
134 builder.DrawCircle(DlPoint(300, 300), 200, paint);
135 paint.setColor(DlColor::kGreen());
136 paint.setBlendMode(DlBlendMode::kScreen);
137 builder.DrawPaint(paint);
138
139 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
140 }

## ◆ TEST_P() [190/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectStrokesRenderCorrectly |
| ) |  |

Definition at line 784 of file aiks_dl_path_unittests.cc.

784 {
785 DisplayListBuilder builder;
786 DlPaint paint;
787 paint.setColor(DlColor::kRed());
788 paint.setDrawStyle(DlDrawStyle::kStroke);
789 paint.setStrokeWidth(10);
790
791 builder.Translate(100, 100);
792 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
793
794 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
795 }

## ◆ TEST_P() [191/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectStrokesWithBevelJoinRenderCorrectly |
| ) |  |

Definition at line 797 of file aiks_dl_path_unittests.cc.

797 {
798 DisplayListBuilder builder;
799 DlPaint paint;
800 paint.setColor(DlColor::kRed());
801 paint.setDrawStyle(DlDrawStyle::kStroke);
802 paint.setStrokeWidth(10);
803 paint.setStrokeJoin(DlStrokeJoin::kBevel);
804
805 builder.Translate(100, 100);
806 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
807
808 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
809 }

## ◆ TEST_P() [192/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveNoSaveLayer |
| ) |  |

Definition at line 509 of file aiks_dl_text_unittests.cc.

509 {
510 DisplayListBuilder builder;
511
512 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
513 0.0, 1.0, 0.0, 0.0, //
514 0.0, 0.0, 1.0, 0.01, //
515 0.0, 0.0, 0.0, 1.0) * //
516 Matrix::MakeRotationY({Degrees{10}});
517
518 builder.Transform(matrix);
519
520 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
521 "Roboto-Regular.ttf"));
522 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
523 }

References RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [193/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveSaveLayer |
| ) |  |

Definition at line 525 of file aiks_dl_text_unittests.cc.

525 {
526 DisplayListBuilder builder;
527
528 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
529 0.0, 1.0, 0.0, 0.0, //
530 0.0, 0.0, 1.0, 0.01, //
531 0.0, 0.0, 0.0, 1.0) * //
532 Matrix::MakeRotationY({Degrees{10}});
533
534 DlPaint save_paint;
535 DlRect window_bounds =
536 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
537 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
538 builder.SaveLayer(window_bounds, &save_paint);
539 builder.Transform(matrix);
540
541 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
542 "Roboto-Regular.ttf"));
543
544 builder.Restore();
545 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
546 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [194/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseCircle |
| ) |  |

Definition at line 429 of file aiks_dl_shadow_unittests.cc.

429 {
430 DisplayListBuilder builder;
431 builder.Clear(DlColor::kWhite());
432 builder.Scale(GetContentScale().x, GetContentScale().y);
433 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
434 Scalar elevation = 30.0f;
435
436 // A weight of sqrt(2) is how you really perform conic circular sections,
437 // but by tweaking it slightly the path will not be recognized as an oval
438 // and accelerated.
439 constexpr Scalar kWeight = kSqrt2Over2 - 0.0005f;
440
441 DlPathBuilder path_builder;
442 path_builder.MoveTo(DlPoint(200, 100));
443 path_builder.ConicCurveTo(DlPoint(300, 100), DlPoint(300, 200), kWeight);
444 path_builder.ConicCurveTo(DlPoint(300, 300), DlPoint(200, 300), kWeight);
445 path_builder.ConicCurveTo(DlPoint(100, 300), DlPoint(100, 200), kWeight);
446 path_builder.ConicCurveTo(DlPoint(100, 100), DlPoint(200, 100), kWeight);
447 path_builder.Close();
448 DlPath path = path_builder.TakePath();
449
450 // Path must be convex, but unrecognizable as a simple shape.
451 ASSERT_TRUE(path.IsConvex());
452 ASSERT_FALSE(path.IsRect());
453 ASSERT_FALSE(path.IsOval());
454 ASSERT_FALSE(path.IsRoundRect());
455
456 const DlPath simple_path = DlPath::MakeCircle(DlPoint(200, 200), 100);
457 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
458
459 auto dl = builder.Build();
460 ASSERT_TRUE(OpenPlaygroundHere(dl));
461 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [195/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseConic |
| ) |  |

Definition at line 715 of file aiks_dl_shadow_unittests.cc.

715 {
716 DisplayListBuilder builder;
717 builder.Clear(DlColor::kWhite());
718 builder.Scale(GetContentScale().x, GetContentScale().y);
719 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
720 Scalar elevation = 30.0f;
721
722 DlPathBuilder path_builder;
723 path_builder.MoveTo(DlPoint(200, 100));
724 path_builder.ConicCurveTo(DlPoint(300, 100), DlPoint(300, 200), 0.4f);
725 path_builder.ConicCurveTo(DlPoint(300, 300), DlPoint(200, 300), 0.4f);
726 path_builder.ConicCurveTo(DlPoint(100, 300), DlPoint(100, 200), 0.4f);
727 path_builder.ConicCurveTo(DlPoint(100, 100), DlPoint(200, 100), 0.4f);
728 path_builder.Close();
729 DlPath path = path_builder.TakePath();
730
731 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
732
733 auto dl = builder.Build();
734 ASSERT_TRUE(OpenPlaygroundHere(dl));
735 }

References x.

## ◆ TEST_P() [196/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseCubic |
| ) |  |

Definition at line 759 of file aiks_dl_shadow_unittests.cc.

759 {
760 DisplayListBuilder builder;
761 builder.Clear(DlColor::kWhite());
762 builder.Scale(GetContentScale().x, GetContentScale().y);
763 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
764 Scalar elevation = 30.0f;
765
766 DlPathBuilder path_builder;
767 path_builder.MoveTo(DlPoint(200, 100));
768 path_builder.CubicCurveTo(DlPoint(280, 100), DlPoint(300, 120),
769 DlPoint(300, 200));
770 path_builder.CubicCurveTo(DlPoint(300, 280), DlPoint(280, 300),
771 DlPoint(200, 300));
772 path_builder.CubicCurveTo(DlPoint(120, 300), DlPoint(100, 280),
773 DlPoint(100, 200));
774 path_builder.CubicCurveTo(DlPoint(100, 120), DlPoint(120, 100),
775 DlPoint(200, 100));
776 path_builder.Close();
777 DlPath path = path_builder.TakePath();
778
779 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
780
781 auto dl = builder.Build();
782 ASSERT_TRUE(OpenPlaygroundHere(dl));
783 }

References x.

## ◆ TEST_P() [197/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseMultiRadiiRoundRect |
| ) |  |

Definition at line 615 of file aiks_dl_shadow_unittests.cc.

615 {
616 DisplayListBuilder builder;
617 builder.Clear(DlColor::kWhite());
618 builder.Scale(GetContentScale().x, GetContentScale().y);
619 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
620 Scalar elevation = 30.0f;
621
622 DlRoundingRadii radii = DlRoundingRadii{
623 .top_left = {80, 60},
624 .top_right = {20, 25},
625 .bottom_left = {60, 80},
626 .bottom_right = {25, 20},
627 };
628 DlPath path = MakeAlmostRoundRectPath(DlRect::MakeLTRB(100, 100, 300, 300),
629 radii, true);
630
631 // Path must be convex, but unrecognizable as a simple shape.
632 ASSERT_TRUE(path.IsConvex());
633 ASSERT_FALSE(path.IsRect());
634 ASSERT_FALSE(path.IsOval());
635 ASSERT_FALSE(path.IsRoundRect());
636
637 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
638
639 auto dl = builder.Build();
640 ASSERT_TRUE(OpenPlaygroundHere(dl));
641 }

References x.

## ◆ TEST_P() [198/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseOctagon |
| ) |  |

Definition at line 811 of file aiks_dl_shadow_unittests.cc.

811 {
812 DisplayListBuilder builder;
813 builder.Clear(DlColor::kWhite());
814 builder.Scale(GetContentScale().x, GetContentScale().y);
815 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
816 Scalar elevation = 30.0f;
817
818 DlPathBuilder path_builder;
819 path_builder.MoveTo(DlPoint(100, 125));
820 path_builder.LineTo(DlPoint(125, 100));
821 path_builder.LineTo(DlPoint(275, 100));
822 path_builder.LineTo(DlPoint(300, 125));
823 path_builder.LineTo(DlPoint(300, 275));
824 path_builder.LineTo(DlPoint(275, 300));
825 path_builder.LineTo(DlPoint(125, 300));
826 path_builder.LineTo(DlPoint(100, 275));
827 path_builder.Close();
828 DlPath path = path_builder.TakePath();
829
830 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
831
832 auto dl = builder.Build();
833 ASSERT_TRUE(OpenPlaygroundHere(dl));
834 }

References x.

## ◆ TEST_P() [199/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseOval |
| ) |  |

Definition at line 497 of file aiks_dl_shadow_unittests.cc.

497 {
498 DisplayListBuilder builder;
499 builder.Clear(DlColor::kWhite());
500 builder.Scale(GetContentScale().x, GetContentScale().y);
501 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
502 Scalar elevation = 30.0f;
503
504 // A weight of sqrt(2) is how you really perform conic circular sections,
505 // but by tweaking it slightly the path will not be recognized as an oval
506 // and accelerated.
507 constexpr Scalar kWeight = kSqrt2Over2 - 0.0005f;
508
509 DlPathBuilder path_builder;
510 path_builder.MoveTo(DlPoint(200, 120));
511 path_builder.ConicCurveTo(DlPoint(300, 120), DlPoint(300, 200), kWeight);
512 path_builder.ConicCurveTo(DlPoint(300, 280), DlPoint(200, 280), kWeight);
513 path_builder.ConicCurveTo(DlPoint(100, 280), DlPoint(100, 200), kWeight);
514 path_builder.ConicCurveTo(DlPoint(100, 120), DlPoint(200, 120), kWeight);
515 path_builder.Close();
516 DlPath path = path_builder.TakePath();
517
518 // Path must be convex, but unrecognizable as a simple shape.
519 ASSERT_TRUE(path.IsConvex());
520 ASSERT_FALSE(path.IsRect());
521 ASSERT_FALSE(path.IsOval());
522 ASSERT_FALSE(path.IsRoundRect());
523
524 const DlPath simple_path = DlPath::MakeOvalLTRB(100, 120, 300, 280);
525 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
526
527 auto dl = builder.Build();
528 ASSERT_TRUE(OpenPlaygroundHere(dl));
529 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [200/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseQuadratic |
| ) |  |

Definition at line 671 of file aiks_dl_shadow_unittests.cc.

671 {
672 DisplayListBuilder builder;
673 builder.Clear(DlColor::kWhite());
674 builder.Scale(GetContentScale().x, GetContentScale().y);
675 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
676 Scalar elevation = 30.0f;
677
678 DlPathBuilder path_builder;
679 path_builder.MoveTo(DlPoint(200, 100));
680 path_builder.QuadraticCurveTo(DlPoint(300, 100), DlPoint(300, 200));
681 path_builder.QuadraticCurveTo(DlPoint(300, 300), DlPoint(200, 300));
682 path_builder.QuadraticCurveTo(DlPoint(100, 300), DlPoint(100, 200));
683 path_builder.QuadraticCurveTo(DlPoint(100, 100), DlPoint(200, 100));
684 path_builder.Close();
685 DlPath path = path_builder.TakePath();
686
687 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
688
689 auto dl = builder.Build();
690 ASSERT_TRUE(OpenPlaygroundHere(dl));
691 }

References x.

## ◆ TEST_P() [201/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseRect |
| ) |  |

Definition at line 369 of file aiks_dl_shadow_unittests.cc.

369 {
370 DisplayListBuilder builder;
371 builder.Clear(DlColor::kWhite());
372 builder.Scale(GetContentScale().x, GetContentScale().y);
373 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
374 Scalar elevation = 30.0f;
375
376 DlPathBuilder path_builder;
377 path_builder.MoveTo(DlPoint(100, 100));
378 // Tweak one corner by a sub-pixel amount to prevent recognition as
379 // a rectangle, but still generating a rectangular shadow.
380 path_builder.LineTo(DlPoint(299.9, 100));
381 path_builder.LineTo(DlPoint(300, 300));
382 path_builder.LineTo(DlPoint(100, 300));
383 path_builder.Close();
384 DlPath path = path_builder.TakePath();
385
386 // Path must be convex, but unrecognizable as a simple shape.
387 ASSERT_TRUE(path.IsConvex());
388 ASSERT_FALSE(path.IsRect());
389 ASSERT_FALSE(path.IsOval());
390 ASSERT_FALSE(path.IsRoundRect());
391
392 const DlPath simple_path = DlPath::MakeRectLTRB(100, 100, 300, 300);
393 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
394
395 auto dl = builder.Build();
396 ASSERT_TRUE(OpenPlaygroundHere(dl));
397 }

References x.

## ◆ TEST_P() [202/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseTriangle |
| ) |  |

Definition at line 329 of file aiks_dl_shadow_unittests.cc.

329 {
330 DisplayListBuilder builder;
331 builder.Clear(DlColor::kWhite());
332 builder.Scale(GetContentScale().x, GetContentScale().y);
333 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
334 Scalar elevation = 30.0f;
335
336 DlPathBuilder path_builder;
337 path_builder.MoveTo(DlPoint(200, 100));
338 path_builder.LineTo(DlPoint(300, 300));
339 path_builder.LineTo(DlPoint(100, 300));
340 path_builder.Close();
341 DlPath path = path_builder.TakePath();
342
343 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
344
345 auto dl = builder.Build();
346 ASSERT_TRUE(OpenPlaygroundHere(dl));
347 }

References x.

## ◆ TEST_P() [203/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseUniformRoundRect |
| ) |  |

Definition at line 565 of file aiks_dl_shadow_unittests.cc.

565 {
566 DisplayListBuilder builder;
567 builder.Clear(DlColor::kWhite());
568 builder.Scale(GetContentScale().x, GetContentScale().y);
569 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
570 Scalar elevation = 30.0f;
571
572 DlPath path = MakeAlmostRoundRectPath(DlRect::MakeLTRB(100, 100, 300, 300),
573 DlRoundingRadii::MakeRadius(30), true);
574
575 // Path must be convex, but unrecognizable as a simple shape.
576 ASSERT_TRUE(path.IsConvex());
577 ASSERT_FALSE(path.IsRect());
578 ASSERT_FALSE(path.IsOval());
579 ASSERT_FALSE(path.IsRoundRect());
580
581 const RoundRect round_rect =
582 RoundRect::MakeRectRadius(Rect::MakeLTRB(100, 100, 300, 300), 30);
583 const DlPath simple_path = DlPath::MakeRoundRect(round_rect);
584 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
585
586 auto dl = builder.Build();
587 ASSERT_TRUE(OpenPlaygroundHere(dl));
588 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and x.

## ◆ TEST_P() [204/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeClockwiseWithExtraColinearVertices |
| ) |  |

Definition at line 886 of file aiks_dl_shadow_unittests.cc.

886 {
887 DisplayListBuilder builder;
888 builder.Clear(DlColor::kWhite());
889 builder.Scale(GetContentScale().x, GetContentScale().y);
890 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
891 Scalar elevation = 30.0f;
892
893 DlPathBuilder path_builder;
894 path_builder.MoveTo(DlPoint(200, 100));
895 path_builder.LineTo(DlPoint(250, 200));
896 path_builder.LineTo(DlPoint(300, 300));
897 path_builder.LineTo(DlPoint(200, 300));
898 path_builder.LineTo(DlPoint(100, 300));
899 path_builder.LineTo(DlPoint(150, 200));
900 path_builder.Close();
901 DlPath path = path_builder.TakePath();
902
903 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
904
905 auto dl = builder.Build();
906 ASSERT_TRUE(OpenPlaygroundHere(dl));
907 }

References x.

## ◆ TEST_P() [205/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseCircle |
| ) |  |

Definition at line 463 of file aiks_dl_shadow_unittests.cc.

463 {
464 DisplayListBuilder builder;
465 builder.Clear(DlColor::kWhite());
466 builder.Scale(GetContentScale().x, GetContentScale().y);
467 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
468 Scalar elevation = 30.0f;
469
470 // A weight of sqrt(2)/2 is how you really perform conic circular sections,
471 // but by tweaking it slightly the path will not be recognized as an oval
472 // and accelerated.
473 constexpr Scalar kWeight = kSqrt2Over2 - 0.0005f;
474
475 DlPathBuilder path_builder;
476 path_builder.MoveTo(DlPoint(200, 100));
477 path_builder.ConicCurveTo(DlPoint(100, 100), DlPoint(100, 200), kWeight);
478 path_builder.ConicCurveTo(DlPoint(100, 300), DlPoint(200, 300), kWeight);
479 path_builder.ConicCurveTo(DlPoint(300, 300), DlPoint(300, 200), kWeight);
480 path_builder.ConicCurveTo(DlPoint(300, 100), DlPoint(200, 100), kWeight);
481 path_builder.Close();
482 DlPath path = path_builder.TakePath();
483
484 // Path must be convex, but unrecognizable as a simple shape.
485 ASSERT_TRUE(path.IsConvex());
486 ASSERT_FALSE(path.IsRect());
487 ASSERT_FALSE(path.IsOval());
488 ASSERT_FALSE(path.IsRoundRect());
489
490 const DlPath simple_path = DlPath::MakeCircle(DlPoint(200, 200), 100);
491 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
492
493 auto dl = builder.Build();
494 ASSERT_TRUE(OpenPlaygroundHere(dl));
495 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [206/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseConic |
| ) |  |

Definition at line 737 of file aiks_dl_shadow_unittests.cc.

737 {
738 DisplayListBuilder builder;
739 builder.Clear(DlColor::kWhite());
740 builder.Scale(GetContentScale().x, GetContentScale().y);
741 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
742 Scalar elevation = 30.0f;
743
744 DlPathBuilder path_builder;
745 path_builder.MoveTo(DlPoint(200, 100));
746 path_builder.ConicCurveTo(DlPoint(100, 100), DlPoint(100, 200), 0.4f);
747 path_builder.ConicCurveTo(DlPoint(100, 300), DlPoint(200, 300), 0.4f);
748 path_builder.ConicCurveTo(DlPoint(300, 300), DlPoint(300, 200), 0.4f);
749 path_builder.ConicCurveTo(DlPoint(300, 100), DlPoint(200, 100), 0.4f);
750 path_builder.Close();
751 DlPath path = path_builder.TakePath();
752
753 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
754
755 auto dl = builder.Build();
756 ASSERT_TRUE(OpenPlaygroundHere(dl));
757 }

References x.

## ◆ TEST_P() [207/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseCubic |
| ) |  |

Definition at line 785 of file aiks_dl_shadow_unittests.cc.

785 {
786 DisplayListBuilder builder;
787 builder.Clear(DlColor::kWhite());
788 builder.Scale(GetContentScale().x, GetContentScale().y);
789 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
790 Scalar elevation = 30.0f;
791
792 DlPathBuilder path_builder;
793 path_builder.MoveTo(DlPoint(200, 100));
794 path_builder.CubicCurveTo(DlPoint(120, 100), DlPoint(100, 120),
795 DlPoint(100, 200));
796 path_builder.CubicCurveTo(DlPoint(100, 280), DlPoint(120, 300),
797 DlPoint(200, 300));
798 path_builder.CubicCurveTo(DlPoint(280, 300), DlPoint(300, 280),
799 DlPoint(300, 200));
800 path_builder.CubicCurveTo(DlPoint(300, 120), DlPoint(280, 100),
801 DlPoint(200, 100));
802 path_builder.Close();
803 DlPath path = path_builder.TakePath();
804
805 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
806
807 auto dl = builder.Build();
808 ASSERT_TRUE(OpenPlaygroundHere(dl));
809 }

References x.

## ◆ TEST_P() [208/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseMultiRadiiRoundRect |
| ) |  |

Definition at line 643 of file aiks_dl_shadow_unittests.cc.

643 {
644 DisplayListBuilder builder;
645 builder.Clear(DlColor::kWhite());
646 builder.Scale(GetContentScale().x, GetContentScale().y);
647 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
648 Scalar elevation = 30.0f;
649
650 DlRoundingRadii radii = DlRoundingRadii{
651 .top_left = {80, 60},
652 .top_right = {20, 25},
653 .bottom_left = {60, 80},
654 .bottom_right = {25, 20},
655 };
656 DlPath path = MakeAlmostRoundRectPath(DlRect::MakeLTRB(100, 100, 300, 300),
657 radii, false);
658
659 // Path must be convex, but unrecognizable as a simple shape.
660 ASSERT_TRUE(path.IsConvex());
661 ASSERT_FALSE(path.IsRect());
662 ASSERT_FALSE(path.IsOval());
663 ASSERT_FALSE(path.IsRoundRect());
664
665 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
666
667 auto dl = builder.Build();
668 ASSERT_TRUE(OpenPlaygroundHere(dl));
669 }

References x.

## ◆ TEST_P() [209/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseOctagon |
| ) |  |

Definition at line 836 of file aiks_dl_shadow_unittests.cc.

836 {
837 DisplayListBuilder builder;
838 builder.Clear(DlColor::kWhite());
839 builder.Scale(GetContentScale().x, GetContentScale().y);
840 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
841 Scalar elevation = 30.0f;
842
843 DlPathBuilder path_builder;
844 path_builder.MoveTo(DlPoint(100, 125));
845 path_builder.LineTo(DlPoint(100, 275));
846 path_builder.LineTo(DlPoint(125, 300));
847 path_builder.LineTo(DlPoint(275, 300));
848 path_builder.LineTo(DlPoint(300, 275));
849 path_builder.LineTo(DlPoint(300, 125));
850 path_builder.LineTo(DlPoint(275, 100));
851 path_builder.LineTo(DlPoint(125, 100));
852 path_builder.Close();
853 DlPath path = path_builder.TakePath();
854
855 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
856
857 auto dl = builder.Build();
858 ASSERT_TRUE(OpenPlaygroundHere(dl));
859 }

References x.

## ◆ TEST_P() [210/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseOval |
| ) |  |

Definition at line 531 of file aiks_dl_shadow_unittests.cc.

531 {
532 DisplayListBuilder builder;
533 builder.Clear(DlColor::kWhite());
534 builder.Scale(GetContentScale().x, GetContentScale().y);
535 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
536 Scalar elevation = 30.0f;
537
538 // A weight of sqrt(2)/2 is how you really perform conic circular sections,
539 // but by tweaking it slightly the path will not be recognized as an oval
540 // and accelerated.
541 constexpr Scalar kWeight = kSqrt2Over2 - 0.0005f;
542
543 DlPathBuilder path_builder;
544 path_builder.MoveTo(DlPoint(200, 120));
545 path_builder.ConicCurveTo(DlPoint(100, 120), DlPoint(100, 200), kWeight);
546 path_builder.ConicCurveTo(DlPoint(100, 280), DlPoint(200, 280), kWeight);
547 path_builder.ConicCurveTo(DlPoint(300, 280), DlPoint(300, 200), kWeight);
548 path_builder.ConicCurveTo(DlPoint(300, 120), DlPoint(200, 120), kWeight);
549 path_builder.Close();
550 DlPath path = path_builder.TakePath();
551
552 // Path must be convex, but unrecognizable as a simple shape.
553 ASSERT_TRUE(path.IsConvex());
554 ASSERT_FALSE(path.IsRect());
555 ASSERT_FALSE(path.IsOval());
556 ASSERT_FALSE(path.IsRoundRect());
557
558 const DlPath simple_path = DlPath::MakeOvalLTRB(100, 120, 300, 280);
559 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
560
561 auto dl = builder.Build();
562 ASSERT_TRUE(OpenPlaygroundHere(dl));
563 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [211/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseQuadratic |
| ) |  |

Definition at line 693 of file aiks_dl_shadow_unittests.cc.

693 {
694 DisplayListBuilder builder;
695 builder.Clear(DlColor::kWhite());
696 builder.Scale(GetContentScale().x, GetContentScale().y);
697 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
698 Scalar elevation = 30.0f;
699
700 DlPathBuilder path_builder;
701 path_builder.MoveTo(DlPoint(200, 100));
702 path_builder.QuadraticCurveTo(DlPoint(100, 100), DlPoint(100, 200));
703 path_builder.QuadraticCurveTo(DlPoint(100, 300), DlPoint(200, 300));
704 path_builder.QuadraticCurveTo(DlPoint(300, 300), DlPoint(300, 200));
705 path_builder.QuadraticCurveTo(DlPoint(300, 100), DlPoint(200, 100));
706 path_builder.Close();
707 DlPath path = path_builder.TakePath();
708
709 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
710
711 auto dl = builder.Build();
712 ASSERT_TRUE(OpenPlaygroundHere(dl));
713 }

References x.

## ◆ TEST_P() [212/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseRect |
| ) |  |

Definition at line 399 of file aiks_dl_shadow_unittests.cc.

399 {
400 DisplayListBuilder builder;
401 builder.Clear(DlColor::kWhite());
402 builder.Scale(GetContentScale().x, GetContentScale().y);
403 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
404 Scalar elevation = 30.0f;
405
406 DlPathBuilder path_builder;
407 path_builder.MoveTo(DlPoint(100, 100));
408 path_builder.LineTo(DlPoint(100, 300));
409 path_builder.LineTo(DlPoint(300, 300));
410 // Tweak one corner by a sub-pixel amount to prevent recognition as
411 // a rectangle, but still generating a rectangular shadow.
412 path_builder.LineTo(DlPoint(299.9, 100));
413 path_builder.Close();
414 DlPath path = path_builder.TakePath();
415
416 // Path must be convex, but unrecognizable as a simple shape.
417 ASSERT_TRUE(path.IsConvex());
418 ASSERT_FALSE(path.IsRect());
419 ASSERT_FALSE(path.IsOval());
420 ASSERT_FALSE(path.IsRoundRect());
421
422 const DlPath simple_path = DlPath::MakeRectLTRB(100, 100, 300, 300);
423 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
424
425 auto dl = builder.Build();
426 ASSERT_TRUE(OpenPlaygroundHere(dl));
427 }

References x.

## ◆ TEST_P() [213/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseTriangle |
| ) |  |

Definition at line 349 of file aiks_dl_shadow_unittests.cc.

349 {
350 DisplayListBuilder builder;
351 builder.Clear(DlColor::kWhite());
352 builder.Scale(GetContentScale().x, GetContentScale().y);
353 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
354 Scalar elevation = 30.0f;
355
356 DlPathBuilder path_builder;
357 path_builder.MoveTo(DlPoint(200, 100));
358 path_builder.LineTo(DlPoint(100, 300));
359 path_builder.LineTo(DlPoint(300, 300));
360 path_builder.Close();
361 DlPath path = path_builder.TakePath();
362
363 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
364
365 auto dl = builder.Build();
366 ASSERT_TRUE(OpenPlaygroundHere(dl));
367 }

References x.

## ◆ TEST_P() [214/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseUniformRoundRect |
| ) |  |

Definition at line 590 of file aiks_dl_shadow_unittests.cc.

590 {
591 DisplayListBuilder builder;
592 builder.Clear(DlColor::kWhite());
593 builder.Scale(GetContentScale().x, GetContentScale().y);
594 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
595 Scalar elevation = 30.0f;
596
597 DlPath path = MakeAlmostRoundRectPath(DlRect::MakeLTRB(100, 100, 300, 300),
598 DlRoundingRadii::MakeRadius(30), false);
599
600 // Path must be convex, but unrecognizable as a simple shape.
601 ASSERT_TRUE(path.IsConvex());
602 ASSERT_FALSE(path.IsRect());
603 ASSERT_FALSE(path.IsOval());
604 ASSERT_FALSE(path.IsRoundRect());
605
606 const RoundRect round_rect =
607 RoundRect::MakeRectRadius(Rect::MakeLTRB(100, 100, 300, 300), 30);
608 const DlPath simple_path = DlPath::MakeRoundRect(round_rect);
609 DrawShadowAndCompareMeshes(builder, path, elevation, dpr, &simple_path);
610
611 auto dl = builder.Build();
612 ASSERT_TRUE(OpenPlaygroundHere(dl));
613 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and x.

## ◆ TEST_P() [215/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeCounterClockwiseWithExtraColinearVertices |
| ) |  |

Definition at line 909 of file aiks_dl_shadow_unittests.cc.

910 {
911 DisplayListBuilder builder;
912 builder.Clear(DlColor::kWhite());
913 builder.Scale(GetContentScale().x, GetContentScale().y);
914 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
915 Scalar elevation = 30.0f;
916
917 DlPathBuilder path_builder;
918 path_builder.MoveTo(DlPoint(200, 100));
919 path_builder.LineTo(DlPoint(150, 200));
920 path_builder.LineTo(DlPoint(100, 300));
921 path_builder.LineTo(DlPoint(200, 300));
922 path_builder.LineTo(DlPoint(300, 300));
923 path_builder.LineTo(DlPoint(250, 200));
924 path_builder.Close();
925 DlPath path = path_builder.TakePath();
926
927 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
928
929 auto dl = builder.Build();
930 ASSERT_TRUE(OpenPlaygroundHere(dl));
931 }

References x.

## ◆ TEST_P() [216/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowCanOptimizeWithExtraneousMoveTos |
| ) |  |

Definition at line 861 of file aiks_dl_shadow_unittests.cc.

861 {
862 DisplayListBuilder builder;
863 builder.Clear(DlColor::kWhite());
864 builder.Scale(GetContentScale().x, GetContentScale().y);
865 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
866 Scalar elevation = 30.0f;
867
868 DlPathBuilder path_builder;
869 path_builder.MoveTo(DlPoint(0, 0));
870 path_builder.MoveTo(DlPoint(1000, 1000));
871 path_builder.MoveTo(DlPoint(100, 50));
872 path_builder.MoveTo(DlPoint(200, 100));
873 path_builder.LineTo(DlPoint(300, 300));
874 path_builder.LineTo(DlPoint(100, 300));
875 path_builder.Close();
876 path_builder.MoveTo(DlPoint(1000, 1000));
877 path_builder.MoveTo(DlPoint(500, 300));
878 DlPath path = path_builder.TakePath();
879
880 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
881
882 auto dl = builder.Build();
883 ASSERT_TRUE(OpenPlaygroundHere(dl));
884 }

References x.

## ◆ TEST_P() [217/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowDoesNotOptimizeHourglass |
| ) |  |

Definition at line 234 of file aiks_dl_shadow_unittests.cc.

234 {
235 DisplayListBuilder builder;
236 builder.Clear(DlColor::kWhite());
237 builder.Scale(GetContentScale().x, GetContentScale().y);
238 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
239 Scalar elevation = 30.0f;
240
241 DlPathBuilder path_builder;
242 path_builder.MoveTo(DlPoint(100, 100));
243 path_builder.LineTo(DlPoint(300, 300));
244 path_builder.LineTo(DlPoint(100, 300));
245 path_builder.LineTo(DlPoint(300, 100));
246 path_builder.Close();
247 DlPath path = path_builder.TakePath();
248
249 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
250
251 auto dl = builder.Build();
252 ASSERT_TRUE(OpenPlaygroundHere(dl));
253 }

References x.

## ◆ TEST_P() [218/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowDoesNotOptimizeInnerOuterSpiral |
| ) |  |

Definition at line 255 of file aiks_dl_shadow_unittests.cc.

255 {
256 DisplayListBuilder builder;
257 builder.Clear(DlColor::kWhite());
258 builder.Scale(GetContentScale().x, GetContentScale().y);
259 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
260 Scalar elevation = 30.0f;
261 int step_count = 20;
262
263 DlPathBuilder path_builder;
264 path_builder.MoveTo(DlPoint(300, 200));
265 for (int i = 1; i < step_count * 2; i++) {
266 Scalar angle = (k2Pi * i) / step_count;
267 Scalar radius = 80.0f + std::abs(i - step_count);
268 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
269 std::sin(angle) * radius));
270 }
271 path_builder.Close();
272 DlPath path = path_builder.TakePath();
273
274 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
275
276 auto dl = builder.Build();
277 ASSERT_TRUE(OpenPlaygroundHere(dl));
278 }

References impeller::k2Pi, and x.

## ◆ TEST_P() [219/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowDoesNotOptimizeMultipleContours |
| ) |  |

Definition at line 305 of file aiks_dl_shadow_unittests.cc.

305 {
306 DisplayListBuilder builder;
307 builder.Clear(DlColor::kWhite());
308 builder.Scale(GetContentScale().x, GetContentScale().y);
309 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
310 Scalar elevation = 30.0f;
311
312 DlPathBuilder path_builder;
313 path_builder.MoveTo(DlPoint(150, 100));
314 path_builder.LineTo(DlPoint(200, 300));
315 path_builder.LineTo(DlPoint(100, 300));
316 path_builder.Close();
317 path_builder.MoveTo(DlPoint(250, 100));
318 path_builder.LineTo(DlPoint(300, 300));
319 path_builder.LineTo(DlPoint(200, 300));
320 path_builder.Close();
321 DlPath path = path_builder.TakePath();
322
323 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
324
325 auto dl = builder.Build();
326 ASSERT_TRUE(OpenPlaygroundHere(dl));
327 }

References x.

## ◆ TEST_P() [220/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawShadowDoesNotOptimizeOuterInnerSpiral |
| ) |  |

Definition at line 280 of file aiks_dl_shadow_unittests.cc.

280 {
281 DisplayListBuilder builder;
282 builder.Clear(DlColor::kWhite());
283 builder.Scale(GetContentScale().x, GetContentScale().y);
284 Scalar dpr = std::max(GetContentScale().x, GetContentScale().y);
285 Scalar elevation = 30.0f;
286 int step_count = 20;
287
288 DlPathBuilder path_builder;
289 path_builder.MoveTo(DlPoint(280, 200));
290 for (int i = 1; i < step_count * 2; i++) {
291 Scalar angle = (k2Pi * i) / step_count;
292 Scalar radius = 100.0f - std::abs(i - step_count);
293 path_builder.LineTo(DlPoint(200, 200) + DlPoint(std::cos(angle) * radius,
294 std::sin(angle) * radius));
295 }
296 path_builder.Close();
297 DlPath path = path_builder.TakePath();
298
299 DrawShadowAndCompareMeshes(builder, path, elevation, dpr);
300
301 auto dl = builder.Build();
302 ASSERT_TRUE(OpenPlaygroundHere(dl));
303 }

References impeller::k2Pi, and x.

## ◆ TEST_P() [221/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinates |
| ) |  |

Definition at line 273 of file aiks_dl_vertices_unittests.cc.

273 {
274 auto texture = CreateTextureForFixture("embarcadero.jpg");
275 auto dl_image = DlImageImpeller::Make(texture);
276 std::vector<DlPoint> positions = {
277 DlPoint(100, 300),
278 DlPoint(200, 100),
279 DlPoint(300, 300),
280 };
281 std::vector<DlPoint> texture_coordinates = {
282 DlPoint(0, 0),
283 DlPoint(100, 200),
284 DlPoint(200, 100),
285 };
286
287 auto vertices = flutter::DlVertices::Make(
288 flutter::DlVertexMode::kTriangles, 3, positions.data(),
289 texture_coordinates.data(), /*colors=*/nullptr);
290
291 flutter::DisplayListBuilder builder;
292 flutter::DlPaint paint;
293
294 auto image_source = flutter::DlColorSource::MakeImage(
295 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
296
297 paint.setColorSource(image_source);
298 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
299
300 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
301 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [222/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending |
| ) |  |

Definition at line 303 of file aiks_dl_vertices_unittests.cc.

304 {
305 auto texture = CreateTextureForFixture("embarcadero.jpg");
306 auto dl_image = DlImageImpeller::Make(texture);
307 std::vector<DlPoint> positions = {
308 DlPoint(100, 300),
309 DlPoint(200, 100),
310 DlPoint(300, 300),
311 };
312 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
313 flutter::DlColor::kGreen(),
314 flutter::DlColor::kWhite()};
315 std::vector<DlPoint> texture_coordinates = {
316 DlPoint(0, 0),
317 DlPoint(100, 200),
318 DlPoint(200, 100),
319 };
320
321 auto vertices = flutter::DlVertices::Make(
322 flutter::DlVertexMode::kTriangles, 3, positions.data(),
323 texture_coordinates.data(), colors.data());
324
325 flutter::DisplayListBuilder builder;
326 flutter::DlPaint paint;
327
328 auto image_source = flutter::DlColorSource::MakeImage(
329 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
330
331 paint.setColorSource(image_source);
332 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
333
334 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
335 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [223/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithEmptySize |
| ) |  |

Definition at line 286 of file canvas_unittests.cc.

286 {
287 RenderCallback callback = [&](RenderTarget& render_target) {
288 ContentContext context(GetContext(), nullptr);
289 Canvas canvas(context, render_target, true, false);
290
291 std::vector<flutter::DlPoint> vertex_coordinates = {
292 flutter::DlPoint(0, 0),
293 flutter::DlPoint(600, 0),
294 flutter::DlPoint(0, 600),
295 };
296 std::vector<flutter::DlPoint> texture_coordinates = {
297 flutter::DlPoint(0, 0),
298 flutter::DlPoint(500, 0),
299 flutter::DlPoint(0, 500),
300 };
301 std::vector<uint16_t> indices = {0, 1, 2};
302 flutter::DlVertices::Builder vertices_builder(
303 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
304 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
305 vertices_builder.store_vertices(vertex_coordinates.data());
306 vertices_builder.store_indices(indices.data());
307 vertices_builder.store_texture_coordinates(texture_coordinates.data());
308 auto vertices = vertices_builder.build();
309
310 // The start and end points of the gradient form an empty rectangle.
311 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
312 flutter::DlColor::kRed()};
313 std::vector<Scalar> stops = {0.0, 1.0};
314 auto gradient = flutter::DlColorSource::MakeLinear(
315 {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
316 flutter::DlTileMode::kClamp);
317
318 Paint paint;
319 paint.color_source = gradient.get();
320 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
321 BlendMode::kSrcOver, paint);
322
323 canvas.EndReplay();
324 return true;
325 };
326
327 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
328 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, and impeller::Playground::OpenPlaygroundHere().

## ◆ TEST_P() [224/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithoutIndices |
| ) |  |

Definition at line 212 of file aiks_dl_vertices_unittests.cc.

212 {
213 std::vector<DlPoint> positions = {
214 DlPoint(100, 300),
215 DlPoint(200, 100),
216 DlPoint(300, 300),
217 };
218
219 auto vertices = flutter::DlVertices::Make(
220 flutter::DlVertexMode::kTriangles, 3, positions.data(),
221 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
222
223 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
224 flutter::DlColor::kRed()};
225 const float stops[2] = {0.0, 1.0};
226
227 auto linear = flutter::DlColorSource::MakeLinear(
228 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
229 flutter::DlTileMode::kRepeat);
230
231 flutter::DisplayListBuilder builder;
232 flutter::DlPaint paint;
233
234 paint.setColorSource(linear);
235 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
236
237 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
238 }

## ◆ TEST_P() [225/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithTextureCoordinates |
| ) |  |

Definition at line 240 of file aiks_dl_vertices_unittests.cc.

240 {
241 std::vector<DlPoint> positions = {
242 DlPoint(100, 300),
243 DlPoint(200, 100),
244 DlPoint(300, 300),
245 };
246 std::vector<DlPoint> texture_coordinates = {
247 DlPoint(300, 100),
248 DlPoint(100, 200),
249 DlPoint(300, 300),
250 };
251
252 auto vertices = flutter::DlVertices::Make(
253 flutter::DlVertexMode::kTriangles, 3, positions.data(),
254 texture_coordinates.data(), /*colors=*/nullptr);
255
256 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
257 flutter::DlColor::kRed()};
258 const float stops[2] = {0.0, 1.0};
259
260 auto linear = flutter::DlColorSource::MakeLinear(
261 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
262 flutter::DlTileMode::kRepeat);
263
264 flutter::DisplayListBuilder builder;
265 flutter::DlPaint paint;
266
267 paint.setColorSource(linear);
268 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
269
270 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
271 }

## ◆ TEST_P() [226/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesPremultipliesColors |
| ) |  |

Definition at line 360 of file aiks_dl_vertices_unittests.cc.

360 {
361 std::vector<DlPoint> positions = {
362 DlPoint(100, 300),
363 DlPoint(200, 100),
364 DlPoint(300, 300),
365 DlPoint(200, 500),
366 };
367 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
368 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
369 std::vector<flutter::DlColor> colors = {color, color, color, color};
370
371 auto vertices = flutter::DlVertices::Make(
372 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
373 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
374 indices.data());
375
376 flutter::DisplayListBuilder builder;
377 flutter::DlPaint paint;
378 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
379 paint.setColor(flutter::DlColor::kRed());
380
381 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
382 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
383
384 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
385 }

## ◆ TEST_P() [227/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesSolidColorTrianglesWithIndices |
| ) |  |

Definition at line 337 of file aiks_dl_vertices_unittests.cc.

337 {
338 std::vector<DlPoint> positions = {
339 DlPoint(100, 300),
340 DlPoint(200, 100),
341 DlPoint(300, 300),
342 DlPoint(200, 500),
343 };
344 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
345
346 auto vertices = flutter::DlVertices::Make(
347 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
348 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
349 indices.data());
350
351 flutter::DisplayListBuilder builder;
352 flutter::DlPaint paint;
353
354 paint.setColor(flutter::DlColor::kRed());
355 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
356
357 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
358 }

## ◆ TEST_P() [228/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesSolidColorTrianglesWithoutIndices |
| ) |  |

Definition at line 186 of file aiks_dl_vertices_unittests.cc.

186 {
187 // Use negative coordinates and then scale the transform by -1, -1 to make
188 // sure coverage is taking the transform into account.
189 std::vector<DlPoint> positions = {
190 DlPoint(-100, -300),
191 DlPoint(-200, -100),
192 DlPoint(-300, -300),
193 };
194 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
195 flutter::DlColor::kGreen(),
196 flutter::DlColor::kWhite()};
197
198 auto vertices = flutter::DlVertices::Make(
199 flutter::DlVertexMode::kTriangles, 3, positions.data(),
200 /*texture_coordinates=*/nullptr, colors.data());
201
202 flutter::DisplayListBuilder builder;
203 flutter::DlPaint paint;
204
205 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
206 builder.Scale(-1, -1);
207 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
208
209 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
210 }

## ◆ TEST_P() [229/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesTextureCoordinatesWithFragmentShader |
| ) |  |

Definition at line 419 of file aiks_dl_vertices_unittests.cc.

419 {
420 std::vector<DlPoint> positions_lt = {
421 DlPoint(0, 0), //
422 DlPoint(50, 0), //
423 DlPoint(0, 50), //
424 DlPoint(50, 50), //
425 };
426
427 auto vertices_lt = flutter::DlVertices::Make(
428 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
429 positions_lt.data(),
430 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
431 /*index_count=*/0,
432 /*indices=*/nullptr);
433
434 std::vector<DlPoint> positions_rt = {
435 DlPoint(50, 0), //
436 DlPoint(100, 0), //
437 DlPoint(50, 50), //
438 DlPoint(100, 50), //
439 };
440
441 auto vertices_rt = flutter::DlVertices::Make(
442 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
443 positions_rt.data(),
444 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
445 /*index_count=*/0,
446 /*indices=*/nullptr);
447
448 std::vector<DlPoint> positions_lb = {
449 DlPoint(0, 50), //
450 DlPoint(50, 50), //
451 DlPoint(0, 100), //
452 DlPoint(50, 100), //
453 };
454
455 auto vertices_lb = flutter::DlVertices::Make(
456 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
457 positions_lb.data(),
458 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
459 /*index_count=*/0,
460 /*indices=*/nullptr);
461
462 std::vector<DlPoint> positions_rb = {
463 DlPoint(50, 50), //
464 DlPoint(100, 50), //
465 DlPoint(50, 100), //
466 DlPoint(100, 100), //
467 };
468
469 auto vertices_rb = flutter::DlVertices::Make(
470 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
471 positions_rb.data(),
472 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
473 /*index_count=*/0,
474 /*indices=*/nullptr);
475
476 flutter::DisplayListBuilder builder;
477 flutter::DlPaint paint;
478 flutter::DlPaint rect_paint;
479 rect_paint.setColor(DlColor::kBlue());
480
481 auto runtime_stages_result =
482 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
483 ABSL_ASSERT_OK(runtime_stages_result);
484 std::shared_ptr<RuntimeStage> runtime_stage =
485 runtime_stages_result
486 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
487 ASSERT_TRUE(runtime_stage);
488
489 auto runtime_effect = DlRuntimeEffectImpeller::Make(runtime_stage);
490 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
491 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
492 runtime_effect, {}, uniform_data);
493
494 paint.setColorSource(color_source);
495
496 builder.Scale(GetContentScale().x, GetContentScale().y);
497 builder.Save();
498 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), rect_paint);
499 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
500 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
501 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
502 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
503 builder.Restore();
504
505 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
506 }

References flutter::DlRuntimeEffectImpeller::Make(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [230/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesTextureCoordinatesWithFragmentShaderNonZeroOrigin |
| ) |  |

Definition at line 510 of file aiks_dl_vertices_unittests.cc.

511 {
512 std::vector<DlPoint> positions_lt = {
513 DlPoint(200, 200), //
514 DlPoint(250, 200), //
515 DlPoint(200, 250), //
516 DlPoint(250, 250), //
517 };
518
519 auto vertices = flutter::DlVertices::Make(
520 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
521 positions_lt.data(),
522 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
523 /*index_count=*/0,
524 /*indices=*/nullptr);
525
526 flutter::DisplayListBuilder builder;
527 flutter::DlPaint paint;
528 flutter::DlPaint rect_paint;
529 rect_paint.setColor(DlColor::kBlue());
530
531 auto runtime_stages_result =
532 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
533 ABSL_ASSERT_OK(runtime_stages_result);
534 std::shared_ptr<RuntimeStage> runtime_stage =
535 runtime_stages_result
536 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
537 ASSERT_TRUE(runtime_stage);
538
539 auto runtime_effect = DlRuntimeEffectImpeller::Make(runtime_stage);
540 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
541
542 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
543 uniform_data->resize(rect_data.size() * sizeof(Rect));
544 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
545
546 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
547 runtime_effect, {}, uniform_data);
548
549 paint.setColorSource(color_source);
550
551 builder.Scale(GetContentScale().x, GetContentScale().y);
552 builder.DrawRect(DlRect::MakeLTRB(200, 200, 250, 250), rect_paint);
553 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
554
555 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
556 }

References flutter::DlRuntimeEffectImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [231/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesWithEmptyTextureCoordinates |
| ) |  |

Definition at line 330 of file canvas_unittests.cc.

330 {
331 auto runtime_stages_result =
332 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
333 ABSL_ASSERT_OK(runtime_stages_result);
334 std::shared_ptr<RuntimeStage> runtime_stage =
335 runtime_stages_result
336 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
337 ASSERT_TRUE(runtime_stage);
338
339 auto runtime_effect = flutter::DlRuntimeEffectImpeller::Make(runtime_stage);
340 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
341 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
342 runtime_effect, {}, uniform_data);
343
344 RenderCallback callback = [&](RenderTarget& render_target) {
345 ContentContext context(GetContext(), nullptr);
346 Canvas canvas(context, render_target, true, false);
347
348 std::vector<flutter::DlPoint> vertex_coordinates = {
349 flutter::DlPoint(100, 100),
350 flutter::DlPoint(300, 100),
351 flutter::DlPoint(100, 300),
352 };
353 // The bounding box of the texture coordinates is empty.
354 std::vector<flutter::DlPoint> texture_coordinates = {
355 flutter::DlPoint(0, 0),
356 flutter::DlPoint(0, 100),
357 flutter::DlPoint(0, 0),
358 };
359 std::vector<uint16_t> indices = {0, 1, 2};
360 flutter::DlVertices::Builder vertices_builder(
361 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
362 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
363 vertices_builder.store_vertices(vertex_coordinates.data());
364 vertices_builder.store_indices(indices.data());
365 vertices_builder.store_texture_coordinates(texture_coordinates.data());
366 auto vertices = vertices_builder.build();
367
368 Paint paint;
369 paint.color_source = color_source.get();
370 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
371 BlendMode::kSrcOver, paint);
372
373 canvas.EndReplay();
374 return true;
375 };
376
377 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
378 }
flutter::DlRuntimeEffectImpeller::Make
static sk_sp< DlRuntimeEffect > Make(std::shared_ptr< impeller::RuntimeStage > runtime_stage)
Definition: dl_runtime_effect_impeller.cc:14

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, flutter::DlRuntimeEffectImpeller::Make(), impeller::Playground::OpenPlaygroundHere(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [232/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesWithInvalidIndices |
| ) |  |

Definition at line 387 of file aiks_dl_vertices_unittests.cc.

387 {
388 std::vector<DlPoint> positions = {
389 DlPoint(100, 300),
390 DlPoint(200, 100),
391 DlPoint(300, 300),
392 DlPoint(200, 500),
393 };
394 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
395
396 auto vertices = flutter::DlVertices::Make(
397 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
398 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
399 indices.data());
400
401 EXPECT_EQ(vertices->GetBounds(), DlRect::MakeLTRB(100, 100, 300, 500));
402
403 flutter::DisplayListBuilder builder;
404 flutter::DlPaint paint;
405 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
406 paint.setColor(flutter::DlColor::kRed());
407
408 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
409 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
410
411 AiksContext renderer(GetContext(), nullptr);
412 std::shared_ptr<Texture> image =
413 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
414 EXPECT_TRUE(image);
415 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [233/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | EmptySaveLayerIgnoresPaint |
| ) |  |

Definition at line 1767 of file aiks_dl_basic_unittests.cc.

1767 {
1768 DisplayListBuilder builder;
1769 builder.Scale(GetContentScale().x, GetContentScale().y);
1770
1771 DlPaint paint;
1772 paint.setColor(DlColor::kRed());
1773 builder.DrawPaint(paint);
1774 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1775 paint.setColor(DlColor::kBlue());
1776 builder.SaveLayer(std::nullopt, &paint);
1777 builder.Restore();
1778
1779 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1780 }

References x.

## ◆ TEST_P() [234/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | EmptySaveLayerRendersWithClear |
| ) |  |

Definition at line 1782 of file aiks_dl_basic_unittests.cc.

1782 {
1783 DisplayListBuilder builder;
1784 builder.Scale(GetContentScale().x, GetContentScale().y);
1785 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1786 builder.DrawImage(image, DlPoint(10, 10), {});
1787 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1788
1789 DlPaint paint;
1790 paint.setBlendMode(DlBlendMode::kClear);
1791 builder.SaveLayer(std::nullopt, &paint);
1792 builder.Restore();
1793
1794 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1795 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [235/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | EmulatedAdvancedBlendRestore |
| ) |  |

Definition at line 927 of file aiks_dl_blend_unittests.cc.

927 {
928 DisplayListBuilder builder;
929
930 builder.DrawPaint(DlPaint(DlColor::kWhite()));
931 builder.Save();
932 builder.ClipRect(DlRect::MakeLTRB(100, 100, 400, 300));
933
934 // Draw should apply the clip, even though it is an advanced blend.
935 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 300),
936 DlPaint()
937 .setColor(DlColor::kRed())
938 .setBlendMode(DlBlendMode::kDifference));
939 // This color should not show if clip is still functional.
940 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100),
941 DlPaint().setColor(DlColor::kBlue()));
942 builder.Restore();
943
944 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
945 }

## ◆ TEST_P() [236/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastEllipticalRRectMaskBlursRenderCorrectly |
| ) |  |

Definition at line 2184 of file aiks_dl_basic_unittests.cc.

2184 {
2185 DisplayListBuilder builder;
2186
2187 builder.Scale(GetContentScale().x, GetContentScale().y);
2188 DlPaint paint;
2189 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
2190
2191 DlPaint save_paint;
2192 save_paint.setColor(DlColor::kWhite());
2193 builder.DrawPaint(save_paint);
2194
2195 paint.setColor(DlColor::kBlue());
2196 for (int i = 0; i < 5; i++) {
2197 Scalar y = i * 125;
2198 Scalar y_radius = i * 15;
2199 for (int j = 0; j < 5; j++) {
2200 Scalar x = j * 125;
2201 Scalar x_radius = j * 15;
2202 builder.DrawRoundRect(
2203 DlRoundRect::MakeRectXY(
2204 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
2205 x_radius, y_radius),
2206 paint);
2207 }
2208 }
2209
2210 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2211 }

References x.

## ◆ TEST_P() [237/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastGradientTestHorizontal |
| ) |  |

Definition at line 825 of file aiks_dl_gradient_unittests.cc.

825 {
826 DisplayListBuilder builder;
827 DlPaint paint;
828 builder.Translate(100.0f, 0);
829
830 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
831 DlColor::kGreen()};
832 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
833
834 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
835 colors.data(), stops.data(),
836 DlTileMode::kClamp));
837
838 paint.setColor(DlColor::kWhite());
839 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
840 builder.Translate(400, 0);
841 builder.DrawRoundRect(
842 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
843
844 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
845 }

## ◆ TEST_P() [238/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastGradientTestHorizontalReversed |
| ) |  |

Definition at line 871 of file aiks_dl_gradient_unittests.cc.

871 {
872 DisplayListBuilder builder;
873 DlPaint paint;
874 builder.Translate(100.0f, 0);
875
876 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
877 DlColor::kGreen()};
878 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
879
880 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
881 colors.data(), stops.data(),
882 DlTileMode::kClamp));
883
884 paint.setColor(DlColor::kWhite());
885 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
886 builder.Translate(400, 0);
887 builder.DrawRoundRect(
888 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
889
890 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
891 }

## ◆ TEST_P() [239/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastGradientTestVertical |
| ) |  |

Definition at line 848 of file aiks_dl_gradient_unittests.cc.

848 {
849 DisplayListBuilder builder;
850 DlPaint paint;
851 builder.Translate(100.0f, 0);
852
853 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
854 DlColor::kGreen()};
855 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
856
857 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
858 colors.data(), stops.data(),
859 DlTileMode::kClamp));
860
861 paint.setColor(DlColor::kWhite());
862 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
863 builder.Translate(400, 0);
864 builder.DrawRoundRect(
865 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
866
867 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }

## ◆ TEST_P() [240/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastGradientTestVerticalReversed |
| ) |  |

Definition at line 894 of file aiks_dl_gradient_unittests.cc.

894 {
895 DisplayListBuilder builder;
896 DlPaint paint;
897 builder.Translate(100.0f, 0);
898
899 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
900 DlColor::kGreen()};
901 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
902
903 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
904 colors.data(), stops.data(),
905 DlTileMode::kClamp));
906
907 paint.setColor(DlColor::kWhite());
908 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
909 builder.Translate(400, 0);
910 builder.DrawRoundRect(
911 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
912
913 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
914 }

## ◆ TEST_P() [241/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FatStrokeArc |
| ) |  |

Definition at line 875 of file aiks_dl_path_unittests.cc.

875 {
876 DlScalar stroke_width = 300;
877 DlScalar aspect = 1.0;
878 DlScalar start_angle = 0;
879 DlScalar end_angle = 90;
880 auto callback = [&]() -> sk_sp<DisplayList> {
881 if (AiksTest::ImGuiBegin("Controls", nullptr,
882 ImGuiWindowFlags_AlwaysAutoResize)) {
883 ImGui::SliderFloat("Stroke Width", &stroke_width, 1, 300);
884 ImGui::SliderFloat("Aspect", &aspect, 0.5, 2.0);
885 ImGui::SliderFloat("Start Angle", &start_angle, 0, 360);
886 ImGui::SliderFloat("End Angle", &end_angle, 0, 360);
887 ImGui::End();
888 }
889
890 DisplayListBuilder builder;
891 DlPaint grey_paint;
892 grey_paint.setColor(DlColor(0xff111111));
893 builder.DrawPaint(grey_paint);
894
895 DlPaint white_paint;
896 white_paint.setColor(DlColor::kWhite());
897 white_paint.setStrokeWidth(stroke_width);
898 white_paint.setDrawStyle(DlDrawStyle::kStroke);
899 DlPaint red_paint;
900 red_paint.setColor(DlColor::kRed());
901
902 Rect rect = Rect::MakeXYWH(100, 100, 100, aspect * 100);
903 builder.DrawRect(rect, red_paint);
904 builder.DrawArc(rect, start_angle, end_angle,
905 /*useCenter=*/false, white_paint);
906 DlScalar frontier = rect.GetRight() + stroke_width / 2.0;
907 builder.DrawLine(Point(frontier, 0), Point(frontier, 150), red_paint);
908
909 return builder.Build();
910 };
911 ASSERT_TRUE(OpenPlaygroundHere(callback));
912 }

References impeller::TRect< T >::GetRight(), impeller::AiksPlayground::ImGuiBegin(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [242/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledArcsRenderCorrectly |
| ) |  |

Definition at line 971 of file aiks_dl_basic_unittests.cc.

971 {
972 DisplayListBuilder builder;
973 builder.Scale(GetContentScale().x, GetContentScale().y);
974 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
975
976 DlPaint paint;
977 paint.setColor(DlColor::kBlue());
978
979 RenderArcFarm(builder, paint,
980 {
981 .use_center = false,
982 .full_circles = false,
983 });
984
985 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
986 }

References x.

## ◆ TEST_P() [243/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledArcsRenderCorrectlyWithCenter |
| ) |  |

Definition at line 1005 of file aiks_dl_basic_unittests.cc.

1005 {
1006 DisplayListBuilder builder;
1007 builder.Scale(GetContentScale().x, GetContentScale().y);
1008 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1009
1010 DlPaint paint;
1011 paint.setColor(DlColor::kBlue());
1012
1013 RenderArcFarm(builder, paint,
1014 {
1015 .use_center = true,
1016 .full_circles = false,
1017 });
1018
1019 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1020 }

References x.

## ◆ TEST_P() [244/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledCirclesRenderCorrectly |
| ) |  |

Definition at line 628 of file aiks_dl_basic_unittests.cc.

628 {
629 DisplayListBuilder builder;
630 builder.Scale(GetContentScale().x, GetContentScale().y);
631 DlPaint paint;
632 const int color_count = 3;
633 DlColor colors[color_count] = {
634 DlColor::kBlue(),
635 DlColor::kGreen(),
636 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
637 };
638
639 paint.setColor(DlColor::kWhite());
640 builder.DrawPaint(paint);
641
642 int c_index = 0;
643 int radius = 600;
644 while (radius > 0) {
645 paint.setColor(colors[(c_index++) % color_count]);
646 builder.DrawCircle(DlPoint(10, 10), radius, paint);
647 if (radius > 30) {
648 radius -= 10;
649 } else {
650 radius -= 2;
651 }
652 }
653
654 DlColor gradient_colors[7] = {
655 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
656 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
657 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
658 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
659 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
660 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
661 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
662 };
663 DlScalar stops[7] = {
664 0.0,
665 (1.0 / 6.0) * 1,
666 (1.0 / 6.0) * 2,
667 (1.0 / 6.0) * 3,
668 (1.0 / 6.0) * 4,
669 (1.0 / 6.0) * 5,
670 1.0,
671 };
672 auto texture = CreateTextureForFixture("airplane.jpg",
673 /*enable_mipmapping=*/true);
674 auto image = DlImageImpeller::Make(texture);
675
676 paint.setColorSource(DlColorSource::MakeRadial(
677 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
678 builder.DrawCircle(DlPoint(500, 600), 100, paint);
679
680 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
681 paint.setColorSource(DlColorSource::MakeImage(
682 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
683 DlImageSampling::kNearestNeighbor, &local_matrix));
684 builder.DrawCircle(DlPoint(800, 300), 100, paint);
685
686 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
687 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [245/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledEllipsesRenderCorrectly |
| ) |  |

Definition at line 850 of file aiks_dl_basic_unittests.cc.

850 {
851 DisplayListBuilder builder;
852 builder.Scale(GetContentScale().x, GetContentScale().y);
853 DlPaint paint;
854 const int color_count = 3;
855 DlColor colors[color_count] = {
856 DlColor::kBlue(),
857 DlColor::kGreen(),
858 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
859 };
860
861 paint.setColor(DlColor::kWhite());
862 builder.DrawPaint(paint);
863
864 int c_index = 0;
865 int long_radius = 600;
866 int short_radius = 600;
867 while (long_radius > 0 && short_radius > 0) {
868 paint.setColor(colors[(c_index++) % color_count]);
869 builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
870 long_radius * 2, short_radius * 2),
871 paint);
872 builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
873 short_radius * 2, long_radius * 2),
874 paint);
875 if (short_radius > 30) {
876 short_radius -= 10;
877 long_radius -= 5;
878 } else {
879 short_radius -= 2;
880 long_radius -= 1;
881 }
882 }
883
884 DlColor gradient_colors[7] = {
885 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
886 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
887 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
888 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
889 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
890 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
891 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
892 };
893 DlScalar stops[7] = {
894 0.0,
895 (1.0 / 6.0) * 1,
896 (1.0 / 6.0) * 2,
897 (1.0 / 6.0) * 3,
898 (1.0 / 6.0) * 4,
899 (1.0 / 6.0) * 5,
900 1.0,
901 };
902 auto texture = CreateTextureForFixture("airplane.jpg",
903 /*enable_mipmapping=*/true);
904 auto image = DlImageImpeller::Make(texture);
905
906 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
907
908 paint.setColorSource(DlColorSource::MakeRadial(
909 DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
910 builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
911 builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
912
913 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
914 paint.setColorSource(DlColorSource::MakeImage(
915 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
916 DlImageSampling::kNearestNeighbor, &local_matrix));
917 builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
918 builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
919
920 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
921 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [246/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledRoundRectPathsRenderCorrectly |
| ) |  |

Definition at line 1918 of file aiks_dl_basic_unittests.cc.

1918 {
1919 DisplayListBuilder builder;
1920 builder.Scale(GetContentScale().x, GetContentScale().y);
1921
1922 DlPaint paint;
1923 const int color_count = 3;
1924 DlColor colors[color_count] = {
1925 DlColor::kBlue(),
1926 DlColor::kGreen(),
1927 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1928 };
1929
1930 paint.setColor(DlColor::kWhite());
1931 builder.DrawPaint(paint);
1932
1933 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1934 const DlPaint& paint) {
1935 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1936 };
1937
1938 int c_index = 0;
1939 for (int i = 0; i < 4; i++) {
1940 for (int j = 0; j < 4; j++) {
1941 paint.setColor(colors[(c_index++) % color_count]);
1942 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1943 i * 5 + 10, j * 5 + 10, paint);
1944 }
1945 }
1946 paint.setColor(colors[(c_index++) % color_count]);
1947 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1948 paint.setColor(colors[(c_index++) % color_count]);
1949 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1950
1951 std::vector<DlColor> gradient_colors = {
1952 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1953 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1954 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1955 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1956 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1957 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1958 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1959 std::vector<Scalar> stops = {
1960 0.0,
1961 (1.0 / 6.0) * 1,
1962 (1.0 / 6.0) * 2,
1963 (1.0 / 6.0) * 3,
1964 (1.0 / 6.0) * 4,
1965 (1.0 / 6.0) * 5,
1966 1.0,
1967 };
1968 auto texture = DlImageImpeller::Make(
1969 CreateTextureForFixture("airplane.jpg",
1970 /*enable_mipmapping=*/true));
1971
1972 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1973 paint.setColorSource(DlColorSource::MakeRadial(
1974 /*center=*/DlPoint(550, 550),
1975 /*radius=*/75,
1976 /*stop_count=*/gradient_colors.size(),
1977 /*colors=*/gradient_colors.data(),
1978 /*stops=*/stops.data(),
1979 /*tile_mode=*/DlTileMode::kMirror));
1980 for (int i = 1; i <= 10; i++) {
1981 int j = 11 - i;
1982 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1983 550 + i * 20, 550 + j * 20),
1984 i * 10, j * 10, paint);
1985 }
1986 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1987 paint.setColorSource(DlColorSource::MakeRadial(
1988 /*center=*/DlPoint(200, 650),
1989 /*radius=*/75,
1990 /*stop_count=*/gradient_colors.size(),
1991 /*colors=*/gradient_colors.data(),
1992 /*stops=*/stops.data(),
1993 /*tile_mode=*/DlTileMode::kMirror));
1994 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1995 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1996
1997 auto matrix = DlMatrix::MakeTranslation({520, 20});
1998 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1999 paint.setColorSource(DlColorSource::MakeImage(
2000 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
2001 DlImageSampling::kMipmapLinear, &matrix));
2002 for (int i = 1; i <= 10; i++) {
2003 int j = 11 - i;
2004 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
2005 720 + i * 20, 220 + j * 20),
2006 i * 10, j * 10, paint);
2007 }
2008 matrix = DlMatrix::MakeTranslation({800, 300});
2009 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
2010 paint.setColorSource(DlColorSource::MakeImage(
2011 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
2012 DlImageSampling::kMipmapLinear, &matrix));
2013
2014 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
2015 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
2016
2017 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2018 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [247/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledRoundRectsRenderCorrectly |
| ) |  |

Definition at line 1322 of file aiks_dl_basic_unittests.cc.

1322 {
1323 DisplayListBuilder builder;
1324 builder.Scale(GetContentScale().x, GetContentScale().y);
1325 DlPaint paint;
1326 const int color_count = 3;
1327 DlColor colors[color_count] = {
1328 DlColor::kBlue(),
1329 DlColor::kGreen(),
1330 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
1331 };
1332
1333 paint.setColor(DlColor::kWhite());
1334 builder.DrawPaint(paint);
1335
1336 int c_index = 0;
1337 for (int i = 0; i < 4; i++) {
1338 for (int j = 0; j < 4; j++) {
1339 paint.setColor(colors[(c_index++) % color_count]);
1340 builder.DrawRoundRect(
1341 DlRoundRect::MakeRectXY(
1342 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
1343 i * 5 + 10, j * 5 + 10),
1344 paint);
1345 }
1346 }
1347 paint.setColor(colors[(c_index++) % color_count]);
1348 builder.DrawRoundRect(
1349 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
1350 paint);
1351 paint.setColor(colors[(c_index++) % color_count]);
1352 builder.DrawRoundRect(
1353 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
1354 paint);
1355
1356 DlColor gradient_colors[7] = {
1357 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1358 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1359 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1360 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1361 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1362 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1363 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
1364 };
1365 DlScalar stops[7] = {
1366 0.0,
1367 (1.0 / 6.0) * 1,
1368 (1.0 / 6.0) * 2,
1369 (1.0 / 6.0) * 3,
1370 (1.0 / 6.0) * 4,
1371 (1.0 / 6.0) * 5,
1372 1.0,
1373 };
1374 auto texture = CreateTextureForFixture("airplane.jpg",
1375 /*enable_mipmapping=*/true);
1376 auto image = DlImageImpeller::Make(texture);
1377
1378 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1379 paint.setColorSource(DlColorSource::MakeRadial(
1380 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1381 for (int i = 1; i <= 10; i++) {
1382 int j = 11 - i;
1383 builder.DrawRoundRect(
1384 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1385 550 + i * 20, 550 + j * 20),
1386 i * 10, j * 10),
1387 paint);
1388 }
1389
1390 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1391 paint.setColorSource(DlColorSource::MakeRadial(
1392 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1393 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1394 builder.DrawRoundRect(
1395 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
1396 paint);
1397 builder.DrawRoundRect(
1398 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
1399 paint);
1400
1401 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1402 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
1403 paint.setColorSource(DlColorSource::MakeImage(
1404 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1405 DlImageSampling::kNearestNeighbor, &local_matrix));
1406 for (int i = 1; i <= 10; i++) {
1407 int j = 11 - i;
1408 builder.DrawRoundRect(
1409 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1410 720 + i * 20, 220 + j * 20),
1411 i * 10, j * 10),
1412 paint);
1413 }
1414
1415 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1416 local_matrix = DlMatrix::MakeTranslation({800, 300});
1417 paint.setColorSource(DlColorSource::MakeImage(
1418 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1419 DlImageSampling::kNearestNeighbor, &local_matrix));
1420 builder.DrawRoundRect(
1421 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
1422 paint);
1423 builder.DrawRoundRect(
1424 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
1425 paint);
1426
1427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1428 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [248/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ForegroundAdvancedBlendAppliesTransformCorrectly |
| ) |  |

Definition at line 732 of file aiks_dl_blend_unittests.cc.

732 {
733 auto texture = CreateTextureForFixture("airplane.jpg",
734 /*enable_mipmapping=*/true);
735
736 DisplayListBuilder builder;
737 builder.Rotate(30);
738
739 DlPaint image_paint;
740 image_paint.setColorFilter(DlColorFilter::MakeBlend(
741 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
742 DlBlendMode::kColorDodge));
743
744 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
745 DlImageSampling::kMipmapLinear, &image_paint);
746
747 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
748 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [249/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ForegroundBlendSubpassCollapseOptimization |
| ) |  |

Definition at line 467 of file aiks_dl_blend_unittests.cc.

467 {
468 DisplayListBuilder builder;
469
470 DlPaint save_paint;
471 save_paint.setColorFilter(
472 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kColorDodge));
473 builder.SaveLayer(std::nullopt, &save_paint);
474
475 builder.Translate(500, 300);
476 builder.Rotate(120);
477
478 DlPaint paint;
479 paint.setColor(DlColor::kBlue());
480 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
481
482 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
483 }

## ◆ TEST_P() [250/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ForegroundPipelineBlendAppliesTransformCorrectly |
| ) |  |

Definition at line 714 of file aiks_dl_blend_unittests.cc.

714 {
715 auto texture = CreateTextureForFixture("airplane.jpg",
716 /*enable_mipmapping=*/true);
717
718 DisplayListBuilder builder;
719 builder.Rotate(30);
720
721 DlPaint image_paint;
722 image_paint.setColorFilter(DlColorFilter::MakeBlend(
723 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
724 DlBlendMode::kSrcIn));
725
726 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
727 DlImageSampling::kMipmapLinear, &image_paint);
728
729 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
730 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [251/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FormatSRGB |
| ) |  |

Definition at line 1831 of file aiks_dl_basic_unittests.cc.

1831 {
1832 PixelFormat pixel_format =
1833 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1834 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1835 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1836 << "pixel format: " << PixelFormatToString(pixel_format);
1837 }
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::PixelFormatToString
constexpr const char * PixelFormatToString(PixelFormat format)
Definition: formats.h:141

References impeller::kB8G8R8A8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::PixelFormatToString().

## ◆ TEST_P() [252/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FormatWideGamut |
| ) |  |

Definition at line 1826 of file aiks_dl_basic_unittests.cc.

1826 {
1827 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1828 PixelFormat::kB10G10R10A10XR);
1829 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [253/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FramebufferAdvancedBlendCoverage |
| ) |  |

Definition at line 750 of file aiks_dl_blend_unittests.cc.

750 {
751 auto texture = CreateTextureForFixture("airplane.jpg",
752 /*enable_mipmapping=*/true);
753
754 // Draw with an advanced blend that can use FramebufferBlendContents and
755 // verify that the scale transform is correctly applied to the image.
756 DisplayListBuilder builder;
757
758 DlPaint paint;
759 paint.setColor(
760 DlColor::RGBA(169.0f / 255.0f, 169.0f / 255.0f, 169.0f / 255.0f, 1.0f));
761 builder.DrawPaint(paint);
762 builder.Scale(0.4, 0.4);
763
764 DlPaint image_paint;
765 image_paint.setBlendMode(DlBlendMode::kMultiply);
766
767 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(20, 20),
768 DlImageSampling::kMipmapLinear, &image_paint);
769
770 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
771 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [254/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FramebufferBlendsRespectClips |
| ) |  |

If correct, this test should draw a green circle. If any red is visible, there is a depth bug.

Definition at line 118 of file aiks_dl_clip_unittests.cc.

118 {
119 DisplayListBuilder builder;
120
121 // Clear the whole canvas with white.
122 DlPaint paint;
123 paint.setColor(DlColor::kWhite());
124 builder.DrawPaint(paint);
125
126 builder.ClipPath(DlPath::MakeCircle(DlPoint(150, 150), 50),
127 DlClipOp::kIntersect);
128
129 // Draw a red rectangle that should not show through the circle clip.
130 paint.setColor(DlColor::kRed());
131 paint.setBlendMode(DlBlendMode::kMultiply);
132 builder.DrawRect(DlRect::MakeXYWH(100, 100, 100, 100), paint);
133
134 // Draw a green circle that shows through the clip.
135 paint.setColor(DlColor::kGreen());
136 paint.setBlendMode(DlBlendMode::kSrcOver);
137 builder.DrawCircle(DlPoint(150, 150), 50, paint);
138
139 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
140 }

## ◆ TEST_P() [255/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAnimatedBackdrop |
| ) |  |

Definition at line 943 of file aiks_dl_blur_unittests.cc.

943 {
944 // This test is for checking out how stable rendering is when content is
945 // translated underneath a blur. Animating under a blur can cause
946 // *shimmering* to happen as a result of pixel alignment.
947 // See also: https://github.com/flutter/flutter/issues/140193
948 auto boston =
949 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
950 ASSERT_TRUE(boston);
951 int64_t count = 0;
952 Scalar sigma = 20.0;
953 Scalar freq = 0.1;
954 Scalar amp = 50.0;
955 auto callback = [&]() -> sk_sp<DisplayList> {
956 if (AiksTest::ImGuiBegin("Controls", nullptr,
957 ImGuiWindowFlags_AlwaysAutoResize)) {
958 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
959 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
960 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
961 ImGui::End();
962 }
963
964 DisplayListBuilder builder;
965 builder.Scale(GetContentScale().x, GetContentScale().y);
966 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
967 builder.DrawImage(DlImageImpeller::Make(boston),
968 DlPoint(1024 / 2 - boston->GetSize().width / 2,
969 (768 / 2 - boston->GetSize().height / 2) + y),
970 DlImageSampling::kMipmapLinear);
971 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
972 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
973 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
974
975 builder.ClipRect(
976 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
977 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
978
979 DlPaint paint;
980 paint.setBlendMode(DlBlendMode::kSrc);
981
982 auto backdrop_filter =
983 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
984 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
985 count += 1;
986 return builder.Build();
987 };
988 ASSERT_TRUE(OpenPlaygroundHere(callback));
989 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), and x.

## ◆ TEST_P() [256/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryHorizontal |
| ) |  |

Definition at line 914 of file aiks_dl_blur_unittests.cc.

914 {
915 DisplayListBuilder builder;
916
917 builder.Scale(GetContentScale().x, GetContentScale().y);
918 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
919 builder.DrawImageRect(
920 DlImageImpeller::Make(boston),
921 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
922 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
923 DlImageSampling::kNearestNeighbor);
924
925 DlPaint paint;
926 paint.setColor(DlColor::kMagenta());
927
928 DlRoundRect rrect = DlRoundRect::MakeRectXY(
929 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
930 builder.DrawRoundRect(rrect, paint);
931 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
932
933 DlPaint save_paint;
934 save_paint.setBlendMode(DlBlendMode::kSrc);
935
936 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
937 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
938
939 builder.Restore();
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [257/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryVertical |
| ) |  |

Definition at line 886 of file aiks_dl_blur_unittests.cc.

886 {
887 DisplayListBuilder builder;
888
889 DlPaint paint;
890 builder.Scale(GetContentScale().x, GetContentScale().y);
891
892 paint.setColor(DlColor::kLimeGreen());
893 DlRoundRect rrect = DlRoundRect::MakeRectXY(
894 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
895 builder.DrawRoundRect(rrect, paint);
896
897 paint.setColor(DlColor::kMagenta());
898 rrect = DlRoundRect::MakeRectXY(
899 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
900 builder.DrawRoundRect(rrect, paint);
901 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
902
903 DlPaint save_paint;
904 save_paint.setBlendMode(DlBlendMode::kSrc);
905
906 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
907
908 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
909 builder.Restore();
910
911 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
912 }

References x.

## ◆ TEST_P() [258/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurBackdropTinyMipMap |
| ) |  |

Definition at line 1377 of file aiks_dl_blur_unittests.cc.

1377 {
1378 AiksContext renderer(GetContext(), nullptr);
1379 for (int32_t i = 1; i < 5; ++i) {
1380 DisplayListBuilder builder;
1381
1382 ISize clip_size = ISize(i, i);
1383 builder.Save();
1384 builder.ClipRect(
1385 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1386
1387 DlPaint paint;
1388 paint.setColor(DlColor::kGreen());
1389 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1390 paint.setImageFilter(blur_filter);
1391
1392 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1393 builder.Restore();
1394
1395 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1396 EXPECT_TRUE(image) << " length " << i;
1397 }
1398 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [259/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurOneDimension |
| ) |  |

Definition at line 1189 of file aiks_dl_blur_unittests.cc.

1189 {
1190 DisplayListBuilder builder;
1191
1192 builder.Scale(GetContentScale().x, GetContentScale().y);
1193 builder.Scale(0.5, 0.5);
1194
1195 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1196 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1197
1198 DlPaint paint;
1199 paint.setBlendMode(DlBlendMode::kSrc);
1200
1201 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1202 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1203 builder.Restore();
1204 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1205 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [260/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClipped |
| ) |  |

Definition at line 1211 of file aiks_dl_blur_unittests.cc.

1211 {
1212 DisplayListBuilder builder;
1213
1214 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1215 Rect bounds =
1216 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1217
1218 DlPaint paint;
1219 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1220
1221 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1222 Vector2 clip_size = {150, 75};
1223 Vector2 center = Vector2(1024, 768) / 2;
1224 builder.Scale(GetContentScale().x, GetContentScale().y);
1225
1226 auto clip_bounds =
1227 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1228 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1229 clip_bounds.GetRight(),
1230 clip_bounds.GetBottom()));
1231 builder.Translate(center.x, center.y);
1232 builder.Scale(0.6, 0.6);
1233 builder.Rotate(25);
1234
1235 auto dst_rect = bounds.Shift(-image_center);
1236 builder.DrawImageRect(
1237 DlImageImpeller::Make(boston), /*src=*/
1238 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1239 bounds.GetBottom()),
1240 /*dst=*/
1241 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1242 dst_rect.GetRight(), dst_rect.GetBottom()),
1243 DlImageSampling::kMipmapLinear, &paint);
1244
1245 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1246 }
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:314

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [261/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClippedInteractive |
| ) |  |

Definition at line 1134 of file aiks_dl_blur_unittests.cc.

1134 {
1135 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1136
1137 auto callback = [&]() -> sk_sp<DisplayList> {
1138 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1139 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1140 DlTileMode::kMirror, DlTileMode::kDecal};
1141
1142 static float rotation = 0;
1143 static float scale = 0.6;
1144 static int selected_tile_mode = 3;
1145
1146 if (AiksTest::ImGuiBegin("Controls", nullptr,
1147 ImGuiWindowFlags_AlwaysAutoResize)) {
1148 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1149 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1150 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1151 sizeof(tile_mode_names) / sizeof(char*));
1152 ImGui::End();
1153 }
1154
1155 DisplayListBuilder builder;
1156 Rect bounds =
1157 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1158 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1159 DlPaint paint;
1160 paint.setImageFilter(
1161 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1162
1163 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1164 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1165 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1166 Vector2 center = Vector2(1024, 768) / 2;
1167
1168 builder.Scale(GetContentScale().x, GetContentScale().y);
1169 builder.ClipRect(
1170 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1171 builder.Translate(center.x, center.y);
1172 builder.Scale(scale, scale);
1173 builder.Rotate(rotation);
1174
1175 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1176 bounds.GetRight(), bounds.GetBottom());
1177 Rect dest = bounds.Shift(-image_center);
1178 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1179 dest.GetRight(), dest.GetBottom());
1180 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1181 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1182 &paint);
1183 return builder.Build();
1184 };
1185
1186 ASSERT_TRUE(OpenPlaygroundHere(callback));
1187 }
impeller::TRect::Shift
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:602

References impeller::DrawPlaygroundLine(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::TPoint< T >::Rotate(), impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [262/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedNonUniform |
| ) |  |

Definition at line 1248 of file aiks_dl_blur_unittests.cc.

1248 {
1249 auto callback = [&]() -> sk_sp<DisplayList> {
1250 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1251 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1252 DlTileMode::kMirror, DlTileMode::kDecal};
1253
1254 static float rotation = 45;
1255 static float scale = 0.6;
1256 static int selected_tile_mode = 3;
1257
1258 if (AiksTest::ImGuiBegin("Controls", nullptr,
1259 ImGuiWindowFlags_AlwaysAutoResize)) {
1260 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1261 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1262 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1263 sizeof(tile_mode_names) / sizeof(char*));
1264 ImGui::End();
1265 }
1266
1267 DisplayListBuilder builder;
1268
1269 DlPaint paint;
1270 paint.setColor(DlColor::kGreen());
1271 paint.setImageFilter(
1272 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1273
1274 Vector2 center = Vector2(1024, 768) / 2;
1275 builder.Scale(GetContentScale().x, GetContentScale().y);
1276 builder.Translate(center.x, center.y);
1277 builder.Scale(scale, scale);
1278 builder.Rotate(rotation);
1279
1280 DlRoundRect rrect =
1281 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1282 builder.DrawRoundRect(rrect, paint);
1283 return builder.Build();
1284 };
1285
1286 ASSERT_TRUE(OpenPlaygroundHere(callback));
1287 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [263/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurScaledAndClipped |
| ) |  |

Definition at line 1101 of file aiks_dl_blur_unittests.cc.

1101 {
1102 DisplayListBuilder builder;
1103 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1104 Rect bounds =
1105 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1106 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1107
1108 DlPaint paint;
1109 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1110
1111 Vector2 clip_size = {150, 75};
1112 Vector2 center = Vector2(1024, 768) / 2;
1113 builder.Scale(GetContentScale().x, GetContentScale().y);
1114
1115 auto rect =
1116 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1117 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1118 rect.GetRight(), rect.GetBottom()));
1119 builder.Translate(center.x, center.y);
1120 builder.Scale(0.6, 0.6);
1121
1122 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1123 bounds.GetRight(), bounds.GetBottom());
1124 Rect dest = bounds.Shift(-image_center);
1125 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1126 dest.GetRight(), dest.GetBottom());
1127 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1128 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1129 &paint);
1130
1131 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1132 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [264/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurSolidColorTinyMipMap |
| ) |  |

Definition at line 1352 of file aiks_dl_blur_unittests.cc.

1352 {
1353 AiksContext renderer(GetContext(), nullptr);
1354
1355 for (int32_t i = 1; i < 5; ++i) {
1356 DisplayListBuilder builder;
1357 Scalar fi = i;
1358 DlPathBuilder path_builder;
1359 path_builder.MoveTo(DlPoint(100, 100));
1360 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1361
1362 DlPaint paint;
1363 paint.setColor(DlColor::kChartreuse());
1364 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1365 paint.setImageFilter(blur_filter);
1366
1367 builder.DrawPath(path_builder.TakePath(), paint);
1368
1369 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1370 EXPECT_TRUE(image) << " length " << i;
1371 }
1372 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [265/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInner |
| ) |  |

Definition at line 741 of file aiks_dl_blur_unittests.cc.

741 {
742 DisplayListBuilder builder;
743 builder.Scale(GetContentScale().x, GetContentScale().y);
744
745 DlPaint paint;
746 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
747 builder.DrawPaint(paint);
748
749 paint.setColor(DlColor::kGreen());
750 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
751
752 DlPathBuilder path_builder;
753 path_builder.MoveTo(DlPoint(200, 200));
754 path_builder.LineTo(DlPoint(300, 400));
755 path_builder.LineTo(DlPoint(100, 400));
756 path_builder.Close();
757
758 builder.DrawPath(path_builder.TakePath(), paint);
759
760 // Draw another thing to make sure the clip area is reset.
761 DlPaint red;
762 red.setColor(DlColor::kRed());
763 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
764
765 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
766 }

References x.

## ◆ TEST_P() [266/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInnerGradient |
| ) |  |

Definition at line 991 of file aiks_dl_blur_unittests.cc.

991 {
992 DisplayListBuilder builder;
993
994 builder.Scale(GetContentScale().x, GetContentScale().y);
995
996 DlPaint paint;
997 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
998 builder.DrawPaint(paint);
999
1000 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1001 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1002 std::vector<Scalar> stops = {0.0, 1.0};
1003
1004 paint = DlPaint{};
1005 paint.setColorSource(DlColorSource::MakeLinear(
1006 /*start_point=*/{0, 0},
1007 /*end_point=*/{200, 200},
1008 /*stop_count=*/colors.size(),
1009 /*colors=*/colors.data(),
1010 /*stops=*/stops.data(),
1011 /*tile_mode=*/DlTileMode::kMirror));
1012 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
1013
1014 DlPathBuilder path_builder;
1015 path_builder.MoveTo(DlPoint(200, 200));
1016 path_builder.LineTo(DlPoint(300, 400));
1017 path_builder.LineTo(DlPoint(100, 400));
1018 path_builder.Close();
1019 builder.DrawPath(path_builder.TakePath(), paint);
1020
1021 // Draw another thing to make sure the clip area is reset.
1022 DlPaint red;
1023 red.setColor(DlColor::kRed());
1024 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1025
1026 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1027 }

References x.

## ◆ TEST_P() [267/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuter |
| ) |  |

Definition at line 768 of file aiks_dl_blur_unittests.cc.

768 {
769 DisplayListBuilder builder;
770 builder.Scale(GetContentScale().x, GetContentScale().y);
771
772 DlPaint paint;
773 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
774 builder.DrawPaint(paint);
775
776 paint.setColor(DlColor::kGreen());
777 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
778
779 DlPathBuilder path_builder;
780 path_builder.MoveTo(DlPoint(200, 200));
781 path_builder.LineTo(DlPoint(300, 400));
782 path_builder.LineTo(DlPoint(100, 400));
783 path_builder.Close();
784
785 builder.DrawPath(path_builder.TakePath(), paint);
786
787 // Draw another thing to make sure the clip area is reset.
788 DlPaint red;
789 red.setColor(DlColor::kRed());
790 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
791
792 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
793 }

References x.

## ◆ TEST_P() [268/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuterGradient |
| ) |  |

Definition at line 1065 of file aiks_dl_blur_unittests.cc.

1065 {
1066 DisplayListBuilder builder;
1067 builder.Scale(GetContentScale().x, GetContentScale().y);
1068
1069 DlPaint paint;
1070 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1071 builder.DrawPaint(paint);
1072
1073 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1074 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1075 std::vector<Scalar> stops = {0.0, 1.0};
1076
1077 paint = DlPaint{};
1078 paint.setColorSource(DlColorSource::MakeLinear(
1079 /*start_point=*/{0, 0},
1080 /*end_point=*/{200, 200},
1081 /*stop_count=*/colors.size(),
1082 /*colors=*/colors.data(),
1083 /*stops=*/stops.data(),
1084 /*tile_mode=*/DlTileMode::kMirror));
1085 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
1086
1087 DlPathBuilder path_builder;
1088 path_builder.MoveTo(DlPoint(200, 200));
1089 path_builder.LineTo(DlPoint(300, 400));
1090 path_builder.LineTo(DlPoint(100, 400));
1091 path_builder.Close();
1092 builder.DrawPath(path_builder.TakePath(), paint);
1093
1094 // Draw another thing to make sure the clip area is reset.
1095 DlPaint red;
1096 red.setColor(DlColor::kRed());
1097 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1098 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1099 }

References x.

## ◆ TEST_P() [269/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolid |
| ) |  |

Definition at line 795 of file aiks_dl_blur_unittests.cc.

795 {
796 DisplayListBuilder builder;
797 builder.Scale(GetContentScale().x, GetContentScale().y);
798
799 DlPaint paint;
800 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
801 builder.DrawPaint(paint);
802
803 paint.setColor(DlColor::kGreen());
804 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
805
806 DlPathBuilder path_builder;
807 path_builder.MoveTo(DlPoint(200, 200));
808 path_builder.LineTo(DlPoint(300, 400));
809 path_builder.LineTo(DlPoint(100, 400));
810 path_builder.Close();
811
812 builder.DrawPath(path_builder.TakePath(), paint);
813
814 // Draw another thing to make sure the clip area is reset.
815 DlPaint red;
816 red.setColor(DlColor::kRed());
817 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
818
819 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
820 }

References x.

## ◆ TEST_P() [270/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolidGradient |
| ) |  |

Definition at line 1029 of file aiks_dl_blur_unittests.cc.

1029 {
1030 DisplayListBuilder builder;
1031 builder.Scale(GetContentScale().x, GetContentScale().y);
1032
1033 DlPaint paint;
1034 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1035 builder.DrawPaint(paint);
1036
1037 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1038 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1039 std::vector<Scalar> stops = {0.0, 1.0};
1040
1041 paint = DlPaint{};
1042 paint.setColorSource(DlColorSource::MakeLinear(
1043 /*start_point=*/{0, 0},
1044 /*end_point=*/{200, 200},
1045 /*stop_count=*/colors.size(),
1046 /*colors=*/colors.data(),
1047 /*stops=*/stops.data(),
1048 /*tile_mode=*/DlTileMode::kMirror));
1049 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
1050
1051 DlPathBuilder path_builder;
1052 path_builder.MoveTo(DlPoint(200, 200));
1053 path_builder.LineTo(DlPoint(300, 400));
1054 path_builder.LineTo(DlPoint(100, 400));
1055 path_builder.Close();
1056 builder.DrawPath(path_builder.TakePath(), paint);
1057
1058 // Draw another thing to make sure the clip area is reset.
1059 DlPaint red;
1060 red.setColor(DlColor::kRed());
1061 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1062 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1063 }

References x.

## ◆ TEST_P() [271/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlur |
| ) |  |

Definition at line 104 of file aiks_dl_blur_unittests.cc.

104 {
105 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
106 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
107 }
impeller::testing::DoGradientOvalStrokeMaskBlur
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
Definition: aiks_dl_blur_unittests.cc:63

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [272/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurInner |
| ) |  |

Definition at line 119 of file aiks_dl_blur_unittests.cc.

119 {
120 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
121 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
122 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [273/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurOuter |
| ) |  |

Definition at line 114 of file aiks_dl_blur_unittests.cc.

114 {
115 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
116 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
117 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [274/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSigmaZero |
| ) |  |

Definition at line 109 of file aiks_dl_blur_unittests.cc.

109 {
110 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
111 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
112 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [275/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSolid |
| ) |  |

Definition at line 124 of file aiks_dl_blur_unittests.cc.

124 {
125 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
126 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
127 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [276/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientStrokesRenderCorrectly |
| ) |  |

Definition at line 734 of file aiks_dl_gradient_unittests.cc.

734 {
735 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
736 auto callback = [&]() -> sk_sp<DisplayList> {
737 static float scale = 3;
738 static bool add_circle_clip = true;
739 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
740 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
741 DlTileMode::kMirror, DlTileMode::kDecal};
742 static int selected_tile_mode = 0;
743 static float alpha = 1;
744
745 if (AiksTest::ImGuiBegin("Controls", nullptr,
746 ImGuiWindowFlags_AlwaysAutoResize)) {
747 ImGui::SliderFloat("Scale", &scale, 0, 6);
748 ImGui::Checkbox("Circle clip", &add_circle_clip);
749 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
750 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
751 sizeof(tile_mode_names) / sizeof(char*));
752 ImGui::End();
753 }
754
755 DisplayListBuilder builder;
756 builder.Scale(GetContentScale().x, GetContentScale().y);
757 DlPaint paint;
758 paint.setColor(DlColor::kWhite());
759 builder.DrawPaint(paint);
760
761 paint.setDrawStyle(DlDrawStyle::kStroke);
762 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
763 paint.setStrokeWidth(10);
764 auto tile_mode = tile_modes[selected_tile_mode];
765
766 std::vector<DlColor> colors = {
767 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
768 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
769 std::vector<Scalar> stops = {0.0, 1.0};
770
771 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
772 stops.size(), colors.data(),
773 stops.data(), tile_mode));
774
775 DlPathBuilder path_builder;
776 path_builder.MoveTo(DlPoint(20, 20));
777 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
778 path_builder.Close();
779 path_builder.MoveTo(DlPoint(60, 20));
780 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
781 DlPath path = path_builder.TakePath();
782
783 builder.Scale(scale, scale);
784
785 if (add_circle_clip) {
786 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
787 Color::Red());
788 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
789 Color::Red());
790 auto [handle_a, handle_b] =
791 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
792
793 Matrix ip_matrix = builder.GetMatrix();
794 if (!ip_matrix.IsInvertible()) {
795 return nullptr;
796 }
797 ip_matrix = ip_matrix.Invert();
798 Point point_a = ip_matrix * handle_a * GetContentScale();
799 Point point_b = ip_matrix * handle_b * GetContentScale();
800
801 Point middle = (point_a + point_b) / 2;
802 auto radius = point_a.GetDistance(middle);
803 builder.ClipPath(DlPath::MakeCircle(middle, radius));
804 }
805
806 for (auto join :
807 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
808 paint.setStrokeJoin(join);
809 for (auto cap :
810 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
811 paint.setStrokeCap(cap);
812 builder.DrawPath(path, paint);
813 builder.Translate(80, 0);
814 }
815 builder.Translate(-240, 60);
816 }
817
818 return builder.Build();
819 };
820
821 ASSERT_TRUE(OpenPlaygroundHere(callback));
822 }
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:201

References impeller::DrawPlaygroundLine(), impeller::TPoint< T >::GetDistance(), impeller::Matrix::Invert(), impeller::Matrix::IsInvertible(), impeller::Color::ToARGB(), and x.

## ◆ TEST_P() [277/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HairlineDrawLine |
| ) |  |

Definition at line 308 of file aiks_dl_path_unittests.cc.

308 {
309 Scalar scale = 1.f;
310 Scalar rotation = 0.f;
311 Scalar offset = 0.f;
312 auto callback = [&]() -> sk_sp<DisplayList> {
313 if (AiksTest::ImGuiBegin("Controls", nullptr,
314 ImGuiWindowFlags_AlwaysAutoResize)) {
315 ImGui::SliderFloat("Scale", &scale, 0, 6);
316 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
317 ImGui::SliderFloat("Offset", &offset, 0, 2);
318 ImGui::End();
319 }
320
321 DisplayListBuilder builder;
322 builder.Scale(GetContentScale().x, GetContentScale().y);
323 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
324
325 DlPaint paint;
326 paint.setStrokeWidth(0.f);
327 paint.setColor(DlColor::kWhite());
328
329 builder.Translate(512, 384);
330 builder.Scale(scale, scale);
331 builder.Rotate(rotation);
332 builder.Translate(-512, -384 + offset);
333
334 for (int i = 0; i < 5; ++i) {
335 Scalar yoffset = i * 25.25f + 300.f;
336
337 builder.DrawLine(DlPoint(100, yoffset), DlPoint(924, yoffset), paint);
338 }
339
340 return builder.Build();
341 };
342
343 ASSERT_TRUE(OpenPlaygroundHere(callback));
344 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [278/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HairlinePath |
| ) |  |

Definition at line 264 of file aiks_dl_path_unittests.cc.

264 {
265 Scalar scale = 1.f;
266 Scalar rotation = 0.f;
267 Scalar offset = 0.f;
268 auto callback = [&]() -> sk_sp<DisplayList> {
269 if (AiksTest::ImGuiBegin("Controls", nullptr,
270 ImGuiWindowFlags_AlwaysAutoResize)) {
271 ImGui::SliderFloat("Scale", &scale, 0, 6);
272 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
273 ImGui::SliderFloat("Offset", &offset, 0, 2);
274 ImGui::End();
275 }
276
277 DisplayListBuilder builder;
278 builder.Scale(GetContentScale().x, GetContentScale().y);
279 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
280
281 DlPaint paint;
282 paint.setStrokeWidth(0.f);
283 paint.setColor(DlColor::kWhite());
284 paint.setStrokeCap(DlStrokeCap::kRound);
285 paint.setStrokeJoin(DlStrokeJoin::kRound);
286 paint.setDrawStyle(DlDrawStyle::kStroke);
287
288 builder.Translate(512, 384);
289 builder.Scale(scale, scale);
290 builder.Rotate(rotation);
291 builder.Translate(-512, -384 + offset);
292
293 for (int i = 0; i < 5; ++i) {
294 Scalar yoffset = i * 25.25f + 300.f;
295 DlPathBuilder path_builder;
296
297 path_builder.MoveTo(DlPoint(100, yoffset));
298 path_builder.LineTo(DlPoint(924, yoffset));
299 builder.DrawPath(path_builder.TakePath(), paint);
300 }
301
302 return builder.Build();
303 };
304
305 ASSERT_TRUE(OpenPlaygroundHere(callback));
306 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [279/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HexagonExperimentAntialiasLines |
| ) |  |

Definition at line 680 of file aiks_dl_path_unittests.cc.

680 {
681 float scale = 5.0f;
682 float line_width = 10.f;
683 float rotation = 0.f;
684
685 auto callback = [&]() -> sk_sp<DisplayList> {
686 if (AiksTest::ImGuiBegin("Controls", nullptr,
687 ImGuiWindowFlags_AlwaysAutoResize)) {
688 // Use ImGui::SliderFloat for consistency
689 ImGui::SliderFloat("Scale", &scale, 0.001f, 5.0f);
690 ImGui::SliderFloat("Width", &line_width, 1.0f, 20.0f);
691 ImGui::SliderFloat("Rotation", &rotation, 0.0f, 180.0f);
692
693 ImGui::End();
694 }
695 DisplayListBuilder builder;
696 builder.Scale(static_cast<float>(GetContentScale().x),
697 static_cast<float>(GetContentScale().y));
698
699 builder.DrawPaint(DlPaint(DlColor(0xff111111))); // Background
700
701 {
702 DlPaint hex_paint;
703 hex_paint.setColor(
704 DlColor::kGreen()); // Changed color to Red for visibility
705 hex_paint.setStrokeWidth(line_width); // Use the interactive width
706
707 float cx = 512.0f; // Center X
708 float cy = 384.0f; // Center Y
709 float r = 80.0f; // Radius (distance from center to vertex)
710
711 float r_sin60 = r * std::sqrt(3.0f) / 2.0f;
712 float r_cos60 = r / 2.0f;
713
714 DlPoint v0 = DlPoint(cx + r, cy); // Right vertex
715 DlPoint v1 = DlPoint(cx + r_cos60, cy - r_sin60); // Top-right vertex
716 DlPoint v2 = DlPoint(
717 cx - r_cos60,
718 cy - r_sin60); // Top-left vertex (v1-v2 is top horizontal side)
719 DlPoint v3 = DlPoint(cx - r, cy); // Left vertex
720 DlPoint v4 = DlPoint(cx - r_cos60, cy + r_sin60); // Bottom-left vertex
721 DlPoint v5 =
722 DlPoint(cx + r_cos60, cy + r_sin60); // Bottom-right vertex (v4-v5 is
723 // bottom horizontal side)
724
725 builder.Translate(cx, cy);
726 builder.Scale(scale, scale);
727 builder.Rotate(rotation);
728 builder.Translate(-cx, -cy);
729
730 builder.DrawLine(v0, v1, hex_paint);
731 builder.DrawLine(v1, v2, hex_paint); // Top side
732 builder.DrawLine(v2, v3, hex_paint);
733 builder.DrawLine(v3, v4, hex_paint);
734 builder.DrawLine(v4, v5, hex_paint); // Bottom side
735 builder.DrawLine(v5, v0, hex_paint); // Close the hexagon
736 }
737
738 return builder.Build();
739 };
740 ASSERT_TRUE(OpenPlaygroundHere(callback));
741 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [280/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageColorSourceEffectTransform |
| ) |  |

Definition at line 1595 of file aiks_dl_basic_unittests.cc.

1595 {
1596 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
1597
1598 DisplayListBuilder builder;
1599 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
1600
1601 DlPaint paint;
1602 paint.setColor(DlColor::kWhite());
1603 builder.DrawPaint(paint);
1604
1605 // Translation
1606 {
1607 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
1608 DlPaint paint;
1609 paint.setColorSource(DlColorSource::MakeImage(
1610 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1611 DlImageSampling::kNearestNeighbor, &matrix));
1612
1613 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
1614 }
1615
1616 // Rotation/skew
1617 {
1618 builder.Save();
1619 builder.Rotate(45);
1620 DlPaint paint;
1621
1622 Matrix matrix(1, -1, 0, 0, //
1623 1, 1, 0, 0, //
1624 0, 0, 1, 0, //
1625 0, 0, 0, 1);
1626 paint.setColorSource(DlColorSource::MakeImage(
1627 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1628 DlImageSampling::kNearestNeighbor, &matrix));
1629 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
1630 builder.Restore();
1631 }
1632
1633 // Scale
1634 {
1635 builder.Save();
1636 builder.Translate(100, 0);
1637 builder.Scale(100, 100);
1638 DlPaint paint;
1639
1640 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
1641 paint.setColorSource(DlColorSource::MakeImage(
1642 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1643 DlImageSampling::kNearestNeighbor, &matrix));
1644
1645 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
1646 builder.Restore();
1647 }
1648
1649 // Perspective
1650 {
1651 builder.Save();
1652 builder.Translate(150, 150);
1653 DlPaint paint;
1654
1655 DlMatrix matrix =
1656 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
1657 paint.setColorSource(DlColorSource::MakeImage(
1658 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1659 DlImageSampling::kNearestNeighbor, &matrix));
1660
1661 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
1662 builder.Restore();
1663 }
1664
1665 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1666 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [281/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageFilteredSaveLayerWithUnboundedContents |
| ) |  |

Definition at line 661 of file aiks_dl_unittests.cc.

661 {
662 DisplayListBuilder builder;
663 builder.Scale(GetContentScale().x, GetContentScale().y);
664
665 auto test = [&builder](const std::shared_ptr<DlImageFilter>& filter) {
666 auto DrawLine = [&builder](const DlPoint& p0, const DlPoint& p1,
667 const DlPaint& p) {
668 DlPaint paint = p;
669 paint.setDrawStyle(DlDrawStyle::kStroke);
670 builder.DrawPath(DlPath::MakeLine(p0, p1), paint);
671 };
672 // Registration marks for the edge of the SaveLayer
673 DlPaint paint;
674 paint.setColor(DlColor::kWhite());
675 DrawLine(DlPoint(75, 100), DlPoint(225, 100), paint);
676 DrawLine(DlPoint(75, 200), DlPoint(225, 200), paint);
677 DrawLine(DlPoint(100, 75), DlPoint(100, 225), paint);
678 DrawLine(DlPoint(200, 75), DlPoint(200, 225), paint);
679
680 DlPaint save_paint;
681 save_paint.setImageFilter(filter);
682 DlRect bounds = DlRect::MakeLTRB(100, 100, 200, 200);
683 builder.SaveLayer(bounds, &save_paint);
684
685 {
686 // DrawPaint to verify correct behavior when the contents are unbounded.
687 DlPaint paint;
688 paint.setColor(DlColor::kYellow());
689 builder.DrawPaint(paint);
690
691 // Contrasting rectangle to see interior blurring
692 paint.setColor(DlColor::kBlue());
693 builder.DrawRect(DlRect::MakeLTRB(125, 125, 175, 175), paint);
694 }
695 builder.Restore();
696 };
697
698 test(DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
699
700 builder.Translate(200.0, 0.0);
701
702 test(DlImageFilter::MakeDilate(10.0, 10.0));
703
704 builder.Translate(200.0, 0.0);
705
706 test(DlImageFilter::MakeErode(10.0, 10.0));
707
708 builder.Translate(-400.0, 200.0);
709
710 DlMatrix matrix = DlMatrix::MakeRotationZ(DlDegrees(10));
711
712 auto rotate_filter =
713 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
714 test(rotate_filter);
715
716 builder.Translate(200.0, 0.0);
717
718 const float m[20] = {
719 0, 1, 0, 0, 0, //
720 0, 0, 1, 0, 0, //
721 1, 0, 0, 0, 0, //
722 0, 0, 0, 1, 0 //
723 };
724 auto rgb_swap_filter =
725 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(m));
726 test(rgb_swap_filter);
727
728 builder.Translate(200.0, 0.0);
729
730 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter));
731
732 builder.Translate(-400.0, 200.0);
733
734 test(rotate_filter->makeWithLocalMatrix(
735 DlMatrix::MakeTranslation({25.0, 25.0})));
736
737 builder.Translate(200.0, 0.0);
738
739 test(rgb_swap_filter->makeWithLocalMatrix(
740 DlMatrix::MakeTranslation({25.0, 25.0})));
741
742 builder.Translate(200.0, 0.0);
743
744 test(DlImageFilter::MakeCompose(rotate_filter, rgb_swap_filter)
745 ->makeWithLocalMatrix(DlMatrix::MakeTranslation({25.0, 25.0})));
746
747 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
748 }

References p1, and x.

## ◆ TEST_P() [282/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageFilteredUnboundedSaveLayerWithUnboundedContents |
| ) |  |

Definition at line 225 of file aiks_dl_unittests.cc.

225 {
226 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
227 builder.Scale(GetContentScale().x, GetContentScale().y);
228
229 DlPaint save_paint;
230 save_paint.setImageFilter(
231 DlImageFilter::MakeBlur(10.0, 10.0, DlTileMode::kDecal));
232 builder.SaveLayer(std::nullopt, &save_paint);
233
234 {
235 // DrawPaint to verify correct behavior when the contents are unbounded.
236 DlPaint draw_paint;
237 draw_paint.setColor(DlColor::kYellow());
238 builder.DrawPaint(draw_paint);
239
240 // Contrasting rectangle to see interior blurring
241 DlPaint draw_rect;
242 draw_rect.setColor(DlColor::kBlue());
243 builder.DrawRect(DlRect::MakeLTRB(125, 125, 175, 175), draw_rect);
244 }
245 builder.Restore();
246
247 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
248 }

References x.

## ◆ TEST_P() [283/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | LinearToSrgbFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 105 of file aiks_dl_unittests.cc.

105 {
106 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
107
108 DlPaint paint;
109 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
110 builder.SaveLayer(std::nullopt, &paint);
111
112 builder.Translate(500, 300);
113 builder.Rotate(120); // 120 deg.
114
115 DlPaint draw_paint;
116 draw_paint.setColor(DlColor::kBlue());
117 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), draw_paint);
118
119 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
120 }

## ◆ TEST_P() [284/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurDoesntStretchContents |
| ) |  |

Definition at line 851 of file aiks_dl_blur_unittests.cc.

851 {
852 Scalar sigma = 70;
853 auto callback = [&]() -> sk_sp<DisplayList> {
854 if (AiksTest::ImGuiBegin("Controls", nullptr,
855 ImGuiWindowFlags_AlwaysAutoResize)) {
856 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
857 ImGui::End();
858 }
859
860 DisplayListBuilder builder;
861 builder.Scale(GetContentScale().x, GetContentScale().y);
862
863 DlPaint paint;
864 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
865 builder.DrawPaint(paint);
866
867 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
868
869 builder.Transform(Matrix::MakeTranslation({100, 100}) *
870 Matrix::MakeScale({0.5, 0.5, 1.0f}));
871
872 paint.setColorSource(DlColorSource::MakeImage(
873 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
874 DlImageSampling::kMipmapLinear));
875 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
876
877 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
878 boston->GetSize().height),
879 paint);
880
881 return builder.Build();
882 };
883 ASSERT_TRUE(OpenPlaygroundHere(callback));
884 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and x.

## ◆ TEST_P() [285/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurOnZeroDimensionIsSkippedWideGamut |
| ) |  |

Definition at line 567 of file aiks_dl_blur_unittests.cc.

567 {
568 // Making sure this test is run on a wide gamut enabled backend
569 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
570 PixelFormat::kB10G10R10A10XR);
571
572 DisplayListBuilder builder;
573 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
574
575 DlPaint paint;
576 paint.setColor(DlColor::kBlue());
577 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
578
579 // Zero height above
580 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
581 // Regular rect
582 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
583 // Zero width to the right
584 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
585
586 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
587 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [286/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurTexture |
| ) |  |

Definition at line 822 of file aiks_dl_blur_unittests.cc.

822 {
823 Scalar sigma = 30;
824 auto callback = [&]() -> sk_sp<DisplayList> {
825 if (AiksTest::ImGuiBegin("Controls", nullptr,
826 ImGuiWindowFlags_AlwaysAutoResize)) {
827 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
828 ImGui::End();
829 }
830
831 DisplayListBuilder builder;
832 builder.Scale(GetContentScale().x, GetContentScale().y);
833
834 DlPaint paint;
835 paint.setColor(DlColor::kGreen());
836 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
837
838 builder.DrawImage(
839 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
840 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
841
842 DlPaint red;
843 red.setColor(DlColor::kRed());
844 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
845
846 return builder.Build();
847 };
848 ASSERT_TRUE(OpenPlaygroundHere(callback));
849 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [287/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurWithZeroSigmaIsSkipped |
| ) |  |

Definition at line 554 of file aiks_dl_blur_unittests.cc.

554 {
555 DisplayListBuilder builder;
556
557 DlPaint paint;
558 paint.setColor(DlColor::kBlue());
559 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
560
561 builder.DrawCircle(DlPoint(300, 300), 200, paint);
562 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
563
564 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
565 }

## ◆ TEST_P() [288/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScaleConvertToPath |
| ) |  |

Definition at line 197 of file aiks_dl_text_unittests.cc.

197 {
198 Scalar scale = 16.0;
199 auto callback = [&]() -> sk_sp<DisplayList> {
200 if (AiksTest::ImGuiBegin("Controls", nullptr,
201 ImGuiWindowFlags_AlwaysAutoResize)) {
202 ImGui::SliderFloat("Scale", &scale, 4, 20);
203 ImGui::End();
204 }
205
206 DisplayListBuilder builder;
207 DlPaint paint;
208 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
209 builder.DrawPaint(paint);
210
211 builder.Scale(scale, scale);
212 RenderTextInCanvasSkia(
213 GetContext(), builder, "HELLO", "Roboto-Regular.ttf",
214 TextRenderOptions{.font_size = 16,
215 .color = (16 * scale >= 250) ? DlColor::kYellow()
216 : DlColor::kOrange(),
217 .position = DlPoint(0, 20)});
218 return builder.Build();
219 };
220
221 ASSERT_TRUE(OpenPlaygroundHere(callback));
222 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [289/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScalingMatrixImageFilter |
| ) |  |

Definition at line 2239 of file aiks_dl_basic_unittests.cc.

2239 {
2240 if (GetBackend() == PlaygroundBackend::kVulkan) {
2241 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
2242 }
2243 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
2244
2245 auto filter = DlImageFilter::MakeMatrix(
2246 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
2247
2248 DlPaint paint;
2249 paint.setImageFilter(filter);
2250 builder.SaveLayer(std::nullopt, &paint);
2251 {
2252 DlPaint paint;
2253 paint.setColor(DlColor::kRed());
2254 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
2255 }
2256 builder.Restore();
2257
2258 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2259 }

References impeller::kVulkan.

## ◆ TEST_P() [290/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixBackdropFilter |
| ) |  |

Definition at line 750 of file aiks_dl_unittests.cc.

750 {
751 DisplayListBuilder builder;
752
753 DlPaint paint;
754 paint.setColor(DlColor::kBlack());
755 builder.DrawPaint(paint);
756 builder.SaveLayer(std::nullopt, nullptr);
757 {
758 DlPaint paint;
759 paint.setColor(DlColor::kGreen().withAlpha(0.5 * 255));
760 paint.setBlendMode(DlBlendMode::kPlus);
761
762 DlPaint rect_paint;
763 rect_paint.setColor(DlColor::kRed());
764 rect_paint.setStrokeWidth(4);
765 rect_paint.setDrawStyle(DlDrawStyle::kStroke);
766 builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 300), rect_paint);
767 builder.DrawCircle(DlPoint(200, 200), 100, paint);
768 // Should render a second circle, centered on the bottom-right-most edge of
769 // the circle.
770 DlMatrix matrix = DlMatrix::MakeTranslation({(100 + 100 * k1OverSqrt2),
771 (100 + 100 * k1OverSqrt2)}) *
772 DlMatrix::MakeScale({0.5, 0.5, 1}) *
773 DlMatrix::MakeTranslation({-100, -100});
774 auto backdrop_filter =
775 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear);
776 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter.get());
777 builder.Restore();
778 }
779 builder.Restore();
780
781 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [291/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen |
| ) |  |

Definition at line 1718 of file aiks_dl_basic_unittests.cc.

1719 {
1720 DisplayListBuilder builder;
1721 builder.Scale(GetContentScale().x, GetContentScale().y);
1722 builder.Translate(100, 100);
1723 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1724 // +300 translation applied by a SaveLayer image filter.
1725
1726 DlPaint paint;
1727 paint.setImageFilter(DlImageFilter::MakeMatrix(
1728 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1729 DlImageSampling::kNearestNeighbor));
1730 builder.SaveLayer(std::nullopt, &paint);
1731
1732 DlPaint circle_paint;
1733 circle_paint.setColor(DlColor::kGreen());
1734 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1735 builder.Restore();
1736
1737 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1738 }

References x.

## ◆ TEST_P() [292/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen |
| ) |  |

Definition at line 1697 of file aiks_dl_basic_unittests.cc.

1697 {
1698 DisplayListBuilder builder;
1699 builder.Scale(GetContentScale().x, GetContentScale().y);
1700 builder.Translate(100, 100);
1701 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1702 // +300 translation applied by a SaveLayer image filter.
1703 DlPaint paint;
1704 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1705 paint.setImageFilter(
1706 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1707 builder.SaveLayer(std::nullopt, &paint);
1708
1709 DlPaint circle_paint;
1710 circle_paint.setColor(DlColor::kGreen());
1711 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1712 builder.Restore();
1713
1714 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1715 }

References x.

## ◆ TEST_P() [293/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterMagnify |
| ) |  |

Definition at line 629 of file aiks_dl_unittests.cc.

629 {
630 Scalar scale = 2.0;
631 auto callback = [&]() -> sk_sp<DisplayList> {
632 if (AiksTest::ImGuiBegin("Controls", nullptr,
633 ImGuiWindowFlags_AlwaysAutoResize)) {
634 ImGui::SliderFloat("Scale", &scale, 1, 2);
635 ImGui::End();
636 }
637 DisplayListBuilder builder;
638 builder.Scale(GetContentScale().x, GetContentScale().y);
639 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
640
641 builder.Translate(600, -200);
642
643 DlMatrix matrix = DlMatrix::MakeScale({scale, scale, 1});
644 DlPaint paint;
645 paint.setImageFilter(
646 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
647 builder.SaveLayer(std::nullopt, &paint);
648
649 DlPaint rect_paint;
650 rect_paint.setAlpha(0.5 * 255);
651 builder.DrawImage(image, DlPoint(0, 0), DlImageSampling::kLinear,
652 &rect_paint);
653 builder.Restore();
654
655 return builder.Build();
656 };
657
658 ASSERT_TRUE(OpenPlaygroundHere(callback));
659 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [294/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixSaveLayerFilter |
| ) |  |

Definition at line 784 of file aiks_dl_unittests.cc.

784 {
785 DisplayListBuilder builder;
786
787 DlPaint paint;
788 paint.setColor(DlColor::kBlack());
789 builder.DrawPaint(paint);
790 builder.SaveLayer(std::nullopt, nullptr);
791 {
792 paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
793 paint.setBlendMode(DlBlendMode::kPlus);
794 builder.DrawCircle(DlPoint(200, 200), 100, paint);
795 // Should render a second circle, centered on the bottom-right-most edge of
796 // the circle.
797
798 DlMatrix matrix = DlMatrix::MakeTranslation({(200 + 100 * k1OverSqrt2),
799 (200 + 100 * k1OverSqrt2)}) *
800 DlMatrix::MakeScale({0.5, 0.5, 1}) *
801 DlMatrix::MakeTranslation({-200, -200});
802 DlPaint save_paint;
803 save_paint.setImageFilter(
804 DlImageFilter::MakeMatrix(matrix, DlImageSampling::kLinear));
805
806 builder.SaveLayer(std::nullopt, &save_paint);
807
808 DlPaint circle_paint;
809 circle_paint.setColor(DlColor::kGreen().withAlpha(255 * 0.5));
810 circle_paint.setBlendMode(DlBlendMode::kPlus);
811 builder.DrawCircle(DlPoint(200, 200), 100, circle_paint);
812 builder.Restore();
813 }
814 builder.Restore();
815
816 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
817 }

References impeller::k1OverSqrt2.

## ◆ TEST_P() [295/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MipmapGenerationWorksCorrectly |
| ) |  |

Definition at line 481 of file aiks_dl_unittests.cc.

481 {
482 TextureDescriptor texture_descriptor;
483 texture_descriptor.size = ISize{1024, 1024};
484 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
485 texture_descriptor.storage_mode = StorageMode::kHostVisible;
486 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
487
488 std::vector<uint8_t> bytes(4194304);
489 bool alternate = false;
490 for (auto i = 0u; i < 4194304; i += 4) {
491 if (alternate) {
492 bytes[i] = 255;
493 bytes[i + 1] = 0;
494 bytes[i + 2] = 0;
495 bytes[i + 3] = 255;
496 } else {
497 bytes[i] = 0;
498 bytes[i + 1] = 255;
499 bytes[i + 2] = 0;
500 bytes[i + 3] = 255;
501 }
502 alternate = !alternate;
503 }
504
505 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
506 auto mapping = std::make_shared<fml::NonOwnedMapping>(
507 bytes.data(), // data
508 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
509 );
510 auto texture =
511 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
512
513 auto device_buffer =
514 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
515 auto command_buffer = GetContext()->CreateCommandBuffer();
516 auto blit_pass = command_buffer->CreateBlitPass();
517
518 blit_pass->AddCopy(DeviceBuffer::AsBufferView(std::move(device_buffer)),
519 texture);
520 blit_pass->GenerateMipmap(texture);
521 EXPECT_TRUE(blit_pass->EncodeCommands());
522 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
523
524 auto image = DlImageImpeller::Make(texture);
525
526 DisplayListBuilder builder;
527 builder.DrawImageRect(
528 image,
529 DlRect::MakeWH(texture->GetSize().width, texture->GetSize().height),
530 DlRect::MakeLTRB(0, 0, 100, 100), DlImageSampling::kMipmapLinear);
531
532 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
533 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::DlImageImpeller::Make(), impeller::TextureDescriptor::mip_count, impeller::TSize< T >::MipCount(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [296/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MultipleColorWithShadowCache |
| ) |  |

Definition at line 838 of file aiks_dl_text_unittests.cc.

838 {
839 DisplayListBuilder builder;
840 builder.Scale(GetContentScale().x, GetContentScale().y);
841 DlPaint paint;
842 paint.setColor(DlColor::kWhite());
843 builder.DrawPaint(paint);
844
845 AiksContext aiks_context(GetContext(),
846 std::make_shared<TypographerContextSkia>());
847 // Cache empty
848 EXPECT_EQ(aiks_context.GetContentContext()
849 .GetTextShadowCache()
850 .GetCacheSizeForTesting(),
851 0u);
852
853 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
854
855 std::array<DlColor, 4> colors{DlColor::kRed(), DlColor::kGreen(),
856 DlColor::kBlue(), DlColor::kRed()};
857 for (const auto& color : colors) {
858 ASSERT_TRUE(RenderTextInCanvasSkia(
859 GetContext(), builder, "A", kFontFixture,
860 TextRenderOptions{
861 .color = color,
862 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
863 sk_font));
864 }
865
866 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
867
868 // The count of cache entries should match the number of distinct colors
869 // in the list. Repeated usage of a color should not add to the cache.
870 EXPECT_EQ(aiks_context.GetContentContext()
871 .GetTextShadowCache()
872 .GetCacheSizeForTesting(),
873 3u);
874 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [297/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MultipleTextWithShadowCache |
| ) |  |

Definition at line 805 of file aiks_dl_text_unittests.cc.

805 {
806 DisplayListBuilder builder;
807 builder.Scale(GetContentScale().x, GetContentScale().y);
808 DlPaint paint;
809 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
810 builder.DrawPaint(paint);
811
812 AiksContext aiks_context(GetContext(),
813 std::make_shared<TypographerContextSkia>());
814 // Cache empty
815 EXPECT_EQ(aiks_context.GetContentContext()
816 .GetTextShadowCache()
817 .GetCacheSizeForTesting(),
818 0u);
819
820 for (auto i = 0; i < 5; i++) {
821 ASSERT_TRUE(RenderTextInCanvasSkia(
822 GetContext(), builder, "Hello World", kFontFixture,
823 TextRenderOptions{
824 .color = DlColor::kBlue(),
825 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
826 }
827
828 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
829
830 // Text should be cached. Each text gets its own entry as we don't analyze the
831 // strings.
832 EXPECT_EQ(aiks_context.GetContentContext()
833 .GetTextShadowCache()
834 .GetCacheSizeForTesting(),
835 5u);
836 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [298/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NoDimplesInRRectPath |
| ) |  |

Definition at line 2261 of file aiks_dl_basic_unittests.cc.

2261 {
2262 Scalar width = 200.f;
2263 Scalar height = 60.f;
2264 Scalar corner = 1.f;
2265 auto callback = [&]() -> sk_sp<DisplayList> {
2266 if (AiksTest::ImGuiBegin("Controls", nullptr,
2267 ImGuiWindowFlags_AlwaysAutoResize)) {
2268 ImGui::SliderFloat("width", &width, 0, 200);
2269 ImGui::SliderFloat("height", &height, 0, 200);
2270 ImGui::SliderFloat("corner", &corner, 0, 1);
2271 ImGui::End();
2272 }
2273
2274 DisplayListBuilder builder;
2275 builder.Scale(GetContentScale().x, GetContentScale().y);
2276
2277 DlPaint background_paint;
2278 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
2279 builder.DrawPaint(background_paint);
2280
2281 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
2282 std::vector<Scalar> stops = {0.0, 1.0};
2283
2284 DlPaint paint;
2285 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
2286 2, colors.data(), stops.data(),
2287 DlTileMode::kClamp);
2288 paint.setColorSource(gradient);
2289 paint.setColor(DlColor::kWhite());
2290 paint.setDrawStyle(DlDrawStyle::kStroke);
2291 paint.setStrokeWidth(20);
2292
2293 builder.Save();
2294 builder.Translate(100, 100);
2295
2296 Scalar corner_x = ((1 - corner) * 50) + 50;
2297 Scalar corner_y = corner * 50 + 50;
2298 DlRoundRect rrect = DlRoundRect::MakeRectXY(
2299 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
2300 builder.DrawRoundRect(rrect, paint);
2301 builder.Restore();
2302 return builder.Build();
2303 };
2304 ASSERT_TRUE(OpenPlaygroundHere(callback));
2305 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [299/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectly |
| ) |  |

Definition at line 1022 of file aiks_dl_basic_unittests.cc.

1022 {
1023 DisplayListBuilder builder;
1024 builder.Scale(GetContentScale().x, GetContentScale().y);
1025 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1026
1027 DlPaint paint;
1028 paint.setColor(DlColor::kBlue());
1029
1030 RenderArcFarm(builder, paint,
1031 {
1032 .use_center = false,
1033 .full_circles = false,
1034 .vertical_scale = 0.8f,
1035 });
1036
1037 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1038 }

References x.

## ◆ TEST_P() [300/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectlyWithCenter |
| ) |  |

Definition at line 1040 of file aiks_dl_basic_unittests.cc.

1040 {
1041 DisplayListBuilder builder;
1042 builder.Scale(GetContentScale().x, GetContentScale().y);
1043 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1044
1045 DlPaint paint;
1046 paint.setColor(DlColor::kBlue());
1047
1048 RenderArcFarm(builder, paint,
1049 {
1050 .use_center = true,
1051 .full_circles = false,
1052 .vertical_scale = 0.8f,
1053 });
1054
1055 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1056 }

References x.

## ◆ TEST_P() [301/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PaintBlendModeIsRespected |
| ) |  |

Definition at line 172 of file aiks_dl_blend_unittests.cc.

172 {
173 DlPaint paint;
174 DisplayListBuilder builder;
175 // Default is kSourceOver.
176
177 paint.setColor(DlColor::RGBA(1, 0, 0, 0.5));
178 builder.DrawCircle(DlPoint(150, 200), 100, paint);
179
180 paint.setColor(DlColor::RGBA(0, 1, 0, 0.5));
181 builder.DrawCircle(DlPoint(250, 200), 100, paint);
182
183 paint.setBlendMode(DlBlendMode::kPlus);
184
185 paint.setColor(DlColor::kRed());
186 builder.DrawCircle(DlPoint(450, 250), 100, paint);
187
188 paint.setColor(DlColor::kGreen());
189 builder.DrawCircle(DlPoint(550, 250), 100, paint);
190
191 paint.setColor(DlColor::kBlue());
192 builder.DrawCircle(DlPoint(500, 150), 100, paint);
193
194 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
195 }

## ◆ TEST_P() [302/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PerspectiveRectangle |
| ) |  |

Definition at line 2335 of file aiks_dl_basic_unittests.cc.

2335 {
2336 int perspective = 58;
2337 bool use_clip = true;
2338 bool diff_clip = false;
2339
2340 auto callback = [&]() -> sk_sp<DisplayList> {
2341 if (AiksTest::ImGuiBegin("Controls", nullptr,
2342 ImGuiWindowFlags_AlwaysAutoResize)) {
2343 ImGui::SliderInt("perspective%", &perspective, 0, 100);
2344 ImGui::Checkbox("use clip", &use_clip);
2345 if (use_clip) {
2346 ImGui::Checkbox("diff clip", &diff_clip);
2347 }
2348 ImGui::SetWindowPos("Controls", ImVec2(500, 100));
2349 ImGui::End();
2350 }
2351
2352 DisplayListBuilder builder;
2353
2354 Scalar val = perspective * -0.00005f;
2355 builder.TransformFullPerspective(
2356 // clang-format off
2357 1.0f, 0.0f, 0.0f, 400.0f,
2358 0.0f, 1.0f, 0.0f, 400.0f,
2359 0.0f, 0.0f, 1.0f, 0.0f,
2360 0.0f, val, 0.0f, 2.2f
2361 // clang-format on
2362 );
2363
2364 if (use_clip) {
2365 Rect clip = DlRect::MakeLTRB(0, 0, 400, 800);
2366 DlClipOp clip_op = DlClipOp::kIntersect;
2367 if (diff_clip) {
2368 clip = clip.Expand(-20);
2369 clip_op = DlClipOp::kDifference;
2370 }
2371 builder.ClipRect(clip, clip_op);
2372 }
2373
2374 DlPaint paint;
2375 paint.setColor(DlColor::kBlue());
2376 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 800), paint);
2377
2378 builder.DrawColor(DlColor::kWhite().withAlphaF(0.5f),
2379 DlBlendMode::kSrcOver);
2380
2381 return builder.Build();
2382 };
2383 ASSERT_TRUE(OpenPlaygroundHere(callback));
2384 }

References impeller::TRect< T >::Expand(), and impeller::AiksPlayground::ImGuiBegin().

## ◆ TEST_P() [303/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PipelineBlendSingleParameter |
| ) |  |

Definition at line 2213 of file aiks_dl_basic_unittests.cc.

2213 {
2214 DisplayListBuilder builder;
2215
2216 // Should render a green square in the middle of a blue circle.
2217 DlPaint paint;
2218 builder.SaveLayer(std::nullopt, &paint);
2219 {
2220 builder.Translate(100, 100);
2221 paint.setColor(DlColor::kBlue());
2222 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2223 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
2224
2225 paint.setColor(DlColor::kGreen());
2226 paint.setBlendMode(DlBlendMode::kSrcOver);
2227 paint.setImageFilter(DlImageFilter::MakeColorFilter(
2228 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
2229 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2230 builder.Restore();
2231 }
2232
2233 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2234 }

## ◆ TEST_P() [304/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ReleasesTextureOnTeardown |
| ) |  |

Definition at line 594 of file aiks_dl_unittests.cc.

594 {
595 auto context = MakeContext();
596 std::weak_ptr<Texture> weak_texture;
597
598 {
599 auto texture = CreateTextureForFixture("table_mountain_nx.png");
600 weak_texture = texture;
601
602 DisplayListBuilder builder;
603 builder.Scale(GetContentScale().x, GetContentScale().y);
604 builder.Translate(100.0f, 100.0f);
605
606 DlPaint paint;
607 paint.setColorSource(DlColorSource::MakeImage(
608 DlImageImpeller::Make(texture), DlTileMode::kClamp, DlTileMode::kClamp,
609 DlImageSampling::kLinear, nullptr));
610
611 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
612
613 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
614 }
615
616 // See https://github.com/flutter/flutter/issues/134751.
617 //
618 // If the fence waiter was working this may not be released by the end of the
619 // scope above. Adding a manual shutdown so that future changes to the fence
620 // waiter will not flake this test.
621 context->Shutdown();
622
623 // The texture should be released by now.
624 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
625 "by the backend, it should be "
626 "released.";
627 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [305/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RotateColorFilteredPath |
| ) |  |

Definition at line 27 of file aiks_dl_path_unittests.cc.

27 {
28 DisplayListBuilder builder;
29 builder.Transform(DlMatrix::MakeTranslation(DlPoint(300, 300)) *
30 DlMatrix::MakeRotationZ(DlDegrees(90)));
31
32 DlPathBuilder arrow_stem;
33 DlPathBuilder arrow_head;
34
35 arrow_stem.MoveTo(DlPoint(120, 190)).LineTo(DlPoint(120, 50));
36 arrow_head.MoveTo(DlPoint(50, 120))
37 .LineTo(DlPoint(120, 190))
38 .LineTo(DlPoint(190, 120));
39
40 auto filter =
41 DlColorFilter::MakeBlend(DlColor::kAliceBlue(), DlBlendMode::kSrcIn);
42
43 DlPaint paint;
44 paint.setStrokeWidth(15.0);
45 paint.setStrokeCap(DlStrokeCap::kRound);
46 paint.setStrokeJoin(DlStrokeJoin::kRound);
47 paint.setDrawStyle(DlDrawStyle::kStroke);
48 paint.setColorFilter(filter);
49 paint.setColor(DlColor::kBlack());
50
51 builder.DrawPath(arrow_stem.TakePath(), paint);
52 builder.DrawPath(arrow_head.TakePath(), paint);
53
54 auto dl = builder.Build();
55 ASSERT_TRUE(OpenPlaygroundHere(dl));
56 }

## ◆ TEST_P() [306/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RoundSuperellipseShadowComparison |
| ) |  |

Definition at line 392 of file canvas_unittests.cc.

392 {
393 // Config
394 Size default_size(600, 400);
395 Point left_center(400, 700);
396 Point right_center(1300, 700);
397 Color color = Color::Red();
398
399 // Convert `color` to a `color_source`. This forces
400 // `canvas.DrawRoundSuperellipse` to use the regular shadow algorithm
401 // (blurring) instead of the fast shadow algorithm.
402 std::shared_ptr<flutter::DlColorSource> color_source;
403 {
404 flutter::DlColor dl_color = flutter::DlColor(color.ToARGB());
405 std::vector<flutter::DlColor> colors = {dl_color, dl_color};
406 std::vector<Scalar> stops = {0.0, 1.0};
407 color_source = flutter::DlColorSource::MakeLinear(
408 {0, 0}, {1000, 1000}, 2, colors.data(), stops.data(),
409 flutter::DlTileMode::kClamp);
410 }
411
412 auto RectMakeCenterHalfSize = [](Point center, Point half_size) {
413 Size size(half_size.x * 2, half_size.y * 2);
414 return Rect::MakeOriginSize(center - half_size, size);
415 };
416
417 RenderCallback callback = [&](RenderTarget& render_target) {
418 ContentContext context(GetContext(), nullptr);
419 Canvas canvas(context, render_target, true, false);
420 // Somehow there's a scaling factor between PlaygroundPoint and Canvas.
421 Matrix ctm = Matrix::MakeScale(Vector2(1, 1) * 0.5);
422 Matrix i_ctm = ctm.Invert();
423
424 static Scalar sigma = 0.05;
425 static Scalar radius = 200;
426
427 // Define the ImGui
428 ImGui::Begin("Shadow", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
429 {
430 ImGui::SliderFloat("Sigma", &sigma, 0, 100);
431 ImGui::SliderFloat("Radius", &radius, 0, 1000);
432 }
433 ImGui::End();
434
435 static PlaygroundPoint right_reference_var(
436 ctm * (right_center + default_size / 2), 30, Color::White());
437 Point right_reference = i_ctm * DrawPlaygroundPoint(right_reference_var);
438 Point half_size = (right_reference - right_center).Abs();
439 Rect left_bounds = RectMakeCenterHalfSize(left_center, half_size);
440 Rect right_bounds = RectMakeCenterHalfSize(right_center, half_size);
441
442 Paint paint{
443 .color = color,
444 .mask_blur_descriptor =
445 Paint::MaskBlurDescriptor{
446 .sigma = Sigma(sigma),
447 },
448 };
449
450 // Left: Draw with canvas
451 canvas.DrawRoundSuperellipse(
452 RoundSuperellipse::MakeRectRadius(left_bounds, radius), paint);
453
454 // Right: Direct draw
455 paint.color_source = color_source.get();
456 canvas.DrawRoundSuperellipse(
457 RoundSuperellipse::MakeRectRadius(right_bounds, radius), paint);
458
459 canvas.EndReplay();
460 return true;
461 };
462
463 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
464 }

References impeller::Paint::color, impeller::DrawPlaygroundPoint(), impeller::Canvas::DrawRoundSuperellipse(), impeller::Canvas::EndReplay(), impeller::Matrix::Invert(), impeller::TRect< Scalar >::MakeOriginSize(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::Matrix::MakeScale(), impeller::Playground::OpenPlaygroundHere(), impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::sigma, impeller::Color::ToARGB(), and impeller::Color::White().

## ◆ TEST_P() [307/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RuntimeEffectImageFilterRotated |
| ) |  |

Definition at line 476 of file aiks_dl_runtime_effect_unittests.cc.

476 {
477 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
478 auto size = image->GetBounds().GetSize();
479
480 struct FragUniforms {
481 Size size;
482 } frag_uniforms = {.size = Size(size.width, size.height)};
483 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
484 uniform_data->resize(sizeof(FragUniforms));
485 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
486
487 auto runtime_stages_result = OpenAssetAsRuntimeStage("gradient.frag.iplr");
488 ABSL_ASSERT_OK(runtime_stages_result);
489 std::shared_ptr<RuntimeStage> runtime_stage =
490 runtime_stages_result
491 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
492 ASSERT_TRUE(runtime_stage);
493 ASSERT_TRUE(runtime_stage->IsDirty());
494
495 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
496 nullptr,
497 };
498
499 auto runtime_filter = DlImageFilter::MakeRuntimeEffect(
500 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
501 uniform_data);
502
503 Scalar rotation = 45;
504
505 auto callback = [&]() -> sk_sp<DisplayList> {
506 if (AiksTest::ImGuiBegin("Controls", nullptr,
507 ImGuiWindowFlags_AlwaysAutoResize)) {
508 ImGui::SliderFloat("rotation", &rotation, 0, 360);
509 ImGui::End();
510 }
511 DisplayListBuilder builder;
512 builder.Translate(size.width * 0.5, size.height * 0.5);
513 builder.Rotate(rotation);
514 builder.Translate(-size.width * 0.5, -size.height * 0.5);
515
516 DlPaint paint;
517 paint.setImageFilter(runtime_filter);
518 builder.DrawImage(image, DlPoint(0.0, 0.0),
519 DlImageSampling::kNearestNeighbor, &paint);
520
521 return builder.Build();
522 };
523
524 ASSERT_TRUE(OpenPlaygroundHere(callback));
525 }

References impeller::AiksPlayground::ImGuiBegin(), flutter::DlRuntimeEffectImpeller::Make(), impeller::DlImageImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [308/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RuntimeEffectVectorArray |
| ) |  |

Definition at line 527 of file aiks_dl_runtime_effect_unittests.cc.

527 {
528 constexpr float kDimension = 400.0f;
529 struct FragUniforms {
530 Vector2 iResolution;
531 Vector4 iValues;
532 } frag_uniforms = {.iResolution = Vector2(kDimension, kDimension),
533 .iValues = Vector4(0.25, 0.50, 0.75, 1.0)};
534 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
535 uniform_data->resize(sizeof(FragUniforms));
536 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
537
538 DlPaint paint;
539 auto effect = MakeRuntimeEffect(this, "runtime_stage_vector_array.frag.iplr",
540 uniform_data);
541 ABSL_ASSERT_OK(effect);
542 paint.setColorSource(effect.value());
543
544 DisplayListBuilder builder;
545 builder.DrawRect(DlRect::MakeXYWH(0, 0, kDimension, kDimension), paint);
546
547 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
548 }

## ◆ TEST_P() [309/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RuntimeEffectWithInvalidSamplerDoesNotCrash |
| ) |  |

Definition at line 128 of file aiks_dl_runtime_effect_unittests.cc.

128 {
129 ScopedValidationDisable disable_validation;
130
131 // Create a sampler that is not usable as an input to the runtime effect.
132 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
133 flutter::DlColor::kRed()};
134 const float stops[2] = {0.0, 1.0};
135 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
136 2, colors.data(), stops,
137 flutter::DlTileMode::kClamp);
138 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
139 linear,
140 };
141
142 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
143 uniform_data->resize(sizeof(Vector2));
144
145 DlPaint paint;
146 auto effect =
147 MakeRuntimeEffect(this, "runtime_stage_filter_example.frag.iplr",
148 uniform_data, sampler_inputs);
149 ABSL_ASSERT_OK(effect);
150 paint.setColorSource(effect.value());
151
152 DisplayListBuilder builder;
153 builder.DrawPaint(paint);
154
155 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
156 }

## ◆ TEST_P() [310/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerDrawsBehindSubsequentEntities |
| ) |  |

Definition at line 2068 of file aiks_dl_basic_unittests.cc.

2068 {
2069 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
2070 DisplayListBuilder builder;
2071 DlPaint paint;
2072
2073 paint.setColor(DlColor::kBlack());
2074 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
2075 builder.DrawRect(rect, paint);
2076
2077 builder.Translate(10, 10);
2078
2079 DlPaint save_paint;
2080 builder.SaveLayer(std::nullopt, &save_paint);
2081
2082 paint.setColor(DlColor::kGreen());
2083 builder.DrawRect(rect, paint);
2084
2085 builder.Restore();
2086
2087 builder.Translate(10, 10);
2088 paint.setColor(DlColor::kRed());
2089 builder.DrawRect(rect, paint);
2090
2091 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2092 }

## ◆ TEST_P() [311/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerFiltersScaleWithTransform |
| ) |  |

Definition at line 2160 of file aiks_dl_basic_unittests.cc.

2160 {
2161 DisplayListBuilder builder;
2162
2163 builder.Scale(GetContentScale().x, GetContentScale().y);
2164 builder.Translate(100, 100);
2165
2166 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
2167 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
2168 builder.SaveLayer(std::nullopt, &paint);
2169 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
2170 builder.Restore();
2171 };
2172
2173 DlPaint effect_paint;
2174 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
2175 draw_image_layer(effect_paint);
2176
2177 builder.Translate(300, 300);
2178 builder.Scale(3, 3);
2179 draw_image_layer(effect_paint);
2180
2181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2182 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [312/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaledK |
| ) |  |

Definition at line 175 of file aiks_dl_text_unittests.cc.

175 {
176 DisplayListBuilder builder;
177 DlPaint paint;
178 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
179 builder.DrawPaint(paint);
180 for (int i = 0; i < 6; ++i) {
181 builder.Save();
182 builder.Translate(300 * i, 0);
183 Scalar scale = 0.445 - (i / 1000.f);
184 builder.Scale(scale, scale);
185 RenderTextInCanvasSkia(
186 GetContext(), builder, "k", "Roboto-Regular.ttf",
187 TextRenderOptions{.font_size = 600, .position = DlPoint(10, 500)});
188 RenderTextInCanvasSkia(
189 GetContext(), builder, "k", "Roboto-Regular.ttf",
190 TextRenderOptions{.font_size = 300, .position = DlPoint(10, 800)});
191 builder.Restore();
192 }
193 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
194 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [313/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaleExperimentAntialiasLines |
| ) |  |

Definition at line 628 of file aiks_dl_path_unittests.cc.

628 {
629 Scalar scale = 5.0;
630 Scalar line_width = 10.f;
631 auto callback = [&]() -> sk_sp<DisplayList> {
632 if (AiksTest::ImGuiBegin("Controls", nullptr,
633 ImGuiWindowFlags_AlwaysAutoResize)) {
634 ImGui::SliderFloat("Scale", &scale, 0.001, 5);
635 ImGui::SliderFloat("Width", &line_width, 1, 20);
636
637 ImGui::End();
638 }
639 DisplayListBuilder builder;
640 builder.Scale(GetContentScale().x, GetContentScale().y);
641
642 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
643
644 {
645 DlPaint paint;
646 paint.setColor(DlColor::kGreenYellow());
647 paint.setStrokeWidth(line_width);
648
649 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 100), paint);
650 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 150), paint);
651
652 builder.Save();
653 builder.Translate(100, 300);
654 builder.Scale(scale, scale);
655 builder.Translate(-100, -300);
656 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 300), paint);
657 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 450), paint);
658 builder.Restore();
659 }
660
661 {
662 DlPaint paint;
663 paint.setColor(DlColor::kGreenYellow());
664 paint.setStrokeWidth(2.0);
665
666 builder.Save();
667 builder.Translate(100, 500);
668 builder.Scale(0.2, 0.2);
669 builder.Translate(-100, -500);
670 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 500), paint);
671 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 650), paint);
672 builder.Restore();
673 }
674
675 return builder.Build();
676 };
677 ASSERT_TRUE(OpenPlaygroundHere(callback));
678 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [314/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SetContentsWithRegion |
| ) |  |

Definition at line 560 of file aiks_dl_unittests.cc.

560 {
561 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
562
563 // Replace part of the texture with a red rectangle.
564 std::vector<uint8_t> bytes(100 * 100 * 4);
565 for (auto i = 0u; i < bytes.size(); i += 4) {
566 bytes[i] = 255;
567 bytes[i + 1] = 0;
568 bytes[i + 2] = 0;
569 bytes[i + 3] = 255;
570 }
571 auto mapping =
572 std::make_shared<fml::NonOwnedMapping>(bytes.data(), bytes.size());
573 auto device_buffer =
574 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
575 auto cmd_buffer = GetContext()->CreateCommandBuffer();
576 auto blit_pass = cmd_buffer->CreateBlitPass();
577 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), bridge,
578 IRect::MakeLTRB(50, 50, 150, 150));
579
580 auto did_submit =
581 blit_pass->EncodeCommands() &&
582 GetContext()->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok();
583 ASSERT_TRUE(did_submit);
584
585 auto image = DlImageImpeller::Make(bridge);
586
587 DisplayListBuilder builder;
588 builder.DrawImage(image, DlPoint(0, 0), {});
589
590 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
591 }

References impeller::DeviceBuffer::AsBufferView(), impeller::DlImageImpeller::Make(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST_P() [315/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SiblingSaveLayerBoundsAreRespected |
| ) |  |

Definition at line 2094 of file aiks_dl_basic_unittests.cc.

2094 {
2095 DisplayListBuilder builder;
2096 DlPaint paint;
2097 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
2098
2099 // Black, green, and red squares offset by [10, 10].
2100 {
2101 DlPaint save_paint;
2102 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
2103 builder.SaveLayer(bounds, &save_paint);
2104 paint.setColor(DlColor::kBlack());
2105 builder.DrawRect(rect, paint);
2106 builder.Restore();
2107 }
2108
2109 {
2110 DlPaint save_paint;
2111 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
2112 builder.SaveLayer(bounds, &save_paint);
2113 paint.setColor(DlColor::kGreen());
2114 builder.DrawRect(rect, paint);
2115 builder.Restore();
2116 }
2117
2118 {
2119 DlPaint save_paint;
2120 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
2121 builder.SaveLayer(bounds, &save_paint);
2122 paint.setColor(DlColor::kRed());
2123 builder.DrawRect(rect, paint);
2124 builder.Restore();
2125 }
2126
2127 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2128 }

## ◆ TEST_P() [316/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SimpleExperimentAntialiasLines |
| ) |  |

Definition at line 743 of file aiks_dl_path_unittests.cc.

743 {
744 DisplayListBuilder builder;
745 builder.Scale(GetContentScale().x, GetContentScale().y);
746
747 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
748
749 DlPaint paint;
750 paint.setColor(DlColor::kGreenYellow());
751 paint.setStrokeWidth(10);
752
753 auto draw = [&builder](DlPaint& paint) {
754 for (auto cap :
755 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
756 paint.setStrokeCap(cap);
757 DlPoint origin = {100, 100};
758 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
759 for (int d = 15; d < 90; d += 15) {
760 Matrix m = Matrix::MakeRotationZ(Degrees(d));
761 Point origin = {100, 100};
762 Point p0 = {50, 0};
763 Point p1 = {150, 0};
764 auto a = origin + m * p0;
765 auto b = origin + m * p1;
766
767 builder.DrawLine(a, b, paint);
768 }
769 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
770 builder.DrawCircle(origin, 35, paint);
771
772 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
773
774 builder.Translate(250, 0);
775 }
776 builder.Translate(-750, 250);
777 };
778
779 draw(paint);
780
781 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782 }

References impeller::saturated::b, impeller::Matrix::MakeRotationZ(), p1, and x.

## ◆ TEST_P() [317/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SingleIconShadowTest |
| ) |  |

Definition at line 876 of file aiks_dl_text_unittests.cc.

876 {
877 DisplayListBuilder builder;
878 builder.Scale(GetContentScale().x, GetContentScale().y);
879 DlPaint paint;
880 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
881 builder.DrawPaint(paint);
882
883 AiksContext aiks_context(GetContext(),
884 std::make_shared<TypographerContextSkia>());
885 // Cache empty
886 EXPECT_EQ(aiks_context.GetContentContext()
887 .GetTextShadowCache()
888 .GetCacheSizeForTesting(),
889 0u);
890
891 // Create font instance outside loop so all draws use identical font instance.
892 auto c_font_fixture = std::string(kFontFixture);
893 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
894 ASSERT_TRUE(mapping);
895 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
896 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
897
898 for (auto i = 0; i < 10; i++) {
899 ASSERT_TRUE(RenderTextInCanvasSkia(
900 GetContext(), builder, "A", kFontFixture,
901 TextRenderOptions{
902 .color = DlColor::kBlue(),
903 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
904 sk_font));
905 }
906
907 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
908
909 // Text should be cached. All 10 glyphs use the same cache entry.
910 EXPECT_EQ(aiks_context.GetContentContext()
911 .GetTextShadowCache()
912 .GetCacheSizeForTesting(),
913 1u);
914 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [318/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCircleMaskBlurTinySigma |
| ) |  |

Definition at line 129 of file aiks_dl_blur_unittests.cc.

129 {
130 DisplayListBuilder builder;
131 builder.Scale(GetContentScale().x, GetContentScale().y);
132
133 std::vector<float> sigmas = {0.0, 0.01, 1.0};
134 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
135 DlColor::kRed()};
136 for (uint32_t i = 0; i < sigmas.size(); ++i) {
137 DlPaint paint;
138 paint.setColor(colors[i]);
139 paint.setMaskFilter(
140 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
141
142 builder.Save();
143 builder.Translate(100 + (i * 100), 100);
144 DlRoundRect rrect = DlRoundRect::MakeRectXY(
145 DlRect::MakeXYWH(0, 0, 100.0f, 100.0f), 100, 100);
146 builder.DrawRoundRect(rrect, paint);
147 builder.Restore();
148 }
149
150 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
151 }

References x.

## ◆ TEST_P() [319/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCirclesOvalsRRectsMaskBlurCorrectly |
| ) |  |

Definition at line 1430 of file aiks_dl_basic_unittests.cc.

1430 {
1431 DisplayListBuilder builder;
1432 builder.Scale(GetContentScale().x, GetContentScale().y);
1433 DlPaint paint;
1434 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
1435
1436 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1437
1438 paint.setColor(
1439 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
1440 Scalar y = 100.0f;
1441 for (int i = 0; i < 5; i++) {
1442 Scalar x = (i + 1) * 100;
1443 Scalar radius = x / 10.0f;
1444 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1445 radius, 60.0f - radius),
1446 paint);
1447 }
1448
1449 paint.setColor(DlColor::kBlue());
1450 y += 100.0f;
1451 for (int i = 0; i < 5; i++) {
1452 Scalar x = (i + 1) * 100;
1453 Scalar radius = x / 10.0f;
1454 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
1455 }
1456
1457 paint.setColor(DlColor::kGreen());
1458 y += 100.0f;
1459 for (int i = 0; i < 5; i++) {
1460 Scalar x = (i + 1) * 100;
1461 Scalar radius = x / 10.0f;
1462 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1463 radius, 60.0f - radius),
1464 paint);
1465 }
1466
1467 paint.setColor(
1468 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
1469 y += 100.0f;
1470 for (int i = 0; i < 5; i++) {
1471 Scalar x = (i + 1) * 100;
1472 Scalar radius = x / 20.0f;
1473 builder.DrawRoundRect(
1474 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1475 radius, radius),
1476 paint);
1477 }
1478
1479 paint.setColor(
1480 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
1481 y += 100.0f;
1482 for (int i = 0; i < 5; i++) {
1483 Scalar x = (i + 1) * 100;
1484 Scalar radius = x / 20.0f;
1485 builder.DrawRoundRect(
1486 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1487 radius, 5.0f),
1488 paint);
1489 }
1490
1491 auto dl = builder.Build();
1492 ASSERT_TRUE(OpenPlaygroundHere(dl));
1493 }

References x.

## ◆ TEST_P() [320/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorOvalsMaskBlurTinySigma |
| ) |  |

Definition at line 39 of file aiks_dl_blur_unittests.cc.

39 {
40 DisplayListBuilder builder;
41 builder.Scale(GetContentScale().x, GetContentScale().y);
42
43 std::vector<float> sigmas = {0.0, 0.01, 1.0};
44 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
45 DlColor::kRed()};
46 for (uint32_t i = 0; i < sigmas.size(); ++i) {
47 DlPaint paint;
48 paint.setColor(colors[i]);
49 paint.setMaskFilter(
50 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
51
52 builder.Save();
53 builder.Translate(100 + (i * 100), 100);
54 DlRoundRect rrect =
55 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 60.0f, 160.0f), 50, 100);
56 builder.DrawRoundRect(rrect, paint);
57 builder.Restore();
58 }
59
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61 }

References x.

## ◆ TEST_P() [321/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidStrokesRenderCorrectly |
| ) |  |

Definition at line 473 of file aiks_dl_path_unittests.cc.

473 {
474 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
475 auto callback = [&]() -> sk_sp<DisplayList> {
476 static Color color = Color::Black().WithAlpha(0.5);
477 static float scale = 3;
478 static bool add_circle_clip = true;
479
480 if (AiksTest::ImGuiBegin("Controls", nullptr,
481 ImGuiWindowFlags_AlwaysAutoResize)) {
482 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
483 ImGui::SliderFloat("Scale", &scale, 0, 6);
484 ImGui::Checkbox("Circle clip", &add_circle_clip);
485 ImGui::End();
486 }
487
488 DisplayListBuilder builder;
489 builder.Scale(GetContentScale().x, GetContentScale().y);
490 DlPaint paint;
491
492 paint.setColor(DlColor::kWhite());
493 builder.DrawPaint(paint);
494
495 paint.setColor(
496 DlColor::ARGB(color.alpha, color.red, color.green, color.blue));
497 paint.setDrawStyle(DlDrawStyle::kStroke);
498 paint.setStrokeWidth(10);
499
500 DlPathBuilder path_builder;
501 path_builder.MoveTo(DlPoint(20, 20));
502 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
503 path_builder.Close();
504 path_builder.MoveTo(DlPoint(60, 20));
505 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
506 DlPath path = path_builder.TakePath();
507
508 builder.Scale(scale, scale);
509
510 if (add_circle_clip) {
511 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
512 Color::Red());
513 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
514 Color::Red());
515 auto [handle_a, handle_b] =
516 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
517
518 Matrix screen_to_canvas = builder.GetMatrix();
519 if (!screen_to_canvas.IsInvertible()) {
520 return nullptr;
521 }
522 screen_to_canvas = screen_to_canvas.Invert();
523
524 Point point_a = screen_to_canvas * handle_a;
525 Point point_b = screen_to_canvas * handle_b;
526
527 Point middle = point_a + point_b;
528 middle *= GetContentScale().x / 2;
529
530 auto radius = point_a.GetDistance(middle);
531
532 builder.ClipPath(DlPath::MakeCircle(middle, radius));
533 }
534
535 for (auto join :
536 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
537 paint.setStrokeJoin(join);
538 for (auto cap :
539 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
540 paint.setStrokeCap(cap);
541 builder.DrawPath(path, paint);
542 builder.Translate(80, 0);
543 }
544 builder.Translate(-240, 60);
545 }
546
547 return builder.Build();
548 };
549
550 ASSERT_TRUE(OpenPlaygroundHere(callback));
551 }
impeller::TPoint::x
Type x
Definition: point.h:31

References impeller::Color::alpha, impeller::Color::Black(), impeller::Color::blue, impeller::DrawPlaygroundLine(), impeller::TPoint< T >::GetDistance(), impeller::Color::green, impeller::AiksPlayground::ImGuiBegin(), impeller::Matrix::Invert(), impeller::Matrix::IsInvertible(), impeller::Color::red, impeller::Color::Red(), impeller::Color::WithAlpha(), x, and impeller::TPoint< T >::x.

## ◆ TEST_P() [322/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SrgbToLinearFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 122 of file aiks_dl_unittests.cc.

122 {
123 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
124
125 DlPaint paint;
126 paint.setColorFilter(DlColorFilter::MakeLinearToSrgbGamma());
127 builder.SaveLayer(std::nullopt, &paint);
128
129 builder.Translate(500, 300);
130 builder.Rotate(120); // 120 deg
131
132 DlPaint draw_paint;
133 draw_paint.setColor(DlColor::kBlue());
134 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), draw_paint);
135
136 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
137 }

## ◆ TEST_P() [323/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokeCapsAndJoins |
| ) |  |

Definition at line 987 of file aiks_dl_path_unittests.cc.

987 {
988 DisplayListBuilder builder;
989 builder.Scale(GetContentScale().x, GetContentScale().y);
990
991 builder.Translate(100, 0);
992
993 builder.Save();
994 for (auto cap : std::vector<DlStrokeCap>{
995 DlStrokeCap::kButt, DlStrokeCap::kRound, DlStrokeCap::kSquare}) {
996 DlPathBuilder path_builder;
997 path_builder.MoveTo({20, 50});
998 path_builder.LineTo({50, 50});
999 path_builder.MoveTo({120, 50});
1000 path_builder.LineTo({120, 80});
1001 path_builder.MoveTo({180, 50});
1002 path_builder.LineTo({180, 50});
1003 DlPath path = path_builder.TakePath();
1004
1005 DlPaint paint;
1006 paint.setColor(DlColor::kRed());
1007 paint.setDrawStyle(DlDrawStyle::kStroke);
1008 paint.setStrokeWidth(20.0f);
1009 paint.setStrokeCap(cap);
1010 paint.setStrokeJoin(DlStrokeJoin::kBevel);
1011
1012 builder.DrawPath(path, paint);
1013
1014 paint.setColor(DlColor::kYellow());
1015 paint.setStrokeWidth(1.0f);
1016 paint.setStrokeCap(DlStrokeCap::kButt);
1017
1018 builder.DrawPath(path, paint);
1019
1020 builder.Translate(250, 0);
1021 }
1022 builder.Restore();
1023
1024 builder.Translate(0, 100);
1025
1026 builder.Save();
1027 for (auto join : std::vector<DlStrokeJoin>{
1028 DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
1029 DlPathBuilder path_builder;
1030 path_builder.MoveTo({20, 50}); // 0 degree right turn
1031 path_builder.LineTo({50, 50});
1032 path_builder.LineTo({80, 50});
1033 path_builder.MoveTo({20, 150}); // 90 degree right turn
1034 path_builder.LineTo({50, 150});
1035 path_builder.LineTo({50, 180});
1036 path_builder.MoveTo({20, 250}); // 45 degree right turn
1037 path_builder.LineTo({50, 250});
1038 path_builder.LineTo({70, 270});
1039 path_builder.MoveTo({20, 350}); // 135 degree right turn
1040 path_builder.LineTo({50, 350});
1041 path_builder.LineTo({30, 370});
1042 path_builder.MoveTo({20, 450}); // 180 degree right turn
1043 path_builder.LineTo({50, 450});
1044 path_builder.LineTo({20, 450});
1045 path_builder.MoveTo({120, 80}); // 0 degree left turn
1046 path_builder.LineTo({150, 80});
1047 path_builder.LineTo({180, 80});
1048 path_builder.MoveTo({120, 180}); // 90 degree left turn
1049 path_builder.LineTo({150, 180});
1050 path_builder.LineTo({150, 150});
1051 path_builder.MoveTo({120, 280}); // 45 degree left turn
1052 path_builder.LineTo({150, 280});
1053 path_builder.LineTo({170, 260});
1054 path_builder.MoveTo({120, 380}); // 135 degree left turn
1055 path_builder.LineTo({150, 380});
1056 path_builder.LineTo({130, 360});
1057 path_builder.MoveTo({120, 480}); // 180 degree left turn
1058 path_builder.LineTo({150, 480});
1059 path_builder.LineTo({120, 480});
1060 DlPath path = path_builder.TakePath();
1061
1062 DlPaint paint;
1063
1064 paint.setColor(DlColor::kRed());
1065 paint.setDrawStyle(DlDrawStyle::kStroke);
1066 paint.setStrokeWidth(20.0f);
1067 paint.setStrokeCap(DlStrokeCap::kSquare);
1068 paint.setStrokeJoin(join);
1069 builder.DrawPath(path, paint);
1070
1071 paint.setColor(DlColor::kYellow());
1072 paint.setStrokeWidth(1.0f);
1073 paint.setStrokeCap(DlStrokeCap::kButt);
1074 builder.DrawPath(path, paint);
1075
1076 builder.Translate(250, 0);
1077 }
1078 builder.Restore();
1079
1080 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1081 }

References x.

## ◆ TEST_P() [324/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsCoverFullArcWithButtEnds |
| ) |  |

Definition at line 1281 of file aiks_dl_basic_unittests.cc.

1281 {
1282 // This test compares the rendering of a full circle arc against a partial
1283 // arc by drawing a one over the other in high contrast. If the partial
1284 // arc misses any pixels that were drawn by the full arc, there will be
1285 // some "pixel dirt" around the missing "erased" parts of the arcs. This
1286 // case arises while rendering a CircularProgressIndicator with a background
1287 // color where we want the rendering of the background full arc to hit the
1288 // same pixels around the edges as the partial arc that covers it.
1289 //
1290 // In this case we draw a full blue circle and then draw a partial arc
1291 // over it in the background color (white).
1292
1293 DisplayListBuilder builder;
1294 builder.Scale(GetContentScale().x, GetContentScale().y);
1295 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1296
1297 DlPaint paint;
1298 paint.setDrawStyle(DlDrawStyle::kStroke);
1299 paint.setStrokeWidth(6.0f);
1300 paint.setStrokeCap(DlStrokeCap::kButt);
1301 paint.setColor(DlColor::kBlue());
1302
1303 // First draw full circles in blue to establish the pixels to be erased
1304 RenderArcFarm(builder, paint,
1305 {
1306 .use_center = false,
1307 .full_circles = true,
1308 });
1309
1310 paint.setColor(DlColor::kWhite());
1311
1312 // Then draw partial arcs in white over the circles to "erase" them
1313 RenderArcFarm(builder, paint,
1314 {
1315 .use_center = false,
1316 .full_circles = false,
1317 });
1318
1319 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1320 }

References x.

## ◆ TEST_P() [325/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter |
| ) |  |

Definition at line 1148 of file aiks_dl_basic_unittests.cc.

1148 {
1149 DisplayListBuilder builder;
1150 builder.Scale(GetContentScale().x, GetContentScale().y);
1151 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1152
1153 DlPaint paint;
1154 paint.setDrawStyle(DlDrawStyle::kStroke);
1155 paint.setStrokeWidth(6.0f);
1156 paint.setStrokeJoin(DlStrokeJoin::kBevel);
1157 paint.setColor(DlColor::kBlue());
1158
1159 RenderArcFarm(builder, paint,
1160 {
1161 .use_center = true,
1162 .full_circles = false,
1163 .sweeps_over_360 = true,
1164 });
1165
1166 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1167 }

References x.

## ◆ TEST_P() [326/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithButtEnds |
| ) |  |

Definition at line 1058 of file aiks_dl_basic_unittests.cc.

1058 {
1059 DisplayListBuilder builder;
1060 builder.Scale(GetContentScale().x, GetContentScale().y);
1061 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1062
1063 DlPaint paint;
1064 paint.setDrawStyle(DlDrawStyle::kStroke);
1065 paint.setStrokeWidth(6.0f);
1066 paint.setStrokeCap(DlStrokeCap::kButt);
1067 paint.setColor(DlColor::kBlue());
1068
1069 RenderArcFarm(builder, paint,
1070 {
1071 .use_center = false,
1072 .full_circles = false,
1073 });
1074
1075 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1076 }

References x.

## ◆ TEST_P() [327/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter |
| ) |  |

Definition at line 1169 of file aiks_dl_basic_unittests.cc.

1169 {
1170 DisplayListBuilder builder;
1171 builder.Scale(GetContentScale().x, GetContentScale().y);
1172 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1173
1174 DlPaint paint;
1175 paint.setDrawStyle(DlDrawStyle::kStroke);
1176 paint.setStrokeWidth(6.0f);
1177 paint.setStrokeJoin(DlStrokeJoin::kMiter);
1178 // Default miter of 4.0 does a miter on all of the centers, but
1179 // using 3.0 will show some bevels on the widest interior angles...
1180 paint.setStrokeMiter(3.0f);
1181 paint.setColor(DlColor::kBlue());
1182
1183 RenderArcFarm(builder, paint,
1184 {
1185 .use_center = true,
1186 .full_circles = false,
1187 .sweeps_over_360 = true,
1188 });
1189
1190 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1191 }

References x.

## ◆ TEST_P() [328/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundEnds |
| ) |  |

Definition at line 1113 of file aiks_dl_basic_unittests.cc.

1113 {
1114 DisplayListBuilder builder;
1115 builder.Scale(GetContentScale().x, GetContentScale().y);
1116 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1117
1118 DlPaint paint;
1119 paint.setDrawStyle(DlDrawStyle::kStroke);
1120 paint.setStrokeWidth(6.0f);
1121 paint.setStrokeCap(DlStrokeCap::kRound);
1122 paint.setColor(DlColor::kBlue());
1123
1124 RenderArcFarm(builder, paint,
1125 {
1126 .use_center = false,
1127 .full_circles = false,
1128 });
1129
1130 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1131 }

References x.

## ◆ TEST_P() [329/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter |
| ) |  |

Definition at line 1193 of file aiks_dl_basic_unittests.cc.

1193 {
1194 DisplayListBuilder builder;
1195 builder.Scale(GetContentScale().x, GetContentScale().y);
1196 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1197
1198 DlPaint paint;
1199 paint.setDrawStyle(DlDrawStyle::kStroke);
1200 paint.setStrokeWidth(6.0f);
1201 paint.setStrokeJoin(DlStrokeJoin::kRound);
1202 paint.setColor(DlColor::kBlue());
1203
1204 RenderArcFarm(builder, paint,
1205 {
1206 .use_center = true,
1207 .full_circles = false,
1208 .sweeps_over_360 = true,
1209 });
1210
1211 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1212 }

References x.

## ◆ TEST_P() [330/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds |
| ) |  |

Definition at line 1243 of file aiks_dl_basic_unittests.cc.

1243 {
1244 DisplayListBuilder builder;
1245 builder.Scale(GetContentScale().x, GetContentScale().y);
1246 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1247
1248 DlPaint paint;
1249 paint.setDrawStyle(DlDrawStyle::kStroke);
1250 paint.setStrokeWidth(8.0f);
1251 paint.setStrokeCap(DlStrokeCap::kSquare);
1252 paint.setColor(DlColor::kRed());
1253
1254 RenderArcFarm(builder, paint,
1255 {
1256 .use_center = false,
1257 .full_circles = false,
1258 });
1259
1260 paint.setStrokeCap(DlStrokeCap::kRound);
1261 paint.setColor(DlColor::kGreen());
1262
1263 RenderArcFarm(builder, paint,
1264 {
1265 .use_center = false,
1266 .full_circles = false,
1267 });
1268
1269 paint.setStrokeCap(DlStrokeCap::kButt);
1270 paint.setColor(DlColor::kBlue());
1271
1272 RenderArcFarm(builder, paint,
1273 {
1274 .use_center = false,
1275 .full_circles = false,
1276 });
1277
1278 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1279 }

References x.

## ◆ TEST_P() [331/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtEnds |
| ) |  |

Definition at line 1214 of file aiks_dl_basic_unittests.cc.

1214 {
1215 DisplayListBuilder builder;
1216 builder.Scale(GetContentScale().x, GetContentScale().y);
1217 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1218
1219 DlPaint paint;
1220 paint.setDrawStyle(DlDrawStyle::kStroke);
1221 paint.setStrokeWidth(8.0f);
1222 paint.setStrokeCap(DlStrokeCap::kSquare);
1223 paint.setColor(DlColor::kRed());
1224
1225 RenderArcFarm(builder, paint,
1226 {
1227 .use_center = false,
1228 .full_circles = false,
1229 });
1230
1231 paint.setStrokeCap(DlStrokeCap::kButt);
1232 paint.setColor(DlColor::kBlue());
1233
1234 RenderArcFarm(builder, paint,
1235 {
1236 .use_center = false,
1237 .full_circles = false,
1238 });
1239
1240 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1241 }

References x.

## ◆ TEST_P() [332/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareEnds |
| ) |  |

Definition at line 1078 of file aiks_dl_basic_unittests.cc.

1078 {
1079 DisplayListBuilder builder;
1080 builder.Scale(GetContentScale().x, GetContentScale().y);
1081 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1082
1083 DlPaint paint;
1084 paint.setDrawStyle(DlDrawStyle::kStroke);
1085 paint.setStrokeWidth(6.0f);
1086 paint.setStrokeCap(DlStrokeCap::kSquare);
1087 paint.setColor(DlColor::kBlue());
1088
1089 RenderArcFarm(builder, paint,
1090 {
1091 .use_center = false,
1092 .full_circles = false,
1093 });
1094
1095 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1096 }

References x.

## ◆ TEST_P() [333/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithTranslucencyAndRoundEnds |
| ) |  |

Definition at line 1133 of file aiks_dl_basic_unittests.cc.

1133 {
1134 DisplayListBuilder builder;
1135 builder.Scale(GetContentScale().x, GetContentScale().y);
1136 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1137
1138 DlPaint paint;
1139 paint.setDrawStyle(DlDrawStyle::kStroke);
1140 paint.setStrokeCap(DlStrokeCap::kRound);
1141 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1142
1143 RenderArcFarmForOverlappingCapsTest(builder, paint);
1144
1145 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1146 }

References x.

## ◆ TEST_P() [334/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithTranslucencyAndSquareEnds |
| ) |  |

Definition at line 1098 of file aiks_dl_basic_unittests.cc.

1098 {
1099 DisplayListBuilder builder;
1100 builder.Scale(GetContentScale().x, GetContentScale().y);
1101 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1102
1103 DlPaint paint;
1104 paint.setDrawStyle(DlDrawStyle::kStroke);
1105 paint.setStrokeCap(DlStrokeCap::kSquare);
1106 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1107
1108 RenderArcFarmForOverlappingCapsTest(builder, paint);
1109
1110 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1111 }

References x.

## ◆ TEST_P() [335/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedCirclesRenderCorrectly |
| ) |  |

Definition at line 689 of file aiks_dl_basic_unittests.cc.

689 {
690 DisplayListBuilder builder;
691 builder.Scale(GetContentScale().x, GetContentScale().y);
692 DlPaint paint;
693 const int color_count = 3;
694 DlColor colors[color_count] = {
695 DlColor::kBlue(),
696 DlColor::kGreen(),
697 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
698 };
699
700 paint.setColor(DlColor::kWhite());
701 builder.DrawPaint(paint);
702
703 int c_index = 0;
704
705 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, DlPoint center,
706 Scalar r, Scalar dr, int n) {
707 for (int i = 0; i < n; i++) {
708 paint.setColor(colors[(c_index++) % color_count]);
709 canvas.DrawCircle(center, r, paint);
710 r += dr;
711 }
712 };
713
714 paint.setDrawStyle(DlDrawStyle::kStroke);
715 paint.setStrokeWidth(1);
716 draw(builder, DlPoint(10, 10), 2, 2, 14); // r = [2, 28], covers [1,29]
717 paint.setStrokeWidth(5);
718 draw(builder, DlPoint(10, 10), 35, 10, 56); // r = [35, 585], covers [30,590]
719
720 DlColor gradient_colors[7] = {
721 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
722 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
723 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
724 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
725 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
726 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
727 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
728 };
729 DlScalar stops[7] = {
730 0.0,
731 (1.0 / 6.0) * 1,
732 (1.0 / 6.0) * 2,
733 (1.0 / 6.0) * 3,
734 (1.0 / 6.0) * 4,
735 (1.0 / 6.0) * 5,
736 1.0,
737 };
738 auto texture = CreateTextureForFixture("airplane.jpg",
739 /*enable_mipmapping=*/true);
740 auto image = DlImageImpeller::Make(texture);
741
742 paint.setColorSource(DlColorSource::MakeRadial(
743 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
744 draw(builder, DlPoint(500, 600), 5, 10, 10);
745
746 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
747 paint.setColorSource(DlColorSource::MakeImage(
748 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
749 DlImageSampling::kNearestNeighbor, &local_matrix));
750 draw(builder, DlPoint(800, 300), 5, 10, 10);
751
752 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
753 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [336/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedPathWithLargeStrokeWidthRendersCorrectly |
| ) |  |

Definition at line 845 of file aiks_dl_basic_unittests.cc.

845 {
846 DrawStrokedAndFilledCirclesWithZoom(this, /*zoom=*/1.0f, /*radius=*/1.0f,
847 /*stroke_width=*/5.0f);
848 }

## ◆ TEST_P() [337/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedPathWithMoveToThenCloseDrawnCorrectly |
| ) |  |

Definition at line 536 of file aiks_dl_unittests.cc.

536 {
537 DlPathBuilder path_builder;
538 path_builder.MoveTo(DlPoint(0, 400))
539 .LineTo(DlPoint(0, 0))
540 .LineTo(DlPoint(400, 0))
541 // MoveTo implicitly adds a contour, ensure that close doesn't
542 // add another nearly-empty contour.
543 .MoveTo(DlPoint(0, 400))
544 .Close();
545 DlPath path = path_builder.TakePath();
546
547 DisplayListBuilder builder;
548 builder.Translate(50, 50);
549
550 DlPaint paint;
551 paint.setColor(DlColor::kBlue());
552 paint.setStrokeCap(DlStrokeCap::kRound);
553 paint.setStrokeWidth(10);
554 paint.setDrawStyle(DlDrawStyle::kStroke);
555 builder.DrawPath(path, paint);
556
557 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
558 }

## ◆ TEST_P() [338/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedRectsRenderCorrectly |
| ) |  |

Definition at line 493 of file aiks_dl_basic_unittests.cc.

493 {
494 DisplayListBuilder builder;
495 builder.Scale(GetContentScale().x, GetContentScale().y);
496
497 DlPaint paint;
498 paint.setColor(DlColor::kPurple());
499 paint.setDrawStyle(DlDrawStyle::kStroke);
500 paint.setStrokeWidth(20.0f);
501
502 DlPaint thin_paint = paint;
503 thin_paint.setColor(DlColor::kYellow());
504 thin_paint.setStrokeWidth(0.0f);
505
506 DlRect rect = DlRect::MakeLTRB(10, 10, 90, 90);
507 DlRect thin_tall_rect = DlRect::MakeLTRB(120, 10, 120, 90);
508 DlRect thin_wide_rect = DlRect::MakeLTRB(10, 120, 90, 120);
509 DlRect empty_rect = DlRect::MakeLTRB(120, 120, 120, 120);
510
511 // We draw the following sets of rectangles:
512 //
513 // A E X
514 // X
515 // B F X
516 // X
517 // C D G H X
518 //
519 // Purple A,B,C,D are all drawn with stroke width 20 (non-overflowing).
520 // Each of those sets has 4 rectangles of dimension 80x80, 80x0, 0x80,
521 // and 0,0 to demonstrate the basic behavior and also the behavior of
522 // empty dimensions.
523 //
524 // Blue E,F,G,H are the same 80x80 rectangles, but with an overflowing
525 // stroke width of 120 to show the behavior with degenerately large
526 // stroke widths.
527 //
528 // A,E are drawn with Bevel joins.
529 // B,F are drawn with Round joins.
530 // C,G are drawn with Miter joins and a large enough miter limit.
531 // D,H are drawn with Miter joins and a too small miter limit (== Bevel).
532 //
533 // All orange X rectangles are drawn with round joins and increasing stroke
534 // widths to demonstrate fidelity of the rounding code at various arc sizes.
535 // These X rectangles also help test that the variable sizing estimates in
536 // the round join code are accurate.
537
538 // rects (A)
539 paint.setStrokeJoin(DlStrokeJoin::kBevel);
540 builder.DrawRect(rect.Shift({100, 100}), paint);
541 builder.DrawRect(rect.Shift({100, 100}), thin_paint);
542 builder.DrawRect(thin_tall_rect.Shift({100, 100}), paint);
543 builder.DrawRect(thin_tall_rect.Shift({100, 100}), thin_paint);
544 builder.DrawRect(thin_wide_rect.Shift({100, 100}), paint);
545 builder.DrawRect(thin_wide_rect.Shift({100, 100}), thin_paint);
546 builder.DrawRect(empty_rect.Shift({100, 100}), paint);
547 builder.DrawRect(empty_rect.Shift({100, 100}), thin_paint);
548
549 // rects (B)
550 paint.setStrokeJoin(DlStrokeJoin::kRound);
551 builder.DrawRect(rect.Shift({100, 300}), paint);
552 builder.DrawRect(rect.Shift({100, 300}), thin_paint);
553 builder.DrawRect(thin_tall_rect.Shift({100, 300}), paint);
554 builder.DrawRect(thin_tall_rect.Shift({100, 300}), thin_paint);
555 builder.DrawRect(thin_wide_rect.Shift({100, 300}), paint);
556 builder.DrawRect(thin_wide_rect.Shift({100, 300}), thin_paint);
557 builder.DrawRect(empty_rect.Shift({100, 300}), paint);
558 builder.DrawRect(empty_rect.Shift({100, 300}), thin_paint);
559
560 // rects (C)
561 paint.setStrokeJoin(DlStrokeJoin::kMiter);
562 paint.setStrokeMiter(kSqrt2 + flutter::kEhCloseEnough);
563 builder.DrawRect(rect.Shift({100, 500}), paint);
564 builder.DrawRect(rect.Shift({100, 500}), thin_paint);
565 builder.DrawRect(thin_tall_rect.Shift({100, 500}), paint);
566 builder.DrawRect(thin_tall_rect.Shift({100, 500}), thin_paint);
567 builder.DrawRect(thin_wide_rect.Shift({100, 500}), paint);
568 builder.DrawRect(thin_wide_rect.Shift({100, 500}), thin_paint);
569 builder.DrawRect(empty_rect.Shift({100, 500}), paint);
570 builder.DrawRect(empty_rect.Shift({100, 500}), thin_paint);
571
572 // rects (D)
573 paint.setStrokeJoin(DlStrokeJoin::kMiter);
574 paint.setStrokeMiter(kSqrt2 - flutter::kEhCloseEnough);
575 builder.DrawRect(rect.Shift({300, 500}), paint);
576 builder.DrawRect(rect.Shift({300, 500}), thin_paint);
577 builder.DrawRect(thin_tall_rect.Shift({300, 500}), paint);
578 builder.DrawRect(thin_tall_rect.Shift({300, 500}), thin_paint);
579 builder.DrawRect(thin_wide_rect.Shift({300, 500}), paint);
580 builder.DrawRect(thin_wide_rect.Shift({300, 500}), thin_paint);
581 builder.DrawRect(empty_rect.Shift({300, 500}), paint);
582 builder.DrawRect(empty_rect.Shift({300, 500}), thin_paint);
583
584 paint.setStrokeWidth(120.0f);
585 paint.setColor(DlColor::kBlue());
586 rect = rect.Expand(-20);
587
588 // rect (E)
589 paint.setStrokeJoin(DlStrokeJoin::kBevel);
590 builder.DrawRect(rect.Shift({500, 100}), paint);
591 builder.DrawRect(rect.Shift({500, 100}), thin_paint);
592
593 // rect (F)
594 paint.setStrokeJoin(DlStrokeJoin::kRound);
595 builder.DrawRect(rect.Shift({500, 300}), paint);
596 builder.DrawRect(rect.Shift({500, 300}), thin_paint);
597
598 // rect (G)
599 paint.setStrokeJoin(DlStrokeJoin::kMiter);
600 paint.setStrokeMiter(kSqrt2 + flutter::kEhCloseEnough);
601 builder.DrawRect(rect.Shift({500, 500}), paint);
602 builder.DrawRect(rect.Shift({500, 500}), thin_paint);
603
604 // rect (H)
605 paint.setStrokeJoin(DlStrokeJoin::kMiter);
606 paint.setStrokeMiter(kSqrt2 - flutter::kEhCloseEnough);
607 builder.DrawRect(rect.Shift({700, 500}), paint);
608 builder.DrawRect(rect.Shift({700, 500}), thin_paint);
609
610 DlPaint round_mock_paint;
611 round_mock_paint.setColor(DlColor::kGreen());
612 round_mock_paint.setDrawStyle(DlDrawStyle::kFill);
613
614 // array of rects (X)
615 Scalar x = 900;
616 Scalar y = 50;
617 for (int i = 0; i < 15; i++) {
618 paint.setStrokeWidth(i);
619 paint.setColor(DlColor::kOrange());
620 paint.setStrokeJoin(DlStrokeJoin::kRound);
621 builder.DrawRect(DlRect::MakeXYWH(x, y, 30, 30), paint);
622 y += 32 + i;
623 }
624
625 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
626 }

References impeller::kEhCloseEnough, impeller::kSqrt2, and x.

## ◆ TEST_P() [339/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SubpassWithClearColorOptimization |
| ) |  |

Definition at line 1668 of file aiks_dl_basic_unittests.cc.

1668 {
1669 DisplayListBuilder builder;
1670
1671 // Use a non-srcOver blend mode to ensure that we don't detect this as an
1672 // opacity peephole optimization.
1673 DlPaint paint;
1674 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1675 paint.setBlendMode(DlBlendMode::kSrc);
1676
1677 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
1678 builder.SaveLayer(bounds, &paint);
1679
1680 paint.setColor(DlColor::kTransparent());
1681 paint.setBlendMode(DlBlendMode::kSrc);
1682 builder.DrawPaint(paint);
1683 builder.Restore();
1684
1685 paint.setColor(DlColor::kBlue());
1686 paint.setBlendMode(DlBlendMode::kDstOver);
1687 builder.SaveLayer(std::nullopt, &paint);
1688 builder.Restore();
1689
1690 // This playground should appear blank on CI since we are only drawing
1691 // transparent black. If the clear color optimization is broken, the texture
1692 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
1693 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1694 }

## ◆ TEST_P() [340/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SupportsBlitToOnscreen |
| ) |  |

Definition at line 380 of file canvas_unittests.cc.

380 {
381 ContentContext context(GetContext(), nullptr);
382 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
383 /*requires_readback=*/true);
384
385 if (GetBackend() != PlaygroundBackend::kMetal) {
386 EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
387 } else {
388 EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
389 }
390 }

References CreateTestCanvas(), impeller::kMetal, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [341/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextContentsMismatchedTransformTest |
| ) |  |

Definition at line 709 of file aiks_dl_text_unittests.cc.

709 {
710 AiksContext aiks_context(GetContext(),
711 std::make_shared<TypographerContextSkia>());
712
713 // Verifies that TextContents only use the scale/transform that is
714 // computed during preroll.
715 constexpr const char* font_fixture = "Roboto-Regular.ttf";
716
717 // Construct the text blob.
718 auto c_font_fixture = std::string(font_fixture);
719 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
720 ASSERT_TRUE(mapping);
721
722 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
723 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
724
725 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
726 ASSERT_TRUE(blob);
727
728 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
729
730 // Simulate recording the text frame during preroll.
731 Matrix preroll_matrix =
732 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
733 Point preroll_point = Point{23, 45};
734 {
735 auto scale = TextFrame::RoundScaledFontSize(
736 (preroll_matrix * Matrix::MakeTranslation(preroll_point))
737 .GetMaxBasisLengthXY());
738
739 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
740 text_frame, //
741 scale, //
742 preroll_point, //
743 preroll_matrix,
744 std::nullopt //
745 );
746 }
747
748 // Now simulate rendering with a slightly different scale factor.
749 RenderTarget render_target =
750 aiks_context.GetContentContext()
751 .GetRenderTargetCache()
752 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
753
754 TextContents text_contents;
755 text_contents.SetTextFrame(text_frame);
756 text_contents.SetOffset(preroll_point);
757 text_contents.SetScale(1.6);
758 text_contents.SetColor(Color::Aqua());
759
760 Matrix not_preroll_matrix =
761 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
762
763 Entity entity;
764 entity.SetTransform(not_preroll_matrix);
765
766 std::shared_ptr<CommandBuffer> command_buffer =
767 aiks_context.GetContext()->CreateCommandBuffer();
768 std::shared_ptr<RenderPass> render_pass =
769 command_buffer->CreateRenderPass(render_target);
770
771 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
772 *render_pass));
773 }

References impeller::AiksContext::GetContentContext(), impeller::AiksContext::GetContext(), impeller::ContentContext::GetLazyGlyphAtlas(), impeller::ContentContext::GetRenderTargetCache(), impeller::MakeTextFrameFromTextBlobSkia(), impeller::TextContents::Render(), impeller::TextContents::SetColor(), impeller::TextContents::SetOffset(), impeller::TextContents::SetScale(), impeller::TextContents::SetTextFrame(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [342/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextForegroundShaderWithTransform |
| ) |  |

Definition at line 594 of file aiks_dl_text_unittests.cc.

594 {
595 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
596 ASSERT_NE(mapping, nullptr);
597
598 Scalar font_size = 100;
599 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
600 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
601
602 DlPaint text_paint;
603 text_paint.setColor(DlColor::kBlue());
604
605 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
606 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
607 std::vector<Scalar> stops = {
608 0.0,
609 1.0,
610 };
611 text_paint.setColorSource(DlColorSource::MakeLinear(
612 /*start_point=*/DlPoint(0, 0), //
613 /*end_point=*/DlPoint(100, 100), //
614 /*stop_count=*/2, //
615 /*colors=*/colors.data(), //
616 /*stops=*/stops.data(), //
617 /*tile_mode=*/DlTileMode::kRepeat //
618 ));
619
620 DisplayListBuilder builder;
621 builder.Translate(100, 100);
622 builder.Rotate(45);
623
624 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
625 ASSERT_NE(blob, nullptr);
626 auto frame = MakeTextFrameFromTextBlobSkia(blob);
627 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
628
629 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
630 }

References font_size, flutter::DlTextImpeller::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [343/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextFrameSubpixelAlignment |
| ) |  |

Definition at line 318 of file aiks_dl_text_unittests.cc.

318 {
319 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
320 std::array<Scalar, 20> phase_offsets = {
321 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
322 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
323 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
324 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
325 auto callback = [&]() -> sk_sp<DisplayList> {
326 static float font_size = 20;
327 static float phase_variation = 0.2;
328 static float speed = 0.5;
329 static float magnitude = 100;
330 if (AiksTest::ImGuiBegin("Controls", nullptr,
331 ImGuiWindowFlags_AlwaysAutoResize)) {
332 ImGui::SliderFloat("Font size", &font_size, 5, 50);
333 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
334 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
335 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
336 ImGui::End();
337 }
338
339 DisplayListBuilder builder;
340 builder.Scale(GetContentScale().x, GetContentScale().y);
341
342 for (size_t i = 0; i < phase_offsets.size(); i++) {
343 DlPoint position = DlPoint(
344 200 +
345 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
346 GetSecondsElapsed() * speed)), //
347 200 + i * font_size * 1.1 //
348 );
349 if (!RenderTextInCanvasSkia(
350 GetContext(), builder,
351 "the quick brown fox jumped over "
352 "the lazy dog!.?",
353 "Roboto-Regular.ttf",
354 {.font_size = font_size, .position = position})) {
355 return nullptr;
356 }
357 }
358 return builder.Build();
359 };
360
361 ASSERT_TRUE(OpenPlaygroundHere(callback));
362 }

References font_size, impeller::k2Pi, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [344/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated |
| ) |  |

Definition at line 490 of file aiks_dl_text_unittests.cc.

490 {
491 DisplayListBuilder builder;
492
493 builder.Scale(GetContentScale().x, GetContentScale().y);
494 DlPaint paint;
495 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
496 builder.DrawPaint(paint);
497
498 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
499 0, 0.5, 0, 0, //
500 0, 0, 0.3, 0, //
501 100, 100, 0, 1.3));
502 ASSERT_TRUE(RenderTextInCanvasSkia(
503 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
504 "Roboto-Regular.ttf"));
505
506 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
507 }

References RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [345/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated180Degrees |
| ) |  |

Definition at line 281 of file aiks_dl_text_unittests.cc.

281 {
282 float fpivot[2] = {200 + 30, 200 - 20};
283 float rotation = 180;
284 float foffset[2] = {200, 200};
285
286 auto callback = [&]() -> sk_sp<DisplayList> {
287 if (AiksTest::ImGuiBegin("Controls", nullptr,
288 ImGuiWindowFlags_AlwaysAutoResize)) {
289 ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
290 ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
291 ImGui::SliderFloat("rotation", &rotation, 0, 360);
292 ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
293 ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
294 ImGui::End();
295 }
296 DisplayListBuilder builder;
297 builder.Scale(GetContentScale().x, GetContentScale().y);
298 builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
299
300 builder.Save();
301 DlPoint pivot = Point(fpivot[0], fpivot[1]);
302 builder.Translate(pivot.x, pivot.y);
303 builder.Rotate(rotation);
304 builder.Translate(-pivot.x, -pivot.y);
305
306 RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
307 TextRenderOptions{
308 .color = DlColor::kBlack(),
309 .position = DlPoint(foffset[0], foffset[1]),
310 });
311
312 builder.Restore();
313 return builder.Build();
314 };
315 ASSERT_TRUE(OpenPlaygroundHere(callback));
316 }

References impeller::testing::TextRenderOptions::color, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [346/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextWithShadowCache |
| ) |  |

Definition at line 775 of file aiks_dl_text_unittests.cc.

775 {
776 DisplayListBuilder builder;
777 builder.Scale(GetContentScale().x, GetContentScale().y);
778 DlPaint paint;
779 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
780 builder.DrawPaint(paint);
781
782 AiksContext aiks_context(GetContext(),
783 std::make_shared<TypographerContextSkia>());
784 // Cache empty
785 EXPECT_EQ(aiks_context.GetContentContext()
786 .GetTextShadowCache()
787 .GetCacheSizeForTesting(),
788 0u);
789
790 ASSERT_TRUE(RenderTextInCanvasSkia(
791 GetContext(), builder, "Hello World", kFontFixture,
792 TextRenderOptions{
793 .color = DlColor::kBlue(),
794 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
795
796 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
797
798 // Text should be cached.
799 EXPECT_EQ(aiks_context.GetContentContext()
800 .GetTextShadowCache()
801 .GetCacheSizeForTesting(),
802 1u);
803 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [347/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ToImageFromImage |
| ) |  |

Definition at line 1042 of file aiks_dl_unittests.cc.

1042 {
1043 DisplayListBuilder builder;
1044 DlPath path = DlPath::MakeArc(DlRect::MakeLTRB(0, 0, 100, 100), DlDegrees(0),
1045 DlDegrees(90),
1046 /*use_center=*/true);
1047
1048 builder.DrawPath(path, DlPaint().setColor(DlColor::kRed()));
1049
1050 AiksContext renderer(GetContext(), nullptr);
1051 auto texture =
1052 DisplayListToTexture(builder.Build(), ISize(100, 100), renderer);
1053
1054 // First, Readback the texture data into a host buffer.
1055 impeller::DeviceBufferDescriptor desc;
1056 desc.size = texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
1057 desc.readback = true;
1058 desc.storage_mode = StorageMode::kHostVisible;
1059
1060 auto device_buffer = GetContext()->GetResourceAllocator()->CreateBuffer(desc);
1061 {
1062 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1063 auto blit_pass = cmd_buffer->CreateBlitPass();
1064
1065 blit_pass->AddCopy(texture, device_buffer);
1066 blit_pass->EncodeCommands();
1067
1068 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1069 GetContext()->GetCommandQueue()->Submit(
1070 {cmd_buffer},
1071 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1072 latch->Wait();
1073 }
1074
1075 impeller::TextureDescriptor tex_desc = texture->GetTextureDescriptor();
1076 auto reupload_texture =
1077 GetContext()->GetResourceAllocator()->CreateTexture(tex_desc);
1078
1079 // Next, Re-upload the data into a new texture.
1080 {
1081 auto cmd_buffer = GetContext()->CreateCommandBuffer();
1082 auto blit_pass = cmd_buffer->CreateBlitPass();
1083 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer),
1084 reupload_texture);
1085 blit_pass->ConvertTextureToShaderRead(texture);
1086 blit_pass->EncodeCommands();
1087
1088 auto latch = std::make_shared<fml::CountDownLatch>(1u);
1089 GetContext()->GetCommandQueue()->Submit(
1090 {cmd_buffer},
1091 [latch](CommandBuffer::Status status) { latch->CountDown(); });
1092 latch->Wait();
1093 }
1094
1095 // Draw the results side by side. These should look the same.
1096 DisplayListBuilder canvas;
1097 DlPaint paint = DlPaint();
1098 canvas.DrawRect(
1099 DlRect::MakeLTRB(0, 0, 100, 100),
1100 DlPaint().setColor(DlColor::kBlue()).setDrawStyle(DlDrawStyle::kStroke));
1101 canvas.DrawImage(DlImageImpeller::Make(texture), DlPoint(0, 0),
1102 DlImageSampling::kNearestNeighbor, &paint);
1103
1104 canvas.DrawRect(
1105 DlRect::MakeLTRB(0, 100, 100, 200),
1106 DlPaint().setColor(DlColor::kRed()).setDrawStyle(DlDrawStyle::kStroke));
1107 canvas.DrawImage(DlImageImpeller::Make(reupload_texture), DlPoint(0, 100),
1108 DlImageSampling::kNearestNeighbor, &paint);
1109 OpenPlaygroundHere(canvas.Build());
1110 }
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::DeviceBufferDescriptor::readback
bool readback
Definition: device_buffer_descriptor.h:19
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16

References impeller::DeviceBuffer::AsBufferView(), impeller::DisplayListToTexture(), impeller::kHostVisible, impeller::DlImageImpeller::Make(), impeller::DeviceBufferDescriptor::readback, impeller::DeviceBufferDescriptor::size, and impeller::DeviceBufferDescriptor::storage_mode.

## ◆ TEST_P() [348/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransformMultipliesCorrectly |
| ) |  |

Definition at line 72 of file canvas_unittests.cc.

72 {
73 ContentContext context(GetContext(), nullptr);
74 auto canvas = CreateTestCanvas(context);
75
76 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
77
78 // clang-format off
79 canvas->Translate(Vector3(100, 200));
80 ASSERT_MATRIX_NEAR(
81 canvas->GetCurrentTransform(),
82 Matrix( 1, 0, 0, 0,
83 0, 1, 0, 0,
84 0, 0, 1, 0,
85 100, 200, 0, 1));
86
87 canvas->Rotate(Radians(kPiOver2));
88 ASSERT_MATRIX_NEAR(
89 canvas->GetCurrentTransform(),
90 Matrix( 0, 1, 0, 0,
91 -1, 0, 0, 0,
92 0, 0, 1, 0,
93 100, 200, 0, 1));
94
95 canvas->Scale(Vector3(2, 3));
96 ASSERT_MATRIX_NEAR(
97 canvas->GetCurrentTransform(),
98 Matrix( 0, 2, 0, 0,
99 -3, 0, 0, 0,
100 0, 0, 0, 0,
101 100, 200, 0, 1));
102
103 canvas->Translate(Vector3(100, 200));
104 ASSERT_MATRIX_NEAR(
105 canvas->GetCurrentTransform(),
106 Matrix( 0, 2, 0, 0,
107 -3, 0, 0, 0,
108 0, 0, 0, 0,
109 -500, 400, 0, 1));
110 // clang-format on
111 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [349/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentFilledArcsRenderCorrectly |
| ) |  |

Definition at line 988 of file aiks_dl_basic_unittests.cc.

988 {
989 DisplayListBuilder builder;
990 builder.Scale(GetContentScale().x, GetContentScale().y);
991 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
992
993 DlPaint paint;
994 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
995
996 RenderArcFarm(builder, paint,
997 {
998 .use_center = false,
999 .full_circles = false,
1000 });
1001
1002 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1003 }

References x.

## ◆ TEST_P() [350/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerDrawsCorrectly |
| ) |  |

Definition at line 139 of file aiks_dl_unittests.cc.

139 {
140 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
141
142 DlPaint paint;
143 paint.setColor(DlColor::kBlue());
144 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300), paint);
145
146 DlPaint save_paint;
147 save_paint.setColor(DlColor::kBlack().withAlpha(128));
148 builder.SaveLayer(std::nullopt, &save_paint);
149 builder.DrawRect(DlRect::MakeXYWH(100, 500, 300, 300), paint);
150 builder.Restore();
151
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153 }

## ◆ TEST_P() [351/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerImageDrawsCorrectly |
| ) |  |

Definition at line 250 of file aiks_dl_unittests.cc.

250 {
251 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
252
253 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
254 builder.DrawImage(image, DlPoint(100, 100), DlImageSampling::kMipmapLinear);
255
256 DlPaint paint;
257 paint.setColor(DlColor::kBlack().withAlpha(128));
258 builder.SaveLayer(std::nullopt, &paint);
259 builder.DrawImage(image, DlPoint(100, 500), DlImageSampling::kMipmapLinear);
260 builder.Restore();
261
262 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
263 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [352/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly |
| ) |  |

Definition at line 335 of file aiks_dl_unittests.cc.

335 {
336 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
337
338 DlPaint paint;
339 paint.setColor(DlColor::kRed());
340 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
341
342 DlPaint save_paint;
343 save_paint.setAlpha(128);
344 save_paint.setBlendMode(DlBlendMode::kLighten);
345 builder.SaveLayer(std::nullopt, &save_paint);
346
347 DlPaint draw_paint;
348 draw_paint.setColor(DlColor::kGreen());
349 builder.DrawCircle(DlPoint(200, 200), 100, draw_paint);
350 builder.Restore();
351
352 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
353 }

## ◆ TEST_P() [353/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly |
| ) |  |

Definition at line 155 of file aiks_dl_unittests.cc.

155 {
156 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
157
158 DlPaint paint;
159 paint.setColor(DlColor::kBlue());
160 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300), paint);
161
162 DlPaint save_paint;
163 paint.setColor(DlColor::kBlack().withAlpha(128));
164 paint.setColorFilter(
165 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
166 builder.Save();
167 builder.ClipRect(DlRect::MakeXYWH(100, 500, 300, 300));
168 builder.SaveLayer(std::nullopt, &paint);
169
170 DlPaint draw_paint;
171 draw_paint.setColor(DlColor::kBlue());
172 builder.DrawRect(DlRect::MakeXYWH(100, 500, 300, 300), draw_paint);
173 builder.Restore();
174 builder.Restore();
175
176 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
177 }

## ◆ TEST_P() [354/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly |
| ) |  |

Definition at line 179 of file aiks_dl_unittests.cc.

179 {
180 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
181
182 DlPaint paint;
183 paint.setColor(DlColor::kBlue());
184 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300), paint);
185
186 DlPaint save_paint;
187 save_paint.setColor(DlColor::kBlack().withAlpha(128));
188 save_paint.setImageFilter(DlImageFilter::MakeColorFilter(
189 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver)));
190
191 builder.SaveLayer(std::nullopt, &save_paint);
192
193 DlPaint draw_paint;
194 draw_paint.setColor(DlColor::kBlue());
195 builder.DrawRect(DlRect::MakeXYWH(100, 500, 300, 300), draw_paint);
196 builder.Restore();
197
198 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
199 }

## ◆ TEST_P() [355/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly |
| ) |  |

Definition at line 201 of file aiks_dl_unittests.cc.

201 {
202 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
203
204 DlPaint paint;
205 paint.setColor(DlColor::kBlue());
206 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300), paint);
207
208 DlPaint save_paint;
209 save_paint.setColor(DlColor::kBlack().withAlpha(128));
210 save_paint.setColorFilter(
211 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kDstOver));
212 builder.Save();
213 builder.ClipRect(DlRect::MakeXYWH(100, 500, 300, 300));
214 builder.SaveLayer(std::nullopt, &save_paint);
215
216 DlPaint draw_paint;
217 draw_paint.setColor(DlColor::kBlue());
218 builder.DrawRect(DlRect::MakeXYWH(100, 500, 300, 300), draw_paint);
219 builder.Restore();
220 builder.Restore();
221
222 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
223 }

## ◆ TEST_P() [356/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly |
| ) |  |

Definition at line 309 of file aiks_dl_unittests.cc.

310 {
311 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
312
313 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
314 builder.DrawImage(image, DlPoint(100, 100), {});
315
316 const float matrix[20] = {
317 1, 0, 0, 0, 0, //
318 0, 1, 0, 0, 0, //
319 0, 0.2, 1, 0, 0, //
320 0, 0, 0, 0.5, 0 //
321 };
322 DlPaint paint;
323 paint.setColor(DlColor::kBlack().withAlpha(128));
324 paint.setImageFilter(
325 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix)));
326 paint.setColorFilter(
327 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kModulate));
328 builder.SaveLayer(std::nullopt, &paint);
329 builder.DrawImage(image, DlPoint(100, 500), {});
330 builder.Restore();
331
332 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
333 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [357/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly |
| ) |  |

Definition at line 265 of file aiks_dl_unittests.cc.

265 {
266 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
267
268 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
269 builder.DrawImage(image, DlPoint(100, 100), {});
270
271 const float matrix[20] = {
272 1, 0, 0, 0, 0, //
273 0, 1, 0, 0, 0, //
274 0, 0, 1, 0, 0, //
275 0, 0, 0, 2, 0 //
276 };
277 DlPaint paint;
278 paint.setColor(DlColor::kBlack().withAlpha(128));
279 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
280 builder.SaveLayer(std::nullopt, &paint);
281 builder.DrawImage(image, DlPoint(100, 500), {});
282 builder.Restore();
283
284 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
285 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [358/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly |
| ) |  |

Definition at line 287 of file aiks_dl_unittests.cc.

287 {
288 DisplayListBuilder builder(DlRect::MakeSize(GetWindowSize()));
289
290 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
291 builder.DrawImage(image, DlPoint(100, 100), {});
292
293 const float matrix[20] = {
294 1, 0, 0, 0, 0, //
295 0, 1, 0, 0, 0, //
296 0, 0, 1, 0, 0, //
297 0, 0, 0, 2, 0 //
298 };
299 DlPaint paint;
300 paint.setColor(DlColor::kBlack().withAlpha(128));
301 paint.setColorFilter(DlColorFilter::MakeMatrix(matrix));
302 builder.SaveLayer(std::nullopt, &paint);
303 builder.DrawImage(image, DlPoint(100, 500), {});
304 builder.Restore();
305
306 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
307 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [359/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransparentShadowProducesCorrectColor |
| ) |  |

Definition at line 858 of file aiks_dl_unittests.cc.

858 {
859 DisplayListBuilder builder;
860 builder.Save();
861 builder.Scale(1.618, 1.618);
862 DlPath path = DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100));
863
864 builder.DrawShadow(path, flutter::DlColor::kTransparent(), 15, false, 1);
865 builder.Restore();
866
867 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }

## ◆ TEST_P() [360/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TwoContourPathWithSinglePointContour |
| ) |  |

Definition at line 967 of file aiks_dl_path_unittests.cc.

967 {
968 DisplayListBuilder builder;
969
970 DlPaint paint;
971 paint.setColor(DlColor::kRed());
972 paint.setDrawStyle(DlDrawStyle::kStroke);
973 paint.setStrokeWidth(15.0);
974 paint.setStrokeCap(DlStrokeCap::kRound);
975
976 DlPathBuilder path_builder;
977 path_builder.MoveTo(DlPoint(100, 100));
978 path_builder.LineTo(DlPoint(150, 150));
979 path_builder.MoveTo(DlPoint(200, 200));
980 path_builder.LineTo(DlPoint(200, 200));
981
982 builder.DrawPath(path_builder.TakePath(), paint);
983
984 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
985 }

## ◆ TEST_P() [361/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VarietyOfTextScalesShowingRasterAndPath |
| ) |  |

Definition at line 916 of file aiks_dl_text_unittests.cc.

916 {
917 DisplayListBuilder builder;
918 DlPaint paint;
919 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
920 builder.DrawPaint(paint);
921 builder.Scale(GetContentScale().x, GetContentScale().y);
922
923 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
924 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
925 Scalar space = 16;
926 Scalar x = 0;
927 for (auto i = 0u; i < scales.size(); i++) {
928 builder.Save();
929 builder.Scale(scales[i], scales[i]);
930 RenderTextInCanvasSkia(
931 GetContext(), builder, "lo", "Roboto-Regular.ttf",
932 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
933 space += spacing[i];
934 if (i == 3) {
935 x = 10;
936 space = 16;
937 }
938 builder.Restore();
939 }
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [362/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerifyNonOptimizedGradient |
| ) |  |

Definition at line 916 of file aiks_dl_gradient_unittests.cc.

916 {
917 DisplayListBuilder builder;
918 DlPaint paint;
919 builder.Translate(100.0f, 0);
920
921 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
922 DlColor::kGreen()};
923 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
924
925 // Inset the start and end point to verify that we do not apply
926 // the fast gradient condition.
927 paint.setColorSource(
928 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
929 stops.data(), DlTileMode::kRepeat));
930
931 paint.setColor(DlColor::kWhite());
932 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
933 builder.Translate(400, 0);
934 builder.DrawRoundRect(
935 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
936
937 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
938 }

## ◆ TEST_P() [363/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionData |
| ) |  |

Definition at line 99 of file aiks_dl_vertices_unittests.cc.

99 {
100 DisplayListBuilder builder;
101 DlPaint paint;
102 auto image =
103 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
104 auto size = image->impeller_texture()->GetSize();
105
106 paint.setColorSource(
107 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
108
109 std::vector<DlPoint> positions = {
110 DlPoint(0, 0), DlPoint(size.width, 0),
111 DlPoint(0, size.height), DlPoint(size.width, 0),
112 DlPoint(0, 0), DlPoint(size.width, size.height),
113 };
114 std::vector<DlColor> colors = {
115 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
116 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
117 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
118 };
119
120 auto vertices =
121 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
122
123 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
124 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
125 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [364/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionDataAdvancedBlend |
| ) |  |

Definition at line 127 of file aiks_dl_vertices_unittests.cc.

127 {
128 DisplayListBuilder builder;
129 DlPaint paint;
130 auto image =
131 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
132 auto size = image->impeller_texture()->GetSize();
133
134 paint.setColorSource(
135 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
136
137 std::vector<DlPoint> positions = {
138 DlPoint(0, 0), DlPoint(size.width, 0),
139 DlPoint(0, size.height), DlPoint(size.width, 0),
140 DlPoint(0, 0), DlPoint(size.width, size.height),
141 };
142 std::vector<DlColor> colors = {
143 DlColor::kRed().modulateOpacity(0.5),
144 DlColor::kBlue().modulateOpacity(0.5),
145 DlColor::kGreen().modulateOpacity(0.5),
146 DlColor::kRed().modulateOpacity(0.5),
147 DlColor::kBlue().modulateOpacity(0.5),
148 DlColor::kGreen().modulateOpacity(0.5),
149 };
150
151 auto vertices =
152 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
153
154 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
155 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
156 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [365/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionData |
| ) |  |

Definition at line 51 of file aiks_dl_vertices_unittests.cc.

51 {
52 DisplayListBuilder builder;
53 DlPaint paint;
54 auto image =
55 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
56 auto size = image->impeller_texture()->GetSize();
57
58 paint.setColorSource(
59 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
60
61 std::vector<DlPoint> vertex_coordinates = {
62 DlPoint(0, 0),
63 DlPoint(size.width, 0),
64 DlPoint(0, size.height),
65 };
66 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
67 {0, 1, 2}, {}, {});
68
69 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
70 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
71 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [366/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionDataWithTranslate |
| ) |  |

Definition at line 74 of file aiks_dl_vertices_unittests.cc.

74 {
75 DisplayListBuilder builder;
76 DlPaint paint;
77 auto image =
78 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
79 auto size = image->impeller_texture()->GetSize();
80
81 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
82 paint.setColorSource(
83 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp,
84 DlImageSampling::kLinear, &matrix));
85
86 std::vector<DlPoint> positions = {
87 DlPoint(0, 0),
88 DlPoint(size.width, 0),
89 DlPoint(0, size.height),
90 };
91 auto vertices =
92 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
93
94 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [367/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryWithMaskFilter |
| ) |  |

Definition at line 559 of file aiks_dl_vertices_unittests.cc.

559 {
560 DisplayListBuilder builder;
561 DlPaint paint;
562 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
563
564 std::vector<DlPoint> vertex_coordinates = {
565 DlPoint(0, 0),
566 DlPoint(400, 0),
567 DlPoint(0, 400),
568 };
569 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
570 {0, 1, 2}, {}, {});
571
572 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
573 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
574 }

## ◆ TEST_P() [368/603]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ZoomedStrokedPathRendersCorrectly |
| ) |  |

Definition at line 840 of file aiks_dl_basic_unittests.cc.

840 {
841 DrawStrokedAndFilledCirclesWithZoom(this, /*zoom=*/80.0f, /*radius=*/2.0f,
842 /*stroke_width=*/0.05f);
843 }

## ◆ TEST_P() [369/603]

impeller::testing::TEST_P | ( | AllocatorMTLTest | ,
|  | DebugTraceMemoryStatistics |
| ) |  |

Definition at line 28 of file allocator_mtl_unittests.mm.

28 {
29 auto& context_mtl = ContextMTL::Cast(*GetContext());
30 const auto& allocator = context_mtl.GetResourceAllocator();
31
32 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
33 0u);
34
35 // Memoryless texture does not increase allocated size.
36 {
37 TextureDescriptor desc;
38 desc.format = PixelFormat::kR8G8B8A8UNormInt;
39 desc.storage_mode = StorageMode::kDeviceTransient;
40 desc.size = {1024, 1024};
41 auto texture_1 = allocator->CreateTexture(desc);
42
43 // Private storage texture increases allocated size.
44 desc.storage_mode = StorageMode::kDevicePrivate;
45 auto texture_2 = allocator->CreateTexture(desc);
46
47 #ifdef IMPELLER_DEBUG
48 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
49 4u);
50 #else
51 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
52 0u);
53 #endif // IMPELLER_DEBUG
54
55 // Host storage texture increases allocated size.
56 desc.storage_mode = StorageMode::kHostVisible;
57 auto texture_3 = allocator->CreateTexture(desc);
58
59 #ifdef IMPELLER_DEBUG
60 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
61 8u);
62 #else
63 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
64 0u);
65 #endif // IMPELLER_DEBUG
66 }
67
68 // After all textures are out of scope, memory has been decremented.
69 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
70 0u);
71 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::TextureDescriptor::format, impeller::AllocationSize< Period >::GetSize(), impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [370/603]

impeller::testing::TEST_P | ( | AllocatorMTLTest | ,
|  | ManagedMemory |
| ) |  |

Definition at line 73 of file allocator_mtl_unittests.mm.

73 {
74 auto& context_mtl = ContextMTL::Cast(*GetContext());
75 auto allocator = std::make_unique<AllocatorMTL>(context_mtl.GetMTLDevice(),
76 "test-allocator");
77 allocator->DebugSetSupportsUMA(false);
78
79 DeviceBufferDescriptor desc;
80 desc.size = 100;
81 desc.storage_mode = StorageMode::kHostVisible;
82
83 auto buffer = allocator->CreateBuffer(desc);
84 ASSERT_TRUE(buffer);
85
86 EXPECT_NE(buffer->OnGetContents(), nullptr);
87 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::kHostVisible, impeller::DeviceBufferDescriptor::size, and impeller::DeviceBufferDescriptor::storage_mode.

## ◆ TEST_P() [371/603]

impeller::testing::TEST_P | ( | BlendFilterContentsTest | ,
|  | AdvancedBlendColorAlignsColorTo4 |
| ) |  |

Definition at line 45 of file blend_filter_contents_unittests.cc.

45 {
46 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
47 BlendFilterContents filter_contents;
48 filter_contents.SetInputs({FilterInput::Make(texture)});
49 filter_contents.SetForegroundColor(Color(1.0, 0.0, 0.0, 1.0));
50 filter_contents.SetBlendMode(BlendMode::kColorDodge);
51
52 std::shared_ptr<ContentContext> renderer = GetContentContext();
53 // Add random byte to get the HostBuffer in a bad alignment.
54 uint8_t byte = 0xff;
55 BufferView buffer_view = renderer->GetTransientsDataBuffer().Emplace(
56 &byte, /*length=*/1, /*align=*/1);
57 EXPECT_EQ(buffer_view.GetRange().offset, 4u);
58 EXPECT_EQ(buffer_view.GetRange().length, 1u);
59 Entity entity;
60
61 std::optional<Entity> result = filter_contents.GetEntity(
62 *renderer, entity, /*coverage_hint=*/std::nullopt);
63
64 EXPECT_TRUE(result.has_value());
65 }

References buffer_view, impeller::FilterContents::GetEntity(), impeller::kColorDodge, impeller::FilterInput::Make(), impeller::BlendFilterContents::SetBlendMode(), impeller::BlendFilterContents::SetForegroundColor(), and impeller::FilterContents::SetInputs().

## ◆ TEST_P() [372/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentPixelFormatsFails |
| ) |  |

Definition at line 30 of file blit_pass_unittests.cc.

30 {
31 ScopedValidationDisable scope; // avoid noise in output.
32 auto context = GetContext();
33 auto cmd_buffer = context->CreateCommandBuffer();
34 auto blit_pass = cmd_buffer->CreateBlitPass();
35
36 TextureDescriptor src_desc;
37 src_desc.format = PixelFormat::kA8UNormInt;
38 src_desc.size = {100, 100};
39 src_desc.storage_mode = StorageMode::kHostVisible;
40 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
41
42 TextureDescriptor dst_format;
43 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
44 dst_format.size = {100, 100};
45 dst_format.storage_mode = StorageMode::kHostVisible;
46 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
47
48 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
49 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [373/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 51 of file blit_pass_unittests.cc.

51 {
52 ScopedValidationDisable scope; // avoid noise in output.
53 auto context = GetContext();
54 auto cmd_buffer = context->CreateCommandBuffer();
55 auto blit_pass = cmd_buffer->CreateBlitPass();
56
57 TextureDescriptor src_desc;
58 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
59 src_desc.sample_count = SampleCount::kCount4;
60 src_desc.size = {100, 100};
61 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
62
63 TextureDescriptor dst_format;
64 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
65 dst_format.size = {100, 100};
66 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
67
68 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
69 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [374/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 71 of file blit_pass_unittests.cc.

71 {
72 ScopedValidationDisable scope; // avoid noise in output.
73 auto context = GetContext();
74 auto cmd_buffer = context->CreateCommandBuffer();
75 auto blit_pass = cmd_buffer->CreateBlitPass();
76
77 TextureDescriptor src_desc;
78 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
79 src_desc.size = {100, 100};
80 src_desc.storage_mode = StorageMode::kHostVisible;
81 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
82
83 TextureDescriptor dst_format;
84 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
85 dst_format.size = {100, 100};
86 dst_format.storage_mode = StorageMode::kHostVisible;
87 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
88
89 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
90 }

References impeller::TextureDescriptor::format, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [375/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitSmallRegionToUninitializedTexture |
| ) |  |

Definition at line 123 of file blit_pass_unittests.cc.

123 {
124 auto context = GetContext();
125 auto cmd_buffer = context->CreateCommandBuffer();
126 auto blit_pass = cmd_buffer->CreateBlitPass();
127
128 TextureDescriptor dst_format;
129 dst_format.storage_mode = StorageMode::kDevicePrivate;
130 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
131 dst_format.size = {1000, 1000};
132 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
133
134 DeviceBufferDescriptor src_format;
135 src_format.size = 4;
136 src_format.storage_mode = StorageMode::kHostVisible;
137 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
138
139 ASSERT_TRUE(dst);
140
141 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
142 IRect::MakeLTRB(0, 0, 1, 1), "",
143 /*mip_level=*/0, /*slice=*/0));
144 EXPECT_TRUE(blit_pass->EncodeCommands());
145 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
146 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< T >::MakeLTRB(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [376/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitToHigherTextureMipLevels |
| ) |  |

Definition at line 176 of file blit_pass_unittests.cc.

176 {
177 auto context = GetContext();
178 auto cmd_buffer = context->CreateCommandBuffer();
179 auto blit_pass = cmd_buffer->CreateBlitPass();
180
181 TextureDescriptor dst_format;
182 dst_format.storage_mode = StorageMode::kDevicePrivate;
183 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
184 dst_format.size = {1000, 1000};
185 dst_format.mip_count = 4;
186 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
187
188 DeviceBufferDescriptor src_format;
189 src_format.size = 4;
190 src_format.storage_mode = StorageMode::kHostVisible;
191 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
192
193 ASSERT_TRUE(dst);
194
195 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
196 IRect::MakeLTRB(0, 0, 1, 1), "",
197 /*mip_level=*/1, /*slice=*/0));
198 EXPECT_TRUE(blit_pass->EncodeCommands());
199 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
200 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< T >::MakeLTRB(), impeller::TextureDescriptor::mip_count, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [377/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanResizeTextures |
| ) |  |

Definition at line 202 of file blit_pass_unittests.cc.

202 {
203 auto context = GetContext();
204 auto cmd_buffer = context->CreateCommandBuffer();
205 auto blit_pass = cmd_buffer->CreateBlitPass();
206
207 TextureDescriptor dst_format;
208 dst_format.storage_mode = StorageMode::kDevicePrivate;
209 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
210 dst_format.size = {10, 10};
211 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
212 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
213
214 TextureDescriptor src_format;
215 src_format.storage_mode = StorageMode::kDevicePrivate;
216 src_format.format = PixelFormat::kR8G8B8A8UNormInt;
217 src_format.size = {100, 100};
218 auto src = context->GetResourceAllocator()->CreateTexture(src_format);
219
220 std::vector<uint8_t> bytes(src_format.GetByteSizeOfBaseMipLevel());
221 for (auto i = 0u; i < src_format.GetByteSizeOfBaseMipLevel(); i += 4) {
222 // RGBA
223 bytes[i + 0] = 255;
224 bytes[i + 1] = 0;
225 bytes[i + 2] = 0;
226 bytes[i + 3] = 255;
227 }
228 auto mapping = fml::DataMapping(bytes);
229 auto staging = context->GetResourceAllocator()->CreateBufferWithCopy(mapping);
230
231 ASSERT_TRUE(dst);
232 ASSERT_TRUE(src);
233 ASSERT_TRUE(staging);
234
235 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(staging), src));
236 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
237 EXPECT_TRUE(blit_pass->EncodeCommands());
238 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
239 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::kShaderRead, impeller::kShaderWrite, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [378/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanResizeTexturesPlayground |
| ) |  |

Definition at line 241 of file blit_pass_unittests.cc.

241 {
242 auto context = GetContext();
243 auto cmd_buffer = context->CreateCommandBuffer();
244 auto blit_pass = cmd_buffer->CreateBlitPass();
245
246 std::shared_ptr<Texture> src = CreateTextureForFixture("kalimba.jpg");
247
248 TextureDescriptor dst_format;
249 dst_format.storage_mode = StorageMode::kDevicePrivate;
250 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
251 dst_format.size = {src->GetSize().width / 2, src->GetSize().height};
252 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
253 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
254
255 ASSERT_TRUE(dst);
256 ASSERT_TRUE(src);
257
258 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
259 EXPECT_TRUE(blit_pass->EncodeCommands());
260 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
261
262 DisplayListBuilder builder;
263 builder.Scale(GetContentScale().x, GetContentScale().y);
264 DlPaint paint;
265 paint.setColor(DlColor::kRed());
266 auto image = DlImageImpeller::Make(dst);
267 builder.DrawImage(image, flutter::DlPoint(100.0, 100.0),
268 DlImageSampling::kNearestNeighbor, &paint);
269 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
270 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kR8G8B8A8UNormInt, impeller::kShaderRead, impeller::kShaderWrite, impeller::DlImageImpeller::Make(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::TextureDescriptor::usage, impeller::TSize< T >::width, and x.

## ◆ TEST_P() [379/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidMipLevelParameter |
| ) |  |

Definition at line 148 of file blit_pass_unittests.cc.

148 {
149 ScopedValidationDisable scope;
150 auto context = GetContext();
151 auto cmd_buffer = context->CreateCommandBuffer();
152 auto blit_pass = cmd_buffer->CreateBlitPass();
153
154 TextureDescriptor dst_format;
155 dst_format.storage_mode = StorageMode::kDevicePrivate;
156 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
157 dst_format.size = {1000, 1000};
158 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
159
160 DeviceBufferDescriptor src_format;
161 src_format.size = 4;
162 src_format.storage_mode = StorageMode::kHostVisible;
163 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
164
165 ASSERT_TRUE(dst);
166
167 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
168 IRect::MakeLTRB(0, 0, 1, 1), "",
169 /*mip_level=*/1, /*slice=*/0));
170
171 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
172 IRect::MakeLTRB(0, 0, 1, 1), "",
173 /*mip_level=*/0, /*slice=*/0));
174 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< T >::MakeLTRB(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [380/603]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidSliceParameters |
| ) |  |

Definition at line 92 of file blit_pass_unittests.cc.

92 {
93 ScopedValidationDisable scope; // avoid noise in output.
94 auto context = GetContext();
95 auto cmd_buffer = context->CreateCommandBuffer();
96 auto blit_pass = cmd_buffer->CreateBlitPass();
97
98 TextureDescriptor dst_format;
99 dst_format.storage_mode = StorageMode::kDevicePrivate;
100 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
101 dst_format.size = {100, 100};
102 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
103
104 DeviceBufferDescriptor src_format;
105 src_format.size = 40000;
106 src_format.storage_mode = StorageMode::kHostVisible;
107 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
108
109 ASSERT_TRUE(dst);
110 ASSERT_TRUE(src);
111
112 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
113 std::nullopt, "", /*mip_level=*/0,
114 /*slice=*/25));
115 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
116 std::nullopt, "", /*mip_level=*/0,
117 /*slice=*/6));
118 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
119 std::nullopt, "", /*mip_level=*/0,
120 /*slice=*/0));
121 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [381/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 184 of file compute_unittests.cc.

184 {
185 using CS = ThreadgroupSizingTestComputeShader;
186 auto context = GetContext();
187 ASSERT_TRUE(context);
188 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
189
190 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
191 auto pipeline_desc =
192 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
193 ASSERT_TRUE(pipeline_desc.has_value());
194 auto compute_pipeline =
195 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
196 ASSERT_TRUE(compute_pipeline);
197
198 auto cmd_buffer = context->CreateCommandBuffer();
199 auto pass = cmd_buffer->CreateComputePass();
200 ASSERT_TRUE(pass && pass->IsValid());
201
202 static constexpr size_t kCount = 2048;
203
204 pass->SetPipeline(compute_pipeline);
205
206 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
207 context, "Output Buffer");
208
209 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
210
211 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
212 ASSERT_TRUE(pass->EncodeCommands());
213
214 fml::AutoResetWaitableEvent latch;
215 ASSERT_TRUE(
216 context->GetCommandQueue()
217 ->Submit({cmd_buffer},
218 [&latch, output_buffer](CommandBuffer::Status status) {
219 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
220
221 auto view = DeviceBuffer::AsBufferView(output_buffer);
222 EXPECT_EQ(view.GetRange().length,
223 sizeof(CS::OutputData<kCount>));
224
225 CS::OutputData<kCount>* output =
226 reinterpret_cast<CS::OutputData<kCount>*>(
227 output_buffer->OnGetContents());
228 EXPECT_TRUE(output);
229 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
230 latch.Signal();
231 })
232 .ok());
233
234 latch.Wait();
235 }

## ◆ TEST_P() [382/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCompute1DimensionalData |
| ) |  |

Definition at line 382 of file compute_unittests.cc.

382 {
383 using CS = SampleComputeShader;
384 auto context = GetContext();
385 auto host_buffer = CreateHostBufferFromContext(context);
386 ASSERT_TRUE(context);
387 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
388
389 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
390 auto pipeline_desc =
391 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
392 ASSERT_TRUE(pipeline_desc.has_value());
393 auto compute_pipeline =
394 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
395 ASSERT_TRUE(compute_pipeline);
396
397 auto cmd_buffer = context->CreateCommandBuffer();
398 auto pass = cmd_buffer->CreateComputePass();
399 ASSERT_TRUE(pass && pass->IsValid());
400
401 static constexpr size_t kCount = 5;
402
403 pass->SetPipeline(compute_pipeline);
404
405 CS::Info info{.count = kCount};
406 CS::Input0<kCount> input_0;
407 CS::Input1<kCount> input_1;
408 for (size_t i = 0; i < kCount; i++) {
409 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
410 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
411 }
412
413 input_0.fixed_array[1] = IPoint32(2, 2);
414 input_1.fixed_array[0] = UintPoint32(3, 3);
415 input_0.some_int = 5;
416 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
417
418 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
419 context, "Output Buffer");
420
421 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
422 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
423 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
424 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
425
426 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
427 ASSERT_TRUE(pass->EncodeCommands());
428
429 fml::AutoResetWaitableEvent latch;
430 ASSERT_TRUE(
431 context->GetCommandQueue()
432 ->Submit(
433 {cmd_buffer},
434 [&latch, output_buffer, &input_0,
435 &input_1](CommandBuffer::Status status) {
436 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
437
438 auto view = DeviceBuffer::AsBufferView(output_buffer);
439 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
440
441 CS::Output<kCount>* output =
442 reinterpret_cast<CS::Output<kCount>*>(
443 output_buffer->OnGetContents());
444 EXPECT_TRUE(output);
445 for (size_t i = 0; i < kCount; i++) {
446 Vector4 vector = output->elements[i];
447 Vector4 computed = input_0.elements[i] * input_1.elements[i];
448 EXPECT_EQ(vector,
449 Vector4(computed.x + 2 + input_1.some_struct.i,
450 computed.y + 3 + input_1.some_struct.vf.x,
451 computed.z + 5 + input_1.some_struct.vf.y,
452 computed.w));
453 }
454 latch.Signal();
455 })
456 .ok());
457
458 latch.Wait();
459 }
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:427
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:428

## ◆ TEST_P() [383/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 118 of file compute_unittests.cc.

118 {
119 using CS = PrefixSumTestComputeShader;
120 auto context = GetContext();
121 auto host_buffer = CreateHostBufferFromContext(context);
122 ASSERT_TRUE(context);
123 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
124
125 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
126 auto pipeline_desc =
127 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
128 ASSERT_TRUE(pipeline_desc.has_value());
129 auto compute_pipeline =
130 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
131 ASSERT_TRUE(compute_pipeline);
132
133 auto cmd_buffer = context->CreateCommandBuffer();
134 auto pass = cmd_buffer->CreateComputePass();
135 ASSERT_TRUE(pass && pass->IsValid());
136
137 static constexpr size_t kCount = 5;
138
139 pass->SetPipeline(compute_pipeline);
140
141 CS::InputData<kCount> input_data;
142 input_data.count = kCount;
143 for (size_t i = 0; i < kCount; i++) {
144 input_data.data[i] = 1 + i;
145 }
146
147 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
148 context, "Output Buffer");
149
150 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
151 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
152
153 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
154 ASSERT_TRUE(pass->EncodeCommands());
155
156 fml::AutoResetWaitableEvent latch;
157 ASSERT_TRUE(
158 context->GetCommandQueue()
159 ->Submit({cmd_buffer},
160 [&latch, output_buffer](CommandBuffer::Status status) {
161 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
162
163 auto view = DeviceBuffer::AsBufferView(output_buffer);
164 EXPECT_EQ(view.GetRange().length,
165 sizeof(CS::OutputData<kCount>));
166
167 CS::OutputData<kCount>* output =
168 reinterpret_cast<CS::OutputData<kCount>*>(
169 output_buffer->OnGetContents());
170 EXPECT_TRUE(output);
171
172 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
173 for (size_t i = 0; i < kCount; i++) {
174 auto computed_sum = output->data[i];
175 EXPECT_EQ(computed_sum, expected[i]);
176 }
177 latch.Signal();
178 })
179 .ok());
180
181 latch.Wait();
182 }

References impeller::DeviceBuffer::AsBufferView().

## ◆ TEST_P() [384/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 237 of file compute_unittests.cc.

237 {
238 using CS = PrefixSumTestComputeShader;
239
240 auto context = GetContext();
241 auto host_buffer = CreateHostBufferFromContext(context);
242
243 ASSERT_TRUE(context);
244 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
245
246 auto callback = [&](RenderPass& render_pass) -> bool {
247 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
248 auto pipeline_desc =
249 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
250 auto compute_pipeline =
251 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
252
253 auto cmd_buffer = context->CreateCommandBuffer();
254 auto pass = cmd_buffer->CreateComputePass();
255
256 static constexpr size_t kCount = 1023;
257
258 pass->SetPipeline(compute_pipeline);
259
260 CS::InputData<kCount> input_data;
261 input_data.count = kCount;
262 for (size_t i = 0; i < kCount; i++) {
263 input_data.data[i] = 1 + i;
264 }
265
266 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
267 context, "Output Buffer");
268
269 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
270 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
271
272 pass->Compute(ISize(kCount, 1));
273 pass->EncodeCommands();
274 host_buffer->Reset();
275 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
276 };
277 ASSERT_TRUE(OpenPlaygroundHere(callback));
278 }

## ◆ TEST_P() [385/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCreateComputePass |
| ) |  |

Definition at line 39 of file compute_unittests.cc.

39 {
40 using CS = SampleComputeShader;
41 auto context = GetContext();
42 auto host_buffer = CreateHostBufferFromContext(context);
43 ASSERT_TRUE(context);
44 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
45
46 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
47 auto pipeline_desc =
48 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
49 ASSERT_TRUE(pipeline_desc.has_value());
50 auto compute_pipeline =
51 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
52 ASSERT_TRUE(compute_pipeline);
53
54 auto cmd_buffer = context->CreateCommandBuffer();
55 auto pass = cmd_buffer->CreateComputePass();
56 ASSERT_TRUE(pass && pass->IsValid());
57
58 static constexpr size_t kCount = 5;
59
60 pass->SetPipeline(compute_pipeline);
61
62 CS::Info info{.count = kCount};
63 CS::Input0<kCount> input_0;
64 CS::Input1<kCount> input_1;
65 for (size_t i = 0; i < kCount; i++) {
66 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
67 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
68 }
69
70 input_0.fixed_array[1] = IPoint32(2, 2);
71 input_1.fixed_array[0] = UintPoint32(3, 3);
72 input_0.some_int = 5;
73 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
74
75 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
76 context, "Output Buffer");
77
78 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
79 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
80 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
81 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
82
83 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
84 ASSERT_TRUE(pass->EncodeCommands());
85
86 fml::AutoResetWaitableEvent latch;
87 ASSERT_TRUE(
88 context->GetCommandQueue()
89 ->Submit(
90 {cmd_buffer},
91 [&latch, output_buffer, &input_0,
92 &input_1](CommandBuffer::Status status) {
93 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
94
95 auto view = DeviceBuffer::AsBufferView(output_buffer);
96 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
97
98 CS::Output<kCount>* output =
99 reinterpret_cast<CS::Output<kCount>*>(
100 output_buffer->OnGetContents());
101 EXPECT_TRUE(output);
102 for (size_t i = 0; i < kCount; i++) {
103 Vector4 vector = output->elements[i];
104 Vector4 computed = input_0.elements[i] * input_1.elements[i];
105 EXPECT_EQ(vector,
106 Vector4(computed.x + 2 + input_1.some_struct.i,
107 computed.y + 3 + input_1.some_struct.vf.x,
108 computed.z + 5 + input_1.some_struct.vf.y,
109 computed.w));
110 }
111 latch.Signal();
112 })
113 .ok());
114
115 latch.Wait();
116 }

References impeller::DeviceBuffer::AsBufferView().

## ◆ TEST_P() [386/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CapabilitiesReportSupport |
| ) |  |

Definition at line 33 of file compute_unittests.cc.

33 {
34 auto context = GetContext();
35 ASSERT_TRUE(context);
36 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
37 }

## ◆ TEST_P() [387/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 280 of file compute_unittests.cc.

280 {
281 using CS1 = Stage1ComputeShader;
282 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
283 using CS2 = Stage2ComputeShader;
284 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
285
286 auto context = GetContext();
287 auto host_buffer = CreateHostBufferFromContext(context);
288 ASSERT_TRUE(context);
289 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
290
291 auto pipeline_desc_1 =
292 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
293 ASSERT_TRUE(pipeline_desc_1.has_value());
294 auto compute_pipeline_1 =
295 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
296 ASSERT_TRUE(compute_pipeline_1);
297
298 auto pipeline_desc_2 =
299 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
300 ASSERT_TRUE(pipeline_desc_2.has_value());
301 auto compute_pipeline_2 =
302 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
303 ASSERT_TRUE(compute_pipeline_2);
304
305 auto cmd_buffer = context->CreateCommandBuffer();
306 auto pass = cmd_buffer->CreateComputePass();
307 ASSERT_TRUE(pass && pass->IsValid());
308
309 static constexpr size_t kCount1 = 5;
310 static constexpr size_t kCount2 = kCount1 * 2;
311
312 CS1::Input<kCount1> input_1;
313 input_1.count = kCount1;
314 for (size_t i = 0; i < kCount1; i++) {
315 input_1.elements[i] = i;
316 }
317
318 CS2::Input<kCount2> input_2;
319 input_2.count = kCount2;
320 for (size_t i = 0; i < kCount2; i++) {
321 input_2.elements[i] = i;
322 }
323
324 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
325 context, "Output Buffer Stage 1");
326 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
327 context, "Output Buffer Stage 2");
328
329 {
330 pass->SetPipeline(compute_pipeline_1);
331
332 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
333 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
334
335 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
336 pass->AddBufferMemoryBarrier();
337 }
338
339 {
340 pass->SetPipeline(compute_pipeline_2);
341
342 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
343 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
344 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
345 }
346
347 ASSERT_TRUE(pass->EncodeCommands());
348
349 fml::AutoResetWaitableEvent latch;
350 ASSERT_TRUE(
351 context->GetCommandQueue()
352 ->Submit({cmd_buffer},
353 [&latch, &output_buffer_1,
354 &output_buffer_2](CommandBuffer::Status status) {
355 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
356
357 CS1::Output<kCount2>* output_1 =
358 reinterpret_cast<CS1::Output<kCount2>*>(
359 output_buffer_1->OnGetContents());
360 EXPECT_TRUE(output_1);
361 EXPECT_EQ(output_1->count, 10u);
362 EXPECT_THAT(
363 output_1->elements,
364 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
365
366 CS2::Output<kCount2>* output_2 =
367 reinterpret_cast<CS2::Output<kCount2>*>(
368 output_buffer_2->OnGetContents());
369 EXPECT_TRUE(output_2);
370 EXPECT_EQ(output_2->count, 10u);
371 EXPECT_THAT(output_2->elements,
372 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
373 18, 16, 24));
374
375 latch.Signal();
376 })
377 .ok());
378
379 latch.Wait();
380 }
impeller::SampleCount::kCount1
@ kCount1

References impeller::kCount1.

## ◆ TEST_P() [388/603]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 461 of file compute_unittests.cc.

461 {
462 using CS = SampleComputeShader;
463 auto context = GetContext();
464 auto host_buffer = CreateHostBufferFromContext(context);
465 ASSERT_TRUE(context);
466 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
467
468 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
469 auto pipeline_desc =
470 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
471 ASSERT_TRUE(pipeline_desc.has_value());
472 auto compute_pipeline =
473 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
474 ASSERT_TRUE(compute_pipeline);
475
476 auto cmd_buffer = context->CreateCommandBuffer();
477 auto pass = cmd_buffer->CreateComputePass();
478 ASSERT_TRUE(pass && pass->IsValid());
479
480 static constexpr size_t kCount = 5;
481
482 pass->SetPipeline(compute_pipeline);
483
484 CS::Info info{.count = kCount};
485 CS::Input0<kCount> input_0;
486 CS::Input1<kCount> input_1;
487 for (size_t i = 0; i < kCount; i++) {
488 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
489 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
490 }
491
492 input_0.fixed_array[1] = IPoint32(2, 2);
493 input_1.fixed_array[0] = UintPoint32(3, 3);
494 input_0.some_int = 5;
495 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
496
497 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
498 context, "Output Buffer");
499
500 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
501 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
502 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
503 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
504
505 // Intentionally making the grid size zero in one dimension. No GPU will
506 // tolerate this.
507 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
508 pass->EncodeCommands();
509 }

## ◆ TEST_P() [389/603]

impeller::testing::TEST_P | ( | ContextMTLTest | ,
|  | FlushTask |
| ) |  |

Definition at line 28 of file context_mtl_unittests.mm.

28 {
29 auto& context_mtl = ContextMTL::Cast(*GetContext());
30
31 int executed = 0;
32 int failed = 0;
33 context_mtl.StoreTaskForGPU([&]() { executed++; }, [&]() { failed++; });
34
35 context_mtl.FlushTasksAwaitingGPU();
36
37 EXPECT_EQ(executed, 1);
38 EXPECT_EQ(failed, 0);
39 }

References impeller::BackendCast< ContextMTL, Context >::Cast().

## ◆ TEST_P() [390/603]

impeller::testing::TEST_P | ( | ContextMTLTest | ,
|  | FlushTaskWithGPULoss |
| ) |  |

Definition at line 41 of file context_mtl_unittests.mm.

41 {
42 auto& context_mtl = ContextMTL::Cast(*GetContext());
43
44 int executed = 0;
45 int failed = 0;
46 context_mtl.StoreTaskForGPU([&]() { executed++; }, [&]() { failed++; });
47
48 // If tasks are flushed while the GPU is disabled, then
49 // they should not be executed.
50 SetGPUDisabled(/*disabled=*/true);
51 context_mtl.FlushTasksAwaitingGPU();
52
53 EXPECT_EQ(executed, 0);
54 EXPECT_EQ(failed, 0);
55
56 // Toggling availibility should flush tasks.
57 SetGPUDisabled(/*disabled=*/false);
58
59 EXPECT_EQ(executed, 1);
60 EXPECT_EQ(failed, 0);
61 }

References impeller::BackendCast< ContextMTL, Context >::Cast().

## ◆ TEST_P() [391/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1271 of file dl_unittests.cc.

1271 {
1272 flutter::DisplayListBuilder builder;
1273
1274 {
1275 builder.SaveLayer(std::nullopt, nullptr);
1276 builder.Translate(100, 100);
1277 flutter::DlPaint paint;
1278 paint.setColor(flutter::DlColor::kRed());
1279 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1280 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1281 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1282 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1283 builder.Restore();
1284 }
1285 {
1286 builder.SaveLayer(std::nullopt, nullptr);
1287 builder.Translate(300, 100);
1288 flutter::DlPaint paint;
1289 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1290 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1291 paint.setColor(flutter::DlColor::kRed());
1292 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1293 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1294 builder.Restore();
1295 }
1296 {
1297 builder.SaveLayer(std::nullopt, nullptr);
1298 builder.Translate(100, 300);
1299 flutter::DlPaint paint;
1300 paint.setColor(flutter::DlColor::kRed());
1301 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1302 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1303 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1304 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1305 builder.Restore();
1306 }
1307 {
1308 builder.SaveLayer(std::nullopt, nullptr);
1309 builder.Translate(300, 300);
1310 flutter::DlPaint paint;
1311 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1312 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1313 paint.setColor(flutter::DlColor::kRed());
1314 paint.setBlendMode(flutter::DlBlendMode::kDst);
1315 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1316 builder.Restore();
1317 }
1318
1319 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1320 }

## ◆ TEST_P() [392/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 626 of file dl_unittests.cc.

626 {
627 auto texture = CreateTextureForFixture("boston.jpg");
628 const float inner_color_matrix[20] = {
629 1, 0, 0, 0, 0, //
630 0, 1, 0, 0, 0, //
631 0, 0, 1, 0, 0, //
632 0, 0, 0, 2, 0, //
633 };
634 const float outer_color_matrix[20] = {
635 1, 0, 0, 0, 0, //
636 0, 1, 0, 0, 0, //
637 0, 0, 1, 0, 0, //
638 0, 0, 0, 0.5, 0, //
639 };
640 auto inner_color_filter =
641 flutter::DlColorFilter::MakeMatrix(inner_color_matrix);
642 auto outer_color_filter =
643 flutter::DlColorFilter::MakeMatrix(outer_color_matrix);
644 auto inner = flutter::DlImageFilter::MakeColorFilter(inner_color_filter);
645 auto outer = flutter::DlImageFilter::MakeColorFilter(outer_color_filter);
646 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
647
648 flutter::DisplayListBuilder builder;
649 flutter::DlPaint paint;
650 paint.setImageFilter(compose.get());
651 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
652 flutter::DlImageSampling::kNearestNeighbor, &paint);
653 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
654 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [393/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 417 of file dl_unittests.cc.

417 {
418 flutter::DisplayListBuilder builder;
419 flutter::DlPaint paint;
420
421 paint.setColor(flutter::DlColor::kRed());
422 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
423 paint.setStrokeWidth(10);
424
425 builder.Translate(300, 300);
426
427 // Move to (50, 50) and draw lines from:
428 // 1. (50, height)
429 // 2. (width, height)
430 // 3. (width, 50)
431 flutter::DlPathBuilder path_builder;
432 path_builder.MoveTo(DlPoint(50, 50));
433 path_builder.LineTo(DlPoint(50, 100));
434 path_builder.LineTo(DlPoint(100, 100));
435 path_builder.LineTo(DlPoint(100, 50));
436 builder.DrawPath(path_builder.TakePath(), paint);
437
438 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
439 }

## ◆ TEST_P() [394/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 155 of file dl_unittests.cc.

155 {
156 auto callback = [&]() {
157 static float start_angle = 45;
158 static float sweep_angle = 270;
159 static float stroke_width = 10;
160 static bool use_center = true;
161
162 static int selected_cap = 0;
163 const char* cap_names[] = {"Butt", "Round", "Square"};
164 flutter::DlStrokeCap cap;
165
166 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
167 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
168 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
169 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
170 ImGui::Combo("Cap", &selected_cap, cap_names,
171 sizeof(cap_names) / sizeof(char*));
172 ImGui::Checkbox("Use center", &use_center);
173 ImGui::End();
174
175 switch (selected_cap) {
176 case 0:
177 cap = flutter::DlStrokeCap::kButt;
178 break;
179 case 1:
180 cap = flutter::DlStrokeCap::kRound;
181 break;
182 case 2:
183 cap = flutter::DlStrokeCap::kSquare;
184 break;
185 default:
186 cap = flutter::DlStrokeCap::kButt;
187 break;
188 }
189
190 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
191 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
192 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
193
194 flutter::DisplayListBuilder builder;
195 flutter::DlPaint paint;
196
197 Vector2 scale = GetContentScale();
198 builder.Scale(scale.x, scale.y);
199 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
200 paint.setStrokeCap(cap);
201 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
202 paint.setStrokeMiter(10);
203 auto rect = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
204 paint.setColor(flutter::DlColor::kGreen());
205 paint.setStrokeWidth(2);
206 builder.DrawRect(rect, paint);
207 paint.setColor(flutter::DlColor::kRed());
208 paint.setStrokeWidth(stroke_width);
209 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
210
211 return builder.Build();
212 };
213 ASSERT_TRUE(OpenPlaygroundHere(callback));
214 }
use_center
bool use_center
Definition: aiks_dl_basic_unittests.cc:925

References impeller::DrawPlaygroundLine(), p1, p2, use_center, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [395/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 656 of file dl_unittests.cc.

656 {
657 auto texture = CreateTextureForFixture("embarcadero.jpg");
658
659 auto callback = [&]() {
660 static float sigma[] = {10, 10};
661 static float ctm_scale = 1;
662 static bool use_bounds = true;
663 static bool draw_circle = true;
664 static bool add_clip = true;
665
666 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
667 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
668 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
669 ImGui::NewLine();
670 ImGui::TextWrapped(
671 "If everything is working correctly, none of the options below should "
672 "impact the filter's appearance.");
673 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
674 ImGui::Checkbox("Draw child element", &draw_circle);
675 ImGui::Checkbox("Add pre-clip", &add_clip);
676 ImGui::End();
677
678 flutter::DisplayListBuilder builder;
679
680 Vector2 scale = ctm_scale * GetContentScale();
681 builder.Scale(scale.x, scale.y);
682
683 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
684 flutter::DlTileMode::kClamp);
685
686 std::optional<DlRect> bounds;
687 if (use_bounds) {
688 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
689 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
690 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
691 bounds = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
692 }
693
694 // Insert a clip to test that the backdrop filter handles stencil depths > 0
695 // correctly.
696 if (add_clip) {
697 builder.ClipRect(DlRect::MakeLTRB(0, 0, 99999, 99999),
698 flutter::DlClipOp::kIntersect, true);
699 }
700
701 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
702 flutter::DlImageSampling::kNearestNeighbor, nullptr);
703 builder.SaveLayer(bounds, nullptr, &filter);
704
705 if (draw_circle) {
706 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
707 auto circle_center = DrawPlaygroundPoint(center_point);
708
709 flutter::DlPaint paint;
710 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
711 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
712 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
713 paint.setStrokeWidth(10);
714 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
715 builder.DrawCircle(DlPoint(circle_center.x, circle_center.y), 100, paint);
716 }
717
718 return builder.Build();
719 };
720
721 ASSERT_TRUE(OpenPlaygroundHere(callback));
722 }

References impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::DlImageImpeller::Make(), p1, p2, impeller::Color::Red(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [396/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBoundedBlur |
| ) |  |

Definition at line 724 of file dl_unittests.cc.

724 {
725 auto texture = CreateTextureForFixture("kalimba.jpg");
726 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
727 const flutter::DlTileMode tile_modes[] = {
728 flutter::DlTileMode::kClamp, flutter::DlTileMode::kRepeat,
729 flutter::DlTileMode::kMirror, flutter::DlTileMode::kDecal};
730
731 auto callback = [&]() {
732 static float sigma = 20;
733 static float bg_scale = 2.1;
734 static float rotate_degree = 0;
735 static float bounds_scale = 1.0;
736 static bool use_bounds = true;
737 static int selected_tile_mode = 0;
738
739 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
740 ImGui::SliderFloat("Background scale", &bg_scale, 0, 10);
741 ImGui::SliderFloat("Sigma", &sigma, 0, 100);
742 ImGui::SliderFloat("Bounds rotate", &rotate_degree, -200, 200);
743 ImGui::SliderFloat("Bounds scale", &bounds_scale, 0.5f, 2.0f);
744 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
745 sizeof(tile_mode_names) / sizeof(char*));
746 ImGui::NewLine();
747 ImGui::Checkbox("Bounded blur", &use_bounds);
748 ImGui::End();
749
750 // Draw from top right to bottom left.
751 static PlaygroundPoint blur_point_a(Point(410, 30), 10, Color::White());
752 static PlaygroundPoint blur_point_b(Point(150, 320), 10, Color::White());
753 auto [p1_raw, p2_raw] = DrawPlaygroundLine(blur_point_a, blur_point_b);
754 Matrix content_scale_transform = Matrix::MakeScale(GetContentScale());
755 Point p1_global = content_scale_transform * p1_raw;
756 Point p2_global = content_scale_transform * p2_raw;
757
758 flutter::DisplayListBuilder builder;
759
760 builder.Save();
761 builder.Scale(bg_scale, bg_scale);
762 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(0, 0),
763 flutter::DlImageSampling::kNearestNeighbor, nullptr);
764 builder.Restore();
765
766 Matrix transform =
767 Matrix::MakeRotationZ(Radians(rotate_degree / 180.0f * kPi));
768 Matrix inverse_transform = transform.Invert();
769
770 builder.Transform(transform);
771
772 Point p1 = inverse_transform * p1_global;
773 Point p2 = inverse_transform * p2_global;
774 DlRect bounds =
775 DlRect::MakeLTRB(p2.x, p1.y, p1.x, p2.y).Scale(bounds_scale);
776
777 builder.ClipRect(bounds);
778 builder.Save();
779
780 flutter::DlPaint save_paint;
781 save_paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
782
783 std::optional<DlRect> blur_bounds;
784 if (use_bounds) {
785 blur_bounds = bounds;
786 }
787 auto filter = flutter::DlBlurImageFilter(
788 sigma, sigma, tile_modes[selected_tile_mode], blur_bounds);
789 builder.SaveLayer(std::nullopt, &save_paint, &filter);
790 builder.Restore();
791 builder.Restore();
792
793 return builder.Build();
794 };
795
796 ASSERT_TRUE(OpenPlaygroundHere(callback));
797 }

References impeller::DrawPlaygroundLine(), impeller::kPi, impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), p1, p2, impeller::Matrix::Scale(), transform, and impeller::Color::White().

## ◆ TEST_P() [397/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 106 of file dl_unittests.cc.

106 {
107 flutter::DisplayListBuilder builder;
108 flutter::DlPaint paint;
109
110 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
111 paint.setStrokeWidth(30);
112 paint.setColor(flutter::DlColor::kRed());
113
114 flutter::DlPathBuilder path_builder;
115 path_builder.MoveTo(DlPoint(-50, 0));
116 path_builder.LineTo(DlPoint(0, -50));
117 path_builder.LineTo(DlPoint(50, 0));
118 flutter::DlPath path = path_builder.TakePath();
119
120 builder.Translate(100, 100);
121 {
122 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
123 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
124 paint.setStrokeMiter(4);
125 builder.DrawPath(path, paint);
126 }
127
128 {
129 builder.Save();
130 builder.Translate(0, 100);
131 // The joint in the path is 45 degrees. A miter length of 1 convert to a
132 // bevel in this case.
133 paint.setStrokeMiter(1);
134 builder.DrawPath(path, paint);
135 builder.Restore();
136 }
137
138 builder.Translate(150, 0);
139 {
140 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
141 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
142 builder.DrawPath(path, paint);
143 }
144
145 builder.Translate(150, 0);
146 {
147 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
148 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
149 builder.DrawPath(path, paint);
150 }
151
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153 }

## ◆ TEST_P() [398/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1322 of file dl_unittests.cc.

1322 {
1323 flutter::DisplayListBuilder builder;
1324 const float green_color_matrix[20] = {
1325 0, 0, 0, 0, 0, //
1326 0, 0, 0, 0, 1, //
1327 0, 0, 0, 0, 0, //
1328 0, 0, 0, 1, 0, //
1329 };
1330 const float blue_color_matrix[20] = {
1331 0, 0, 0, 0, 0, //
1332 0, 0, 0, 0, 0, //
1333 0, 0, 0, 0, 1, //
1334 0, 0, 0, 1, 0, //
1335 };
1336 auto green_color_filter =
1337 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1338 auto blue_color_filter =
1339 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1340 auto blue_image_filter =
1341 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1342
1343 flutter::DlPaint paint;
1344 paint.setColor(flutter::DlColor::kRed());
1345 paint.setColorFilter(green_color_filter);
1346 paint.setImageFilter(blue_image_filter);
1347 builder.DrawRect(DlRect::MakeLTRB(100, 100, 500, 500), paint);
1348 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1349 }

## ◆ TEST_P() [399/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 98 of file dl_unittests.cc.

98 {
99 auto texture = CreateTextureForFixture("embarcadero.jpg");
100 flutter::DisplayListBuilder builder;
101 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
102 flutter::DlImageSampling::kNearestNeighbor, nullptr);
103 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
104 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [400/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 799 of file dl_unittests.cc.

799 {
800 // Image is drawn with corners to scale and center pieces stretched to fit.
801 auto texture = CreateTextureForFixture("embarcadero.jpg");
802 flutter::DisplayListBuilder builder;
803 auto size = texture->GetSize();
804 builder.DrawImageNine(
805 DlImageImpeller::Make(texture),
806 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
807 size.height * 3 / 4),
808 DlRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
809 flutter::DlFilterMode::kNearest, nullptr);
810 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
811 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [401/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 845 of file dl_unittests.cc.

845 {
846 // Edge case, the width and height of the corners does not leave any
847 // room for the center slices. Only the corners are displayed.
848 auto texture = CreateTextureForFixture("embarcadero.jpg");
849 flutter::DisplayListBuilder builder;
850 auto size = texture->GetSize();
851 builder.DrawImageNine(
852 DlImageImpeller::Make(texture),
853 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
854 size.height * 3 / 4),
855 DlRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
856 flutter::DlFilterMode::kNearest, nullptr);
857 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
858 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [402/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 829 of file dl_unittests.cc.

829 {
830 // Edge case, the height of the corners does not leave any room for the
831 // center slice. The center (across the horizontal axis) is folded out of the
832 // resulting image.
833 auto texture = CreateTextureForFixture("embarcadero.jpg");
834 flutter::DisplayListBuilder builder;
835 auto size = texture->GetSize();
836 builder.DrawImageNine(
837 DlImageImpeller::Make(texture),
838 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
839 size.height * 3 / 4),
840 DlRect::MakeLTRB(0, 0, size.width, size.height / 2),
841 flutter::DlFilterMode::kNearest, nullptr);
842 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
843 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [403/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 813 of file dl_unittests.cc.

813 {
814 // Edge case, the width of the corners does not leave any room for the
815 // center slice. The center (across the vertical axis) is folded out of the
816 // resulting image.
817 auto texture = CreateTextureForFixture("embarcadero.jpg");
818 flutter::DisplayListBuilder builder;
819 auto size = texture->GetSize();
820 builder.DrawImageNine(
821 DlImageImpeller::Make(texture),
822 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
823 size.height * 3 / 4),
824 DlRect::MakeLTRB(0, 0, size.width / 2, size.height),
825 flutter::DlFilterMode::kNearest, nullptr);
826 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
827 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [404/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 860 of file dl_unittests.cc.

860 {
861 // Edge case, there is not enough room for the corners to be drawn
862 // without scaling them down.
863 auto texture = CreateTextureForFixture("embarcadero.jpg");
864 flutter::DisplayListBuilder builder;
865 auto size = texture->GetSize();
866 builder.DrawImageNine(
867 DlImageImpeller::Make(texture),
868 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
869 size.height * 3 / 4),
870 DlRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
871 flutter::DlFilterMode::kNearest, nullptr);
872 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
873 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [405/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1219 of file dl_unittests.cc.

1219 {
1220 const flutter::DlColor colors[2] = {
1221 flutter::DlColor(0xFFF44336),
1222 flutter::DlColor(0xFF2196F3),
1223 };
1224 const float stops[2] = {0.0, 1.0};
1225 flutter::DlPaint paint;
1226 flutter::DisplayListBuilder builder;
1227 auto clip_bounds = DlRect::MakeWH(300.0, 300.0);
1228 builder.Save();
1229 builder.Translate(100, 100);
1230 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1231 auto linear =
1232 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1233 stops, flutter::DlTileMode::kRepeat);
1234 paint.setColorSource(linear);
1235 builder.DrawPaint(paint);
1236 builder.Restore();
1237
1238 builder.Save();
1239 builder.Translate(500, 100);
1240 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1241 auto radial = flutter::DlColorSource::MakeRadial(
1242 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1243 paint.setColorSource(radial);
1244 builder.DrawPaint(paint);
1245 builder.Restore();
1246
1247 builder.Save();
1248 builder.Translate(100, 500);
1249 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1250 auto sweep =
1251 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1252 stops, flutter::DlTileMode::kRepeat);
1253 paint.setColorSource(sweep);
1254 builder.DrawPaint(paint);
1255 builder.Restore();
1256
1257 builder.Save();
1258 builder.Translate(500, 500);
1259 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1260 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1261 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1262 flutter::DlTileMode::kRepeat,
1263 flutter::DlTileMode::kRepeat);
1264 paint.setColorSource(image);
1265 builder.DrawPaint(paint);
1266 builder.Restore();
1267
1268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1269 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [406/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 903 of file dl_unittests.cc.

903 {
904 flutter::DisplayListBuilder builder;
905 DlPoint points[7] = {
906 {0, 0}, //
907 {100, 100}, //
908 {100, 0}, //
909 {0, 100}, //
910 {0, 0}, //
911 {48, 48}, //
912 {52, 52}, //
913 };
914 std::vector<flutter::DlStrokeCap> caps = {
915 flutter::DlStrokeCap::kButt,
916 flutter::DlStrokeCap::kRound,
917 flutter::DlStrokeCap::kSquare,
918 };
919 flutter::DlPaint paint =
920 flutter::DlPaint() //
921 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
922 .setStrokeWidth(20);
923 builder.Translate(50, 50);
924 for (auto cap : caps) {
925 paint.setStrokeCap(cap);
926 builder.Save();
927 builder.DrawPoints(flutter::DlPointMode::kPoints, 7, points, paint);
928 builder.Translate(150, 0);
929 builder.DrawPoints(flutter::DlPointMode::kLines, 5, points, paint);
930 builder.Translate(150, 0);
931 builder.DrawPoints(flutter::DlPointMode::kPolygon, 5, points, paint);
932 builder.Restore();
933 builder.Translate(0, 150);
934 }
935 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
936 }

References points.

## ◆ TEST_P() [407/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 47 of file dl_unittests.cc.

47 {
48 flutter::DisplayListBuilder builder;
49 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100),
50 flutter::DlPaint(flutter::DlColor::kBlue()));
51 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
52 }

## ◆ TEST_P() [408/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1205 of file dl_unittests.cc.

1205 {
1206 flutter::DlPaint paint;
1207 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1208 flutter::DisplayListBuilder builder;
1209 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1210 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1211 builder.Translate(0, 200);
1212
1213 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1214 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1215
1216 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1217 }

## ◆ TEST_P() [409/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 961 of file dl_unittests.cc.

961 {
962 flutter::DisplayListBuilder builder;
963 flutter::DlPaint paint;
964
965 auto content_scale = GetContentScale() * 0.8;
966 builder.Scale(content_scale.x, content_scale.y);
967
968 constexpr size_t star_spikes = 5;
969 constexpr DlScalar half_spike_rotation = kPi / star_spikes;
970 constexpr DlScalar radius = 40;
971 constexpr DlScalar spike_size = 10;
972 constexpr DlScalar outer_radius = radius + spike_size;
973 constexpr DlScalar inner_radius = radius - spike_size;
974 std::array<DlPoint, star_spikes * 2> star;
975 for (size_t i = 0; i < star_spikes; i++) {
976 const DlScalar rotation = half_spike_rotation * i * 2;
977 star[i * 2] = DlPoint(50 + std::sin(rotation) * outer_radius,
978 50 - std::cos(rotation) * outer_radius);
979 star[i * 2 + 1] =
980 DlPoint(50 + std::sin(rotation + half_spike_rotation) * inner_radius,
981 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
982 }
983
984 std::array<DlPath, 4> paths = {
985 DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100)),
986 DlPath::MakeRoundRectXY(DlRect::MakeXYWH(20, 0, 200, 100), 30, 30),
987 DlPath::MakeCircle(DlPoint(100, 50), 50),
988 DlPath::MakePoly(star.data(), star.size(), true),
989 };
990 paint.setColor(flutter::DlColor::kWhite());
991 builder.DrawPaint(paint);
992 paint.setColor(flutter::DlColor::kCyan());
993 builder.Translate(100, 50);
994 for (size_t x = 0; x < paths.size(); x++) {
995 builder.Save();
996 for (size_t y = 0; y < 6; y++) {
997 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
998 1);
999 builder.DrawPath(paths[x], paint);
1000 builder.Translate(0, 150);
1001 }
1002 builder.Restore();
1003 builder.Translate(250, 0);
1004 }
1005
1006 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1007 }

References impeller::kPi, and x.

## ◆ TEST_P() [410/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 477 of file dl_unittests.cc.

477 {
478 flutter::DisplayListBuilder builder;
479 flutter::DlPaint paint;
480
481 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
482 paint.setColor(flutter::DlColor::kRed());
483 builder.DrawText(flutter::DlTextSkia::Make(SkTextBlob::MakeFromString(
484 "stoked about stroked text", CreateTestFont())),
485 250, 250, paint);
486
487 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
488 }

## ◆ TEST_P() [411/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 54 of file dl_unittests.cc.

54 {
55 flutter::DisplayListBuilder builder;
56 builder.DrawText(flutter::DlTextSkia::Make(
57 SkTextBlob::MakeFromString("Hello", CreateTestFont())),
58 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
59 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
60 }

## ◆ TEST_P() [412/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 62 of file dl_unittests.cc.

62 {
63 flutter::DisplayListBuilder builder;
64
65 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
66 flutter::DlColor::kRed()};
67 const float stops[2] = {0.0, 1.0};
68
69 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
70 2, colors.data(), stops,
71 flutter::DlTileMode::kClamp);
72 flutter::DlPaint paint;
73 paint.setColorSource(linear);
74
75 builder.DrawText(flutter::DlTextSkia::Make(SkTextBlob::MakeFromString(
76 "Hello World", CreateTestFont())),
77 100, 100, paint);
78 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
79 }

## ◆ TEST_P() [413/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 81 of file dl_unittests.cc.

81 {
82 flutter::DisplayListBuilder builder;
83 builder.DrawText(flutter::DlTextSkia::Make(
84 SkTextBlob::MakeFromString("Hello", CreateTestFont())),
85 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
86
87 flutter::DlPaint save_paint;
88 float alpha = 0.5;
89 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
90 builder.SaveLayer(std::nullopt, &save_paint);
91 builder.DrawText(flutter::DlTextSkia::Make(SkTextBlob::MakeFromString(
92 "Hello with half alpha", CreateTestFontOfSize(100))),
93 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
94 builder.Restore();
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

## ◆ TEST_P() [414/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 530 of file dl_unittests.cc.

530 {
531 auto texture = CreateTextureForFixture("embarcadero.jpg");
532 flutter::DisplayListBuilder builder;
533 flutter::DlPaint paint;
534
535 // Pipeline blended image.
536 {
537 auto filter = flutter::DlColorFilter::MakeBlend(
538 flutter::DlColor::kYellow(), flutter::DlBlendMode::kModulate);
539 paint.setColorFilter(filter);
540 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
541 flutter::DlImageSampling::kNearestNeighbor, &paint);
542 }
543
544 // Advanced blended image.
545 {
546 auto filter = flutter::DlColorFilter::MakeBlend(
547 flutter::DlColor::kRed(), flutter::DlBlendMode::kScreen);
548 paint.setColorFilter(filter);
549 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(250, 250),
550 flutter::DlImageSampling::kNearestNeighbor, &paint);
551 }
552
553 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
554 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [415/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 556 of file dl_unittests.cc.

556 {
557 const float invert_color_matrix[20] = {
558 -1, 0, 0, 0, 1, //
559 0, -1, 0, 0, 1, //
560 0, 0, -1, 0, 1, //
561 0, 0, 0, 1, 0, //
562 };
563 auto texture = CreateTextureForFixture("boston.jpg");
564 flutter::DisplayListBuilder builder;
565 flutter::DlPaint paint;
566
567 auto color_filter = flutter::DlColorFilter::MakeMatrix(invert_color_matrix);
568 auto image_filter = flutter::DlImageFilter::MakeColorFilter(color_filter);
569
570 paint.setImageFilter(image_filter);
571 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
572 flutter::DlImageSampling::kNearestNeighbor, &paint);
573
574 builder.Translate(0, 700);
575 paint.setColorFilter(color_filter);
576 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
577 flutter::DlImageSampling::kNearestNeighbor, &paint);
578 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
579 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [416/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 606 of file dl_unittests.cc.

606 {
607 auto texture = CreateTextureForFixture("boston.jpg");
608 flutter::DisplayListBuilder builder;
609 flutter::DlPaint paint;
610
611 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
612 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
613 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
614 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
615
616 paint.setImageFilter(open.get());
617 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
618 flutter::DlImageSampling::kNearestNeighbor, &paint);
619 builder.Translate(0, 700);
620 paint.setImageFilter(close.get());
621 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
622 flutter::DlImageSampling::kNearestNeighbor, &paint);
623 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
624 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [417/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 581 of file dl_unittests.cc.

581 {
582 auto texture = CreateTextureForFixture("embarcadero.jpg");
583
584 auto callback = [&]() {
585 static float sigma[] = {10, 10};
586
587 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
588 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
589 ImGui::End();
590
591 flutter::DisplayListBuilder builder;
592 flutter::DlPaint paint;
593
594 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
595 flutter::DlTileMode::kClamp);
596 paint.setImageFilter(&filter);
597 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
598 flutter::DlImageSampling::kNearestNeighbor, &paint);
599
600 return builder.Build();
601 };
602
603 ASSERT_TRUE(OpenPlaygroundHere(callback));
604 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [418/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 441 of file dl_unittests.cc.

441 {
442 auto texture = CreateTextureForFixture("embarcadero.jpg");
443 flutter::DisplayListBuilder builder;
444 flutter::DlPaint paint;
445
446 // Mask blurred image.
447 {
448 auto filter =
449 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
450 paint.setMaskFilter(&filter);
451 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
452 flutter::DlImageSampling::kNearestNeighbor, &paint);
453 }
454
455 // Mask blurred filled path.
456 {
457 paint.setColor(flutter::DlColor::kYellow());
458 auto filter =
459 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
460 paint.setMaskFilter(&filter);
461 builder.DrawArc(DlRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
462 }
463
464 // Mask blurred text.
465 {
466 auto filter =
467 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
468 paint.setMaskFilter(&filter);
469 builder.DrawText(flutter::DlTextSkia::Make(SkTextBlob::MakeFromString(
470 "Testing", CreateTestFont())),
471 220, 170, paint);
472 }
473
474 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
475 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [419/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 1043 of file dl_unittests.cc.

1043 {
1044 auto boston = CreateTextureForFixture("boston.jpg");
1045
1046 auto callback = [&]() {
1047 static int selected_matrix_type = 0;
1048 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1049
1050 static float ctm_translation[2] = {200, 200};
1051 static float ctm_scale[2] = {0.65, 0.65};
1052 static float ctm_skew[2] = {0, 0};
1053
1054 static bool enable = true;
1055 static float translation[2] = {100, 100};
1056 static float scale[2] = {0.8, 0.8};
1057 static float skew[2] = {0.2, 0.2};
1058
1059 static bool enable_savelayer = true;
1060
1061 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1062 {
1063 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1064 sizeof(matrix_type_names) / sizeof(char*));
1065
1066 ImGui::TextWrapped("Current Transform");
1067 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1068 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1069 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1070
1071 ImGui::TextWrapped(
1072 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1073 "The only difference is that MatrixFilter doesn't affect the effect "
1074 "transform, whereas LocalMatrixFilter does.");
1075 // Note: See this behavior in:
1076 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1077 ImGui::Checkbox("Enable", &enable);
1078 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1079 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1080 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1081
1082 ImGui::TextWrapped(
1083 "Rendering the filtered image within a layer can expose bounds "
1084 "issues. If the rendered image gets cut off when this setting is "
1085 "enabled, there's a coverage bug in the filter.");
1086 ImGui::Checkbox("Render in layer", &enable_savelayer);
1087 }
1088 ImGui::End();
1089
1090 flutter::DisplayListBuilder builder;
1091 flutter::DlPaint paint;
1092
1093 if (enable_savelayer) {
1094 builder.SaveLayer(std::nullopt, nullptr);
1095 }
1096 {
1097 auto content_scale = GetContentScale();
1098 builder.Scale(content_scale.x, content_scale.y);
1099
1100 // Set the current transform
1101 auto ctm_matrix = Matrix::MakeRow(
1102 ctm_scale[0], ctm_skew[0], 0.0f, ctm_translation[0], //
1103 ctm_skew[1], ctm_scale[1], 0.0f, ctm_translation[1], //
1104 0, 0, 1, 0, //
1105 0, 0, 0, 1);
1106 builder.Transform(ctm_matrix);
1107
1108 // Set the matrix filter
1109 auto filter_matrix =
1110 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1111 skew[1], scale[1], 0.0f, translation[1], //
1112 0.0f, 0.0f, 1.0f, 0.0f, //
1113 0.0f, 0.0f, 0.0f, 1.0f);
1114
1115 if (enable) {
1116 switch (selected_matrix_type) {
1117 case 0: {
1118 auto filter = flutter::DlMatrixImageFilter(
1119 filter_matrix, flutter::DlImageSampling::kLinear);
1120 paint.setImageFilter(&filter);
1121 break;
1122 }
1123 case 1: {
1124 auto internal_filter =
1125 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1126 .shared();
1127 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1128 internal_filter);
1129 paint.setImageFilter(&filter);
1130 break;
1131 }
1132 }
1133 }
1134
1135 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(),
1136 flutter::DlImageSampling::kLinear, &paint);
1137 }
1138 if (enable_savelayer) {
1139 builder.Restore();
1140 }
1141
1142 return builder.Build();
1143 };
1144
1145 ASSERT_TRUE(OpenPlaygroundHere(callback));
1146 }

References impeller::DlImageImpeller::Make(), and impeller::Matrix::MakeRow().

## ◆ TEST_P() [420/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1148 of file dl_unittests.cc.

1148 {
1149 auto callback = [&]() {
1150 static float translation[2] = {0, 0};
1151 static bool enable_save_layer = true;
1152
1153 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1154 ImGui::SliderFloat2("Translation", translation, -130, 130);
1155 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1156 ImGui::End();
1157
1158 flutter::DisplayListBuilder builder;
1159 builder.Save();
1160 builder.Scale(2.0, 2.0);
1161 flutter::DlPaint paint;
1162 paint.setColor(flutter::DlColor::kYellow());
1163 builder.DrawRect(DlRect::MakeWH(300, 300), paint);
1164 paint.setStrokeWidth(1.0);
1165 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1166 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1167 builder.DrawLine(DlPoint(150, 0), DlPoint(150, 300), paint);
1168 builder.DrawLine(DlPoint(0, 150), DlPoint(300, 150), paint);
1169
1170 flutter::DlPaint save_paint;
1171 DlRect bounds = DlRect::MakeXYWH(100, 100, 100, 100);
1172 Matrix translate_matrix =
1173 Matrix::MakeTranslation({translation[0], translation[1]});
1174 if (enable_save_layer) {
1175 auto filter = flutter::DlMatrixImageFilter(
1176 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1177 save_paint.setImageFilter(filter.shared());
1178 builder.SaveLayer(bounds, &save_paint);
1179 } else {
1180 builder.Save();
1181 builder.Transform(translate_matrix);
1182 }
1183
1184 Matrix filter_matrix;
1185 filter_matrix.Translate({150, 150});
1186 filter_matrix.Scale({0.2f, 0.2f});
1187 filter_matrix.Translate({-150, -150});
1188 auto filter = flutter::DlMatrixImageFilter(
1189 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1190
1191 save_paint.setImageFilter(filter.shared());
1192
1193 builder.SaveLayer(bounds, &save_paint);
1194 flutter::DlPaint paint2;
1195 paint2.setColor(flutter::DlColor::kBlue());
1196 builder.DrawRect(bounds, paint2);
1197 builder.Restore();
1198 builder.Restore();
1199 return builder.Build();
1200 };
1201
1202 ASSERT_TRUE(OpenPlaygroundHere(callback));
1203 }

References impeller::Matrix::MakeTranslation(), impeller::Matrix::Scale(), and impeller::Matrix::Translate().

## ◆ TEST_P() [421/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 397 of file dl_unittests.cc.

397 {
398 flutter::DisplayListBuilder builder;
399 flutter::DlPaint paint;
400
401 paint.setColor(flutter::DlColor::kRed());
402 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
403
404 builder.Translate(300, 300);
405 flutter::DlPathBuilder path_builder;
406 path_builder.AddCircle(DlPoint(0, 0), 100);
407 path_builder.AddCircle(DlPoint(0, 0), 50);
408 path_builder.SetFillType(flutter::DlPathFillType::kOdd);
409 builder.DrawPath(path_builder.TakePath(), paint);
410
411 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
412 }

## ◆ TEST_P() [422/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 938 of file dl_unittests.cc.

938 {
939 flutter::DisplayListBuilder builder;
940 std::vector<flutter::DlStrokeCap> caps = {
941 flutter::DlStrokeCap::kButt,
942 flutter::DlStrokeCap::kRound,
943 flutter::DlStrokeCap::kSquare,
944 };
945 flutter::DlPaint paint =
946 flutter::DlPaint() //
947 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
948 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
949 .setStrokeCap(flutter::DlStrokeCap::kButt) //
950 .setStrokeWidth(20);
951 DlPath path = DlPath::MakeLine({150, 50}, {150, 50});
952 for (auto cap : caps) {
953 paint.setStrokeCap(cap);
954 builder.DrawLine(DlPoint(50, 50), DlPoint(50, 50), paint);
955 builder.DrawPath(path, paint);
956 builder.Translate(0, 150);
957 }
958 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
959 }

## ◆ TEST_P() [423/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 1009 of file dl_unittests.cc.

1009 {
1010 flutter::DisplayListBuilder builder;
1011 std::vector<flutter::DlStrokeCap> caps = {
1012 flutter::DlStrokeCap::kButt,
1013 flutter::DlStrokeCap::kRound,
1014 flutter::DlStrokeCap::kSquare,
1015 };
1016 flutter::DlPaint paint = //
1017 flutter::DlPaint() //
1018 .setColor(flutter::DlColor::kWhite()) //
1019 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1020 .setStrokeWidth(0);
1021 flutter::DlPaint outline_paint = //
1022 flutter::DlPaint() //
1023 .setColor(flutter::DlColor::kYellow()) //
1024 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1025 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
1026 .setStrokeWidth(1);
1027 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1028 for (auto cap : caps) {
1029 paint.setStrokeCap(cap);
1030 builder.DrawLine(DlPoint(50, 50), DlPoint(60, 50), paint);
1031 builder.DrawRect(DlRect::MakeLTRB(45, 45, 65, 55), outline_paint);
1032 builder.DrawLine(DlPoint{100, 50}, DlPoint{100, 50}, paint);
1033 if (cap != flutter::DlStrokeCap::kButt) {
1034 builder.DrawRect(DlRect::MakeLTRB(95, 45, 105, 55), outline_paint);
1035 }
1036 builder.DrawPath(path, paint);
1037 builder.DrawRect(path.GetBounds().Expand(5, 5), outline_paint);
1038 builder.Translate(0, 150);
1039 }
1040 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1041 }

## ◆ TEST_P() [424/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1483 of file dl_unittests.cc.

1483 {
1484 flutter::DisplayListBuilder builder;
1485
1486 flutter::DlPaint fill_paint = //
1487 flutter::DlPaint() //
1488 .setColor(flutter::DlColor::kBlue()) //
1489 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1490 .setStrokeWidth(10);
1491 flutter::DlPaint stroke_paint = //
1492 flutter::DlPaint() //
1493 .setColor(flutter::DlColor::kGreen()) //
1494 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1495 .setStrokeWidth(10);
1496
1497 builder.DrawRoundRect(
1498 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1499 fill_paint);
1500 builder.DrawRoundRect(
1501 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1502 stroke_paint);
1503
1504 builder.DrawRoundRect(
1505 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1506 fill_paint);
1507 builder.DrawRoundRect(
1508 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1509 stroke_paint);
1510
1511 flutter::DlPaint reference_paint = //
1512 flutter::DlPaint() //
1513 .setColor(flutter::DlColor::kMidGrey()) //
1514 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1515 .setStrokeWidth(10);
1516
1517 builder.DrawRoundRect(
1518 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1519 reference_paint);
1520 builder.DrawRoundRect(
1521 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1522 reference_paint);
1523
1524 flutter::DlPaint clip_fill_paint = //
1525 flutter::DlPaint() //
1526 .setColor(flutter::DlColor::kCyan()) //
1527 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1528 .setStrokeWidth(10);
1529
1530 builder.Save();
1531 builder.ClipRoundRect(
1532 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1533 builder.DrawPaint(clip_fill_paint);
1534 builder.Restore();
1535
1536 builder.Save();
1537 builder.ClipRoundRect(
1538 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1539 builder.DrawPaint(clip_fill_paint);
1540 builder.Restore();
1541
1542 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1543 }

## ◆ TEST_P() [425/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawCirclesWithTransformations |
| ) |  |

Definition at line 1438 of file dl_unittests.cc.

1438 {
1439 auto callback = [&]() {
1440 static float filled_radius = 100.0;
1441 static float filled_alpha = 255.0;
1442 static float filled_scale[2] = {1.0, 1.0};
1443 static float stroked_radius = 20.0;
1444 static float stroke_width = 10.0;
1445 static float stroked_alpha = 255.0;
1446 static float stroked_scale[2] = {1.0, 1.0};
1447
1448 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1449 {
1450 ImGui::SliderFloat("Filled Radius", &filled_radius, 0, 500);
1451 ImGui::SliderFloat("Filled Alpha", &filled_alpha, 0, 255);
1452 ImGui::SliderFloat2("Filled Scale", filled_scale, 0, 10.0);
1453 ImGui::SliderFloat("Stroked Radius", &stroked_radius, 0, 10.0);
1454 ImGui::SliderFloat("Stroked Width", &stroke_width, 0, 500);
1455 ImGui::SliderFloat("Stroked Alpha", &stroked_alpha, 0, 10.0);
1456 ImGui::SliderFloat2("Stroked Scale", stroked_scale, 0, 10.0);
1457 }
1458 ImGui::End();
1459
1460 flutter::DisplayListBuilder builder;
1461 flutter::DlPaint paint;
1462
1463 paint.setColor(flutter::DlColor::kBlue().withAlpha(filled_alpha));
1464 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1465 builder.Save();
1466 builder.Scale(filled_scale[0], filled_scale[1]);
1467 builder.DrawCircle(DlPoint(500, 750), filled_radius, paint);
1468 builder.Restore();
1469
1470 paint.setColor(flutter::DlColor::kRed().withAlpha(stroked_alpha));
1471 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1472 paint.setStrokeWidth(stroke_width);
1473 builder.Save();
1474 builder.Scale(stroked_scale[0], stroked_scale[1]);
1475 builder.DrawCircle(DlPoint(1250, 750), stroked_radius, paint);
1476 builder.Restore();
1477 return builder.Build();
1478 };
1479
1480 ASSERT_TRUE(OpenPlaygroundHere(callback));
1481 }

## ◆ TEST_P() [426/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1659 of file dl_unittests.cc.

1659 {
1660 flutter::DisplayListBuilder builder;
1661 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1662 Vector2 scale = GetContentScale();
1663 builder.Scale(scale.x, scale.y);
1664
1665 builder.Save();
1666 // We need a small transform op to avoid a deferred save
1667 builder.Translate(1.0f, 1.0f);
1668 auto solid_filter =
1669 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1670 flutter::DlPaint solid_alpha_paint =
1671 flutter::DlPaint() //
1672 .setMaskFilter(solid_filter) //
1673 .setColor(flutter::DlColor::kBlue()) //
1674 .setAlpha(0x7f);
1675 for (int x = 1; x <= 4; x++) {
1676 for (int y = 1; y <= 4; y++) {
1677 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1678 solid_alpha_paint);
1679 }
1680 }
1681 builder.Restore();
1682
1683 builder.Save();
1684 builder.Translate(500.0f, 0.0f);
1685 auto normal_filter =
1686 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1687 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1688 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1689 flutter::DlPaint normal_if_paint =
1690 flutter::DlPaint() //
1691 .setMaskFilter(solid_filter) //
1692 .setImageFilter(rotate_if) //
1693 .setColor(flutter::DlColor::kGreen()) //
1694 .setAlpha(0x7f);
1695 for (int x = 1; x <= 4; x++) {
1696 for (int y = 1; y <= 4; y++) {
1697 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1698 normal_if_paint);
1699 }
1700 }
1701 builder.Restore();
1702
1703 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1704 }

References impeller::Matrix::MakeRotationZ(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [427/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1636 of file dl_unittests.cc.

1636 {
1637 flutter::DisplayListBuilder builder;
1638 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1639
1640 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1641 builder.DrawCircle(DlPoint(300, 300), 200,
1642 flutter::DlPaint().setMaskFilter(&filter));
1643
1644 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1645 flutter::DlColor::kGreen()};
1646 const float stops[2] = {0.0, 1.0};
1647 auto linear = flutter::DlColorSource::MakeLinear(
1648 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1649 flutter::DlTileMode::kRepeat);
1650 flutter::DlPaint blend_paint =
1651 flutter::DlPaint() //
1652 .setColorSource(linear) //
1653 .setBlendMode(flutter::DlBlendMode::kScreen);
1654 builder.DrawPaint(blend_paint);
1655
1656 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1657 }

## ◆ TEST_P() [428/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1399 of file dl_unittests.cc.

1399 {
1400 flutter::DisplayListBuilder builder;
1401 std::vector<flutter::DlStrokeJoin> joins = {
1402 flutter::DlStrokeJoin::kBevel,
1403 flutter::DlStrokeJoin::kRound,
1404 flutter::DlStrokeJoin::kMiter,
1405 };
1406 flutter::DlPaint paint = //
1407 flutter::DlPaint() //
1408 .setColor(flutter::DlColor::kWhite()) //
1409 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1410 .setStrokeWidth(10);
1411 flutter::DlPaint stroke_paint = //
1412 flutter::DlPaint() //
1413 .setColor(flutter::DlColor::kWhite()) //
1414 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1415 .setStrokeWidth(10);
1416 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1417
1418 builder.Translate(300, 50);
1419 builder.Scale(0.8, 0.8);
1420 for (auto join : joins) {
1421 paint.setStrokeJoin(join);
1422 stroke_paint.setStrokeJoin(join);
1423 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1424 builder.DrawRect(DlRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1425 builder.DrawRoundRect(
1426 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 0, 100, 100), 30, 30),
1427 paint);
1428 builder.DrawRoundRect(
1429 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1430 stroke_paint);
1431 builder.DrawCircle(DlPoint(350, 50), 50, paint);
1432 builder.DrawCircle(DlPoint(350, 200), 50, stroke_paint);
1433 builder.Translate(0, 300);
1434 }
1435 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1436 }

## ◆ TEST_P() [429/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1545 of file dl_unittests.cc.

1545 {
1546 std::vector<const char*> blend_mode_names;
1547 std::vector<flutter::DlBlendMode> blend_mode_values;
1548 {
1549 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1550 // Pipeline blends (Porter-Duff alpha compositing)
1551 {"Clear", flutter::DlBlendMode::kClear},
1552 {"Source", flutter::DlBlendMode::kSrc},
1553 {"Destination", flutter::DlBlendMode::kDst},
1554 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1555 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1556 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1557 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1558 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1559 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1560 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1561 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1562 {"Xor", flutter::DlBlendMode::kXor},
1563 {"Plus", flutter::DlBlendMode::kPlus},
1564 {"Modulate", flutter::DlBlendMode::kModulate},
1565 // Advanced blends (color component blends)
1566 {"Screen", flutter::DlBlendMode::kScreen},
1567 {"Overlay", flutter::DlBlendMode::kOverlay},
1568 {"Darken", flutter::DlBlendMode::kDarken},
1569 {"Lighten", flutter::DlBlendMode::kLighten},
1570 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1571 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1572 {"HardLight", flutter::DlBlendMode::kHardLight},
1573 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1574 {"Difference", flutter::DlBlendMode::kDifference},
1575 {"Exclusion", flutter::DlBlendMode::kExclusion},
1576 {"Multiply", flutter::DlBlendMode::kMultiply},
1577 {"Hue", flutter::DlBlendMode::kHue},
1578 {"Saturation", flutter::DlBlendMode::kSaturation},
1579 {"Color", flutter::DlBlendMode::kColor},
1580 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1581 };
1582 assert(blends.size() ==
1583 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1584 for (const auto& [name, mode] : blends) {
1585 blend_mode_names.push_back(name);
1586 blend_mode_values.push_back(mode);
1587 }
1588 }
1589
1590 auto callback = [&]() {
1591 static int current_blend_index = 3;
1592 static float dst_alpha = 1;
1593 static float src_alpha = 1;
1594 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1595 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1596 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1597 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1598
1599 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1600 {
1601 ImGui::ListBox("Blending mode", &current_blend_index,
1602 blend_mode_names.data(), blend_mode_names.size());
1603 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1604 ImGui::ColorEdit4("Color A", color0);
1605 ImGui::ColorEdit4("Color B", color1);
1606 ImGui::ColorEdit4("Color C", color2);
1607 ImGui::ColorEdit4("Source Color", src_color);
1608 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1609 }
1610 ImGui::End();
1611
1612 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1613 DlPoint(200, 100), //
1614 DlPoint(300, 300)};
1615 std::vector<flutter::DlColor> colors = {
1616 toColor(color0).modulateOpacity(dst_alpha),
1617 toColor(color1).modulateOpacity(dst_alpha),
1618 toColor(color2).modulateOpacity(dst_alpha)};
1619
1620 auto vertices = flutter::DlVertices::Make(
1621 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1622 /*texture_coordinates=*/nullptr, colors.data());
1623
1624 flutter::DisplayListBuilder builder;
1625 flutter::DlPaint paint;
1626
1627 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1628 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1629 paint);
1630 return builder.Build();
1631 };
1632
1633 ASSERT_TRUE(OpenPlaygroundHere(callback));
1634 }
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:39

References toColor().

## ◆ TEST_P() [430/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 517 of file dl_unittests.cc.

517 {
518 auto texture = CreateTextureForFixture("embarcadero.jpg");
519 flutter::DisplayListBuilder builder;
520 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
521 flutter::DlPaint paint;
522 paint.setMaskFilter(&filter);
523 builder.SaveLayer(std::nullopt, &paint);
524 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
525 flutter::DlImageSampling::kNearestNeighbor);
526 builder.Restore();
527 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
528 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [431/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1351 of file dl_unittests.cc.

1351 {
1352 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1353 flutter::DlBlurStyle::kNormal, 10);
1354
1355 flutter::DisplayListBuilder builder;
1356
1357 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1358 flutter::DlColor::kGreen()};
1359 std::array<float, 2> stops = {0, 1};
1360 auto texture = CreateTextureForFixture("airplane.jpg");
1361 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1362 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1363 flutter::DlColorSource::MakeImage(
1364 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1365 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1366 &matrix),
1367 flutter::DlColorSource::MakeLinear(
1368 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1369 stops.data(), flutter::DlTileMode::kClamp),
1370 };
1371
1372 builder.Save();
1373 builder.Translate(0, 100);
1374 for (const auto& color_source : color_sources) {
1375 flutter::DlPaint paint;
1376 paint.setColorSource(color_source);
1377 paint.setMaskFilter(blur_filter);
1378
1379 builder.Save();
1380 builder.Translate(100, 0);
1381 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1382 builder.DrawRoundRect(
1383 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1384
1385 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1386 paint.setStrokeWidth(10);
1387 builder.Translate(200, 0);
1388 builder.DrawRoundRect(
1389 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1390
1391 builder.Restore();
1392 builder.Translate(0, 100);
1393 }
1394 builder.Restore();
1395
1396 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1397 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [432/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImageColorFilter |
| ) |  |

Definition at line 887 of file dl_unittests.cc.

887 {
888 auto texture = CreateTextureForFixture("nine_patch2.png");
889
890 auto filter = flutter::DlColorFilter::MakeBlend(flutter::DlColor::kGreen(),
891 flutter::DlBlendMode::kSrcIn);
892 flutter::DlPaint paint;
893 paint.setColorFilter(filter);
894
895 flutter::DisplayListBuilder builder;
896 builder.DrawImageNine(DlImageImpeller::Make(texture),
897 DlIRect::MakeXYWH(10, 10, 1, 1),
898 DlRect::MakeXYWH(0, 0, 200, 100),
899 flutter::DlFilterMode::kNearest, &paint);
900 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
901 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [433/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 875 of file dl_unittests.cc.

875 {
876 // Draw a nine patch image with colored corners and verify that the corner
877 // color does not leak outside the intended region.
878 auto texture = CreateTextureForFixture("nine_patch_corners.png");
879 flutter::DisplayListBuilder builder;
880 builder.DrawImageNine(DlImageImpeller::Make(texture),
881 DlIRect::MakeXYWH(10, 10, 1, 1),
882 DlRect::MakeXYWH(0, 0, 200, 100),
883 flutter::DlFilterMode::kNearest, nullptr);
884 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
885 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [434/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 216 of file dl_unittests.cc.

216 {
217 auto callback = [&]() {
218 flutter::DisplayListBuilder builder;
219 flutter::DlPaint paint;
220
221 paint.setColor(flutter::DlColor::kRed());
222 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
223
224 static float stroke_width = 10.0f;
225 static int selected_stroke_type = 0;
226 static int selected_join_type = 0;
227 const char* stroke_types[] = {"Butte", "Round", "Square"};
228 const char* join_type[] = {"kMiter", "Round", "kBevel"};
229
230 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
231 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
232 sizeof(stroke_types) / sizeof(char*));
233 ImGui::Combo("Join", &selected_join_type, join_type,
234 sizeof(join_type) / sizeof(char*));
235 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
236 ImGui::End();
237
238 flutter::DlStrokeCap cap;
239 flutter::DlStrokeJoin join;
240 switch (selected_stroke_type) {
241 case 0:
242 cap = flutter::DlStrokeCap::kButt;
243 break;
244 case 1:
245 cap = flutter::DlStrokeCap::kRound;
246 break;
247 case 2:
248 cap = flutter::DlStrokeCap::kSquare;
249 break;
250 default:
251 cap = flutter::DlStrokeCap::kButt;
252 break;
253 }
254 switch (selected_join_type) {
255 case 0:
256 join = flutter::DlStrokeJoin::kMiter;
257 break;
258 case 1:
259 join = flutter::DlStrokeJoin::kRound;
260 break;
261 case 2:
262 join = flutter::DlStrokeJoin::kBevel;
263 break;
264 default:
265 join = flutter::DlStrokeJoin::kMiter;
266 break;
267 }
268 paint.setStrokeCap(cap);
269 paint.setStrokeJoin(join);
270 paint.setStrokeWidth(stroke_width);
271
272 // Make rendering better to watch.
273 builder.Scale(1.5f, 1.5f);
274
275 // Rectangle
276 builder.Translate(100, 100);
277 builder.DrawRect(DlRect::MakeWH(100, 100), paint);
278
279 // Rounded rectangle
280 builder.Translate(150, 0);
281 builder.DrawRoundRect(
282 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10), paint);
283
284 // Double rounded rectangle
285 builder.Translate(150, 0);
286 builder.DrawDiffRoundRect(
287 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10),
288 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 10, 80, 30), 10, 10),
289 paint);
290
291 // Contour with duplicate join points
292 {
293 builder.Translate(150, 0);
294 flutter::DlPathBuilder path_builder;
295 path_builder.MoveTo(DlPoint(0, 0));
296 path_builder.LineTo(DlPoint(0, 0));
297 path_builder.LineTo(DlPoint(100, 0));
298 path_builder.LineTo(DlPoint(100, 0));
299 path_builder.LineTo(DlPoint(100, 100));
300 builder.DrawPath(path_builder.TakePath(), paint);
301 }
302
303 // Contour with duplicate start and end points
304
305 // Line.
306 builder.Translate(200, 0);
307 {
308 builder.Save();
309
310 flutter::DlPathBuilder line_path_builder;
311 line_path_builder.MoveTo(DlPoint(0, 0));
312 line_path_builder.MoveTo(DlPoint(0, 0));
313 line_path_builder.LineTo(DlPoint(0, 0));
314 line_path_builder.LineTo(DlPoint(0, 0));
315 line_path_builder.LineTo(DlPoint(50, 50));
316 line_path_builder.LineTo(DlPoint(50, 50));
317 line_path_builder.LineTo(DlPoint(100, 0));
318 line_path_builder.LineTo(DlPoint(100, 0));
319 DlPath line_path = line_path_builder.TakePath();
320 builder.DrawPath(line_path, paint);
321
322 builder.Translate(0, 100);
323 builder.DrawPath(line_path, paint);
324
325 builder.Translate(0, 100);
326 flutter::DlPathBuilder line_path_builder2;
327 line_path_builder2.MoveTo(DlPoint(0, 0));
328 line_path_builder2.LineTo(DlPoint(0, 0));
329 line_path_builder2.LineTo(DlPoint(0, 0));
330 builder.DrawPath(line_path_builder2.TakePath(), paint);
331
332 builder.Restore();
333 }
334
335 // Cubic.
336 builder.Translate(150, 0);
337 {
338 builder.Save();
339
340 flutter::DlPathBuilder cubic_path;
341 cubic_path.MoveTo(DlPoint(0, 0));
342 cubic_path.CubicCurveTo(DlPoint(0, 0), //
343 DlPoint(140.0, 100.0), //
344 DlPoint(140, 20));
345 builder.DrawPath(cubic_path.TakePath(), paint);
346
347 builder.Translate(0, 100);
348 flutter::DlPathBuilder cubic_path2;
349 cubic_path2.MoveTo(DlPoint(0, 0));
350 cubic_path2.CubicCurveTo(DlPoint(0, 0), //
351 DlPoint(0, 0), //
352 DlPoint(150, 150));
353 builder.DrawPath(cubic_path2.TakePath(), paint);
354
355 builder.Translate(0, 100);
356 flutter::DlPathBuilder cubic_path3;
357 cubic_path3.MoveTo(DlPoint(0, 0));
358 cubic_path3.CubicCurveTo(DlPoint(0, 0), //
359 DlPoint(0, 0), //
360 DlPoint(0, 0));
361 builder.DrawPath(cubic_path3.TakePath(), paint);
362
363 builder.Restore();
364 }
365
366 // Quad.
367 builder.Translate(200, 0);
368 {
369 builder.Save();
370
371 flutter::DlPathBuilder quad_path;
372 quad_path.MoveTo(DlPoint(0, 0));
373 quad_path.MoveTo(DlPoint(0, 0));
374 quad_path.QuadraticCurveTo(DlPoint(100, 40), DlPoint(50, 80));
375 builder.DrawPath(quad_path.TakePath(), paint);
376
377 builder.Translate(0, 150);
378 flutter::DlPathBuilder quad_path2;
379 quad_path2.MoveTo(DlPoint(0, 0));
380 quad_path2.MoveTo(DlPoint(0, 0));
381 quad_path2.QuadraticCurveTo(DlPoint(0, 0), DlPoint(100, 100));
382 builder.DrawPath(quad_path2.TakePath(), paint);
383
384 builder.Translate(0, 100);
385 flutter::DlPathBuilder quad_path3;
386 quad_path3.MoveTo(DlPoint(0, 0));
387 quad_path3.QuadraticCurveTo(DlPoint(0, 0), DlPoint(0, 0));
388 builder.DrawPath(quad_path3.TakePath(), paint);
389
390 builder.Restore();
391 }
392 return builder.Build();
393 };
394 ASSERT_TRUE(OpenPlaygroundHere(callback));
395 }

## ◆ TEST_P() [435/603]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 491 of file dl_unittests.cc.

491 {
492 flutter::DisplayListBuilder builder;
493 flutter::DlPaint paint;
494 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
495 auto text = flutter::DlTextSkia::Make(text_blob);
496
497 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
498 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
499
500 // Draw a blue filled rectangle so the text is easier to see.
501 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
502 paint.setColor(mat_blue);
503 builder.DrawRect(DlRect::MakeXYWH(0, 0, 500, 500), paint);
504
505 // Draw stacked text, with stroked text on top.
506 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
507 paint.setColor(flutter::DlColor::kWhite());
508 builder.DrawText(text, 250, 250, paint);
509
510 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
511 paint.setColor(flutter::DlColor::kBlack());
512 builder.DrawText(text, 250, 250, paint);
513
514 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
515 }

## ◆ TEST_P() [436/603]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanDumpToLog |
| ) |  |

Definition at line 30 of file driver_info_vk_unittests.cc.

30 {
31 ASSERT_TRUE(GetContext());
32 const auto& driver_info =
33 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
34 ASSERT_NE(driver_info, nullptr);
35 fml::testing::LogCapture log;
36 driver_info->DumpToLog();
37 EXPECT_TRUE(log.str().find("Driver Information") != std::string::npos);
38 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), and impeller::SurfaceContextVK::GetParent().

## ◆ TEST_P() [437/603]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanQueryDriverInfo |
| ) |  |

Definition at line 17 of file driver_info_vk_unittests.cc.

17 {
18 ASSERT_TRUE(GetContext());
19 const auto& driver_info =
20 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
21 ASSERT_NE(driver_info, nullptr);
22 // 1.1 is the base Impeller version. The driver can't be lower than that.
23 ASSERT_TRUE(driver_info->GetAPIVersion().IsAtLeast(Version{1, 1, 0}));
24 ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
25 ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
26 ASSERT_NE(driver_info->GetDriverName(), "");
27 EXPECT_FALSE(driver_info->IsKnownBadDriver());
28 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::SurfaceContextVK::GetParent(), and impeller::kUnknown.

## ◆ TEST_P() [438/603]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAAImplicitResolve |
| ) |  |

Definition at line 47 of file entity_pass_target_unittests.cc.

47 {
48 auto content_context = GetContentContext();
49 auto buffer = content_context->GetContext()->CreateCommandBuffer();
50 auto context = content_context->GetContext();
51 auto& allocator = *context->GetResourceAllocator();
52
53 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
54 // same.
55 RenderTarget render_target;
56 {
57 PixelFormat pixel_format =
58 context->GetCapabilities()->GetDefaultColorFormat();
59
60 // Create MSAA color texture.
61
62 TextureDescriptor color0_tex_desc;
63 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
64 color0_tex_desc.type = TextureType::kTexture2DMultisample;
65 color0_tex_desc.sample_count = SampleCount::kCount4;
66 color0_tex_desc.format = pixel_format;
67 color0_tex_desc.size = ISize{100, 100};
68 color0_tex_desc.usage = TextureUsage::kRenderTarget;
69
70 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
71
72 // Color attachment.
73
74 ColorAttachment color0;
75 color0.load_action = LoadAction::kDontCare;
76 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
77 color0.texture = color0_msaa_tex;
78 color0.resolve_texture = color0_msaa_tex;
79
80 render_target.SetColorAttachment(color0, 0u);
81 render_target.SetStencilAttachment(std::nullopt);
82 }
83
84 auto entity_pass_target = EntityPassTarget(render_target, false, true);
85
86 auto color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
87 auto msaa_tex = color0.texture;
88 auto resolve_tex = color0.resolve_texture;
89
90 ASSERT_EQ(msaa_tex, resolve_tex);
91
92 FML_DCHECK(content_context);
93 entity_pass_target.Flip(*content_context);
94
95 color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
96
97 ASSERT_NE(msaa_tex, color0.texture);
98 ASSERT_NE(resolve_tex, color0.resolve_texture);
99 ASSERT_EQ(color0.texture, color0.resolve_texture);
100 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kDevicePrivate, impeller::kDontCare, impeller::kRenderTarget, impeller::kStoreAndMultisampleResolve, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::RenderTarget::SetStencilAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, impeller::TextureDescriptor::type, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [439/603]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAATexture |
| ) |  |

Definition at line 19 of file entity_pass_target_unittests.cc.

19 {
20 if (GetContentContext()
21 ->GetDeviceCapabilities()
22 .SupportsImplicitResolvingMSAA()) {
23 GTEST_SKIP() << "Implicit MSAA is used on this device.";
24 }
25 auto content_context = GetContentContext();
26 auto buffer = content_context->GetContext()->CreateCommandBuffer();
27 auto render_target =
28 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
29 *content_context->GetContext(), {100, 100},
30 /*mip_count=*/1);
31
32 auto entity_pass_target = EntityPassTarget(render_target, false, false);
33
34 auto color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
35 auto msaa_tex = color0.texture;
36 auto resolve_tex = color0.resolve_texture;
37
38 FML_DCHECK(content_context);
39 entity_pass_target.Flip(*content_context);
40
41 color0 = entity_pass_target.GetRenderTarget().GetColorAttachment(0);
42
43 ASSERT_EQ(msaa_tex, color0.texture);
44 ASSERT_NE(resolve_tex, color0.resolve_texture);
45 }

## ◆ TEST_P() [440/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 880 of file entity_unittests.cc.

880 {
881 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
882 static float scale = 20;
883
884 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
885 ImGui::SliderFloat("Scale", &scale, 1, 100);
886 ImGui::End();
887
888 Entity entity;
889 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
890 auto path = flutter::DlPathBuilder{}
891 .MoveTo({97.325, 34.818})
892 .CubicCurveTo({98.50862885295136, 34.81812293973836},
893 {99.46822048142015, 33.85863261475589},
894 {99.46822048142015, 32.67499810206613})
895 .CubicCurveTo({99.46822048142015, 31.491363589376355},
896 {98.50862885295136, 30.53187326439389},
897 {97.32499434685802, 30.531998226542708})
898 .CubicCurveTo({96.14153655073771, 30.532123170035373},
899 {95.18222070648729, 31.491540299350355},
900 {95.18222070648729, 32.67499810206613})
901 .CubicCurveTo({95.18222070648729, 33.85845590478189},
902 {96.14153655073771, 34.81787303409686},
903 {97.32499434685802, 34.81799797758954})
904 .Close()
905 .TakePath();
906 entity.SetTransform(
907 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
908
909 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
910
911 auto contents = std::make_shared<SolidColorContents>();
912 contents->SetColor(Color::Red());
913 contents->SetGeometry(geom.get());
914
915 entity.SetContents(contents);
916 return entity.Render(context, pass);
917 };
918 ASSERT_TRUE(OpenPlaygroundHere(callback));
919 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [441/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 748 of file entity_unittests.cc.

748 {
749 std::vector<const char*> blend_mode_names;
750 std::vector<BlendMode> blend_mode_values;
751 {
752 // Force an exhausiveness check with a switch. When adding blend modes,
753 // update this switch with a new name/value to make it selectable in the
754 // test GUI.
755
756 const BlendMode b{};
757 static_assert(b == BlendMode::kClear); // Ensure the first item in
758 // the switch is the first
759 // item in the enum.
760 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
761 switch (b) {
762 case BlendMode::kClear:
763 blend_mode_names.push_back("Clear");
764 blend_mode_values.push_back(BlendMode::kClear);
765 case BlendMode::kSrc:
766 blend_mode_names.push_back("Source");
767 blend_mode_values.push_back(BlendMode::kSrc);
768 case BlendMode::kDst:
769 blend_mode_names.push_back("Destination");
770 blend_mode_values.push_back(BlendMode::kDst);
771 case BlendMode::kSrcOver:
772 blend_mode_names.push_back("SourceOver");
773 blend_mode_values.push_back(BlendMode::kSrcOver);
774 case BlendMode::kDstOver:
775 blend_mode_names.push_back("DestinationOver");
776 blend_mode_values.push_back(BlendMode::kDstOver);
777 case BlendMode::kSrcIn:
778 blend_mode_names.push_back("SourceIn");
779 blend_mode_values.push_back(BlendMode::kSrcIn);
780 case BlendMode::kDstIn:
781 blend_mode_names.push_back("DestinationIn");
782 blend_mode_values.push_back(BlendMode::kDstIn);
783 case BlendMode::kSrcOut:
784 blend_mode_names.push_back("SourceOut");
785 blend_mode_values.push_back(BlendMode::kSrcOut);
786 case BlendMode::kDstOut:
787 blend_mode_names.push_back("DestinationOut");
788 blend_mode_values.push_back(BlendMode::kDstOut);
789 case BlendMode::kSrcATop:
790 blend_mode_names.push_back("SourceATop");
791 blend_mode_values.push_back(BlendMode::kSrcATop);
792 case BlendMode::kDstATop:
793 blend_mode_names.push_back("DestinationATop");
794 blend_mode_values.push_back(BlendMode::kDstATop);
795 case BlendMode::kXor:
796 blend_mode_names.push_back("Xor");
797 blend_mode_values.push_back(BlendMode::kXor);
798 case BlendMode::kPlus:
799 blend_mode_names.push_back("Plus");
800 blend_mode_values.push_back(BlendMode::kPlus);
801 case BlendMode::kModulate:
802 blend_mode_names.push_back("Modulate");
803 blend_mode_values.push_back(BlendMode::kModulate);
804 };
805 }
806
807 auto callback = [&](ContentContext& context, RenderPass& pass) {
808 auto world_matrix = Matrix::MakeScale(GetContentScale());
809 auto draw_rect = [&context, &pass, &world_matrix](
810 Rect rect, Color color, BlendMode blend_mode) -> bool {
811 using VS = SolidFillPipeline::VertexShader;
812 using FS = SolidFillPipeline::FragmentShader;
813
814 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
815 {
816 auto r = rect.GetLTRB();
817 vtx_builder.AddVertices({
818 {Point(r[0], r[1])},
819 {Point(r[2], r[1])},
820 {Point(r[2], r[3])},
821 {Point(r[0], r[1])},
822 {Point(r[2], r[3])},
823 {Point(r[0], r[3])},
824 });
825 }
826
827 pass.SetCommandLabel("Blended Rectangle");
828 auto options = OptionsFromPass(pass);
829 options.blend_mode = blend_mode;
830 options.primitive_type = PrimitiveType::kTriangle;
831 pass.SetPipeline(context.GetSolidFillPipeline(options));
832 pass.SetVertexBuffer(
833 vtx_builder.CreateVertexBuffer(context.GetTransientsDataBuffer(),
834 context.GetTransientsIndexesBuffer()));
835
836 VS::FrameInfo frame_info;
837 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
838 VS::BindFrameInfo(
839 pass, context.GetTransientsDataBuffer().EmplaceUniform(frame_info));
840 FS::FragInfo frag_info;
841 frag_info.color = color.Premultiply();
842 FS::BindFragInfo(
843 pass, context.GetTransientsDataBuffer().EmplaceUniform(frag_info));
844 return pass.Draw().ok();
845 };
846
847 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
848 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
849 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
850 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
851 static int current_blend_index = 3;
852 ImGui::ListBox("Blending mode", &current_blend_index,
853 blend_mode_names.data(), blend_mode_names.size());
854 ImGui::End();
855
856 BlendMode selected_mode = blend_mode_values[current_blend_index];
857
858 Point a, b, c, d;
859 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
860 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
861 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
862 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
863 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
864 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
865
866 bool result = true;
867 result = result &&
868 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
869 pass.GetRenderTargetSize().height),
870 Color(), BlendMode::kClear);
871 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
872 BlendMode::kSrcOver);
873 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
874 selected_mode);
875 return result;
876 };
877 ASSERT_TRUE(OpenPlaygroundHere(callback));
878 }
impeller::FS
LinePipeline::FragmentShader FS
Definition: line_contents.cc:14
impeller::VS
LinePipeline::VertexShader VS
Definition: line_contents.cc:13
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::saturated::b, c, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::DrawPlaygroundLine(), impeller::HostBuffer::EmplaceUniform(), impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContext::GetTransientsDataBuffer(), impeller::ContentContext::GetTransientsIndexesBuffer(), impeller::kClear, impeller::kDst, impeller::kDstATop, impeller::kDstIn, impeller::kDstOut, impeller::kDstOver, impeller::Entity::kLastPipelineBlendMode, impeller::kModulate, impeller::kPlus, impeller::kSrc, impeller::kSrcATop, impeller::kSrcIn, impeller::kSrcOut, impeller::kSrcOver, impeller::kTriangle, impeller::kXor, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::OptionsFromPass(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [442/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1323 of file entity_unittests.cc.

1323 {
1324 auto fill = std::make_shared<SolidColorContents>();
1325 auto geom = Geometry::MakeFillPath(
1326 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1327 fill->SetGeometry(geom.get());
1328 fill->SetColor(Color::CornflowerBlue());
1329 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1330 FilterInput::Make(fill), Radius{3}, Radius{4});
1331
1332 {
1333 Entity e;
1334 e.SetTransform(Matrix());
1335 auto actual = border_mask_blur->GetCoverage(e);
1336 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1337 ASSERT_TRUE(actual.has_value());
1338 ASSERT_RECT_NEAR(actual.value(), expected);
1339 }
1340
1341 {
1342 Entity e;
1343 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1344 auto actual = border_mask_blur->GetCoverage(e);
1345 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1346 ASSERT_TRUE(actual.has_value());
1347 ASSERT_RECT_NEAR(actual.value(), expected);
1348 }
1349 }
ASSERT_RECT_NEAR
#define ASSERT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:191

References ASSERT_RECT_NEAR, impeller::Color::CornflowerBlue(), impeller::kPi, impeller::FilterInput::Make(), impeller::FilterContents::MakeBorderMaskBlur(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeRotationZ(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [443/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2440 of file entity_unittests.cc.

2440 {
2441 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2442
2443 EXPECT_TRUE(path.GetBounds().IsEmpty());
2444
2445 auto geom = Geometry::MakeFillPath(path);
2446
2447 Entity entity;
2448 RenderTarget target =
2449 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2450 *GetContext(), {1, 1}, 1u);
2451 testing::MockRenderPass render_pass(GetContext(), target);
2452 auto position_result =
2453 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2454
2455 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2456
2457 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2458 }

References impeller::GeometryResult::kNormal, impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [444/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 73 of file entity_unittests.cc.

73 {
74 Entity entity;
75 ASSERT_TRUE(entity.GetTransform().IsIdentity());
76 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [445/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 400 of file entity_unittests.cc.

400 {
401 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
402 const char* input_axis[] = {"X", "Y", "Z"};
403 static int rotation_axis_index = 0;
404 static float rotation = 0;
405 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
406 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
407 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
408 sizeof(input_axis) / sizeof(char*));
409 Matrix rotation_matrix;
410 switch (rotation_axis_index) {
411 case 0:
412 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
413 break;
414 case 1:
415 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
416 break;
417 case 2:
418 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
419 break;
420 default:
421 rotation_matrix = Matrix{};
422 break;
423 }
424
425 if (ImGui::Button("Reset")) {
426 rotation = 0;
427 }
428 ImGui::End();
429 Matrix current_transform =
430 Matrix::MakeScale(GetContentScale())
431 .MakeTranslation(
432 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
433 pass.GetRenderTargetSize().height / 2.0)));
434 Matrix result_transform = current_transform * rotation_matrix;
435 flutter::DlPath path =
436 flutter::DlPath::MakeRect(Rect::MakeXYWH(-300, -400, 600, 800));
437
438 Entity entity;
439 entity.SetTransform(result_transform);
440
441 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
442
443 auto contents = std::make_shared<SolidColorContents>();
444 contents->SetColor(Color::Red());
445 contents->SetGeometry(geom.get());
446
447 entity.SetContents(contents);
448 return entity.Render(context, pass);
449 };
450 ASSERT_TRUE(OpenPlaygroundHere(callback));
451 }

References impeller::kPi, impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [446/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRoundSuperEllipseWithJustEnoughRadius |
| ) |  |

Definition at line 2758 of file entity_unittests.cc.

2758 {
2759 // Regression test for https://github.com/flutter/flutter/issues/176894
2760 // Verify that a radius marginally above the minimum threshold can be
2761 // processed safely. The expectation is that the rounded corners are
2762 // drawn as rounded and that no NaNs or crashes occur.
2763 auto geom = Geometry::MakeRoundSuperellipse(
2764 Rect::MakeLTRB(200, 200, 300, 300), 1.1 * kEhCloseEnough);
2765
2766 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2767 Entity entity;
2768
2769 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2770
2771 RenderTargetAllocator allocator(
2772 content_context.GetContext()->GetResourceAllocator());
2773
2774 auto render_target = allocator.CreateOffscreen(
2775 *content_context.GetContext(), /*size=*/{500, 500}, /*mip_count=*/1);
2776 auto pass = cmd_buffer->CreateRenderPass(render_target);
2777
2778 GeometryResult result =
2779 geom->GetPositionBuffer(content_context, entity, *pass);
2780
2781 EXPECT_EQ(result.vertex_buffer.vertex_count, 200u);
2782 Point* written_data = reinterpret_cast<Point*>(
2783 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2784 result.vertex_buffer.vertex_buffer.GetRange().offset));
2785
2786 std::vector<Point> expected_head = {Point(250.0, 200.0), Point(299.9, 200.0),
2787 Point(200.1, 200.0), Point(299.9, 200.0)};
2788
2789 for (size_t i = 0; i < expected_head.size(); i++) {
2790 const Point& point = written_data[i];
2791 EXPECT_NEAR(point.x, expected_head[i].x, 0.1);
2792 EXPECT_NEAR(point.y, expected_head[i].y, 0.1);
2793 }
2794 }

References impeller::RenderTargetAllocator::CreateOffscreen(), impeller::BufferView::GetBuffer(), impeller::ContentContext::GetContext(), impeller::BufferView::GetRange(), impeller::kEhCloseEnough, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRoundSuperellipse(), impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), impeller::VertexBuffer::vertex_buffer, impeller::GeometryResult::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [447/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRoundSuperEllipseWithTinyRadius |
| ) |  |

Definition at line 2720 of file entity_unittests.cc.

2720 {
2721 // Regression test for https://github.com/flutter/flutter/issues/176894
2722 // Verify that a radius marginally below the minimum threshold can be
2723 // processed safely. The expectation is that the rounded corners degenerate
2724 // into sharp corners (four corner points) and that no NaNs or crashes occur.
2725 auto geom = Geometry::MakeRoundSuperellipse(
2726 Rect::MakeLTRB(200, 200, 300, 300), 0.5 * kEhCloseEnough);
2727
2728 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2729 Entity entity;
2730
2731 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2732
2733 RenderTargetAllocator allocator(
2734 content_context.GetContext()->GetResourceAllocator());
2735
2736 auto render_target = allocator.CreateOffscreen(
2737 *content_context.GetContext(), /*size=*/{500, 500}, /*mip_count=*/1);
2738 auto pass = cmd_buffer->CreateRenderPass(render_target);
2739
2740 GeometryResult result =
2741 geom->GetPositionBuffer(content_context, entity, *pass);
2742
2743 EXPECT_EQ(result.vertex_buffer.vertex_count, 4u);
2744 Point* written_data = reinterpret_cast<Point*>(
2745 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2746 result.vertex_buffer.vertex_buffer.GetRange().offset));
2747
2748 std::vector<Point> expected = {Point(300.0, 200.0), Point(300.0, 300.0),
2749 Point(200.0, 200.0), Point(200.0, 300.0)};
2750
2751 for (size_t i = 0; i < expected.size(); i++) {
2752 const Point& point = written_data[i];
2753 EXPECT_NEAR(point.x, expected[i].x, 0.1);
2754 EXPECT_NEAR(point.y, expected[i].y, 0.1);
2755 }
2756 }

References impeller::RenderTargetAllocator::CreateOffscreen(), impeller::BufferView::GetBuffer(), impeller::ContentContext::GetContext(), impeller::BufferView::GetRange(), impeller::kEhCloseEnough, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRoundSuperellipse(), impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), impeller::VertexBuffer::vertex_buffer, impeller::GeometryResult::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [448/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2460 of file entity_unittests.cc.

2460 {
2461 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2462
2463 EXPECT_TRUE(path.GetBounds().IsEmpty());
2464
2465 auto contents = std::make_shared<SolidColorContents>();
2466 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2467 contents->SetGeometry(geom.get());
2468 contents->SetColor(Color::Red());
2469
2470 Entity entity;
2471 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2472 entity.SetContents(contents);
2473
2474 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2475 }

References impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [449/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2173 of file entity_unittests.cc.

2173 {
2174 Entity entity;
2175 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2176 auto src_contents = std::make_shared<SolidColorContents>();
2177 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2178 src_contents->SetGeometry(src_geom.get());
2179 src_contents->SetColor(Color::Red());
2180
2181 auto dst_contents = std::make_shared<SolidColorContents>();
2182 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2183 dst_contents->SetGeometry(dst_geom.get());
2184 dst_contents->SetColor(Color::Blue());
2185
2186 auto contents = ColorFilterContents::MakeBlend(
2187 BlendMode::kSrcOver, {FilterInput::Make(dst_contents, false),
2188 FilterInput::Make(src_contents, false)});
2189 entity.SetContents(std::move(contents));
2190 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2191 }

References impeller::Color::Blue(), impeller::kSrcOver, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [450/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1936 of file entity_unittests.cc.

1936 {
1937 auto image = CreateTextureForFixture("boston.jpg");
1938 auto filter = ColorFilterContents::MakeBlend(
1939 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1940
1941 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1942 Entity entity;
1943 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1944 Matrix::MakeTranslation({500, 300}) *
1945 Matrix::MakeScale(Vector2{0.5, 0.5}));
1946 entity.SetContents(filter);
1947 return entity.Render(context, pass);
1948 };
1949 ASSERT_TRUE(OpenPlaygroundHere(callback));
1950 }

References impeller::kColorBurn, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [451/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1952 of file entity_unittests.cc.

1952 {
1953 auto image = CreateTextureForFixture("boston.jpg");
1954 auto filter = ColorFilterContents::MakeBlend(
1955 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1956
1957 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1958 Entity entity;
1959 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1960 Matrix::MakeTranslation({500, 300}) *
1961 Matrix::MakeScale(Vector2{0.5, 0.5}));
1962 entity.SetContents(filter);
1963 return entity.Render(context, pass);
1964 };
1965 ASSERT_TRUE(OpenPlaygroundHere(callback));
1966 }

References impeller::kClear, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [452/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1984 of file entity_unittests.cc.

1984 {
1985 auto image = CreateTextureForFixture("boston.jpg");
1986 auto filter = ColorFilterContents::MakeBlend(
1987 BlendMode::kDst, FilterInput::Make({image}), Color::Red());
1988
1989 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1990 Entity entity;
1991 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1992 Matrix::MakeTranslation({500, 300}) *
1993 Matrix::MakeScale(Vector2{0.5, 0.5}));
1994 entity.SetContents(filter);
1995 return entity.Render(context, pass);
1996 };
1997 ASSERT_TRUE(OpenPlaygroundHere(callback));
1998 }

References impeller::kDst, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [453/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1968 of file entity_unittests.cc.

1968 {
1969 auto image = CreateTextureForFixture("boston.jpg");
1970 auto filter = ColorFilterContents::MakeBlend(
1971 BlendMode::kSrc, FilterInput::Make({image}), Color::Red());
1972
1973 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1974 Entity entity;
1975 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1976 Matrix::MakeTranslation({500, 300}) *
1977 Matrix::MakeScale(Vector2{0.5, 0.5}));
1978 entity.SetContents(filter);
1979 return entity.Render(context, pass);
1980 };
1981 ASSERT_TRUE(OpenPlaygroundHere(callback));
1982 }

References impeller::kSrc, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [454/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 2000 of file entity_unittests.cc.

2000 {
2001 auto image = CreateTextureForFixture("boston.jpg");
2002 auto filter = ColorFilterContents::MakeBlend(
2003 BlendMode::kSrcIn, FilterInput::Make({image}), Color::Red());
2004
2005 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2006 Entity entity;
2007 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2008 Matrix::MakeTranslation({500, 300}) *
2009 Matrix::MakeScale(Vector2{0.5, 0.5}));
2010 entity.SetContents(filter);
2011 return entity.Render(context, pass);
2012 };
2013 ASSERT_TRUE(OpenPlaygroundHere(callback));
2014 }

References impeller::kSrcIn, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [455/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1450 of file entity_unittests.cc.

1450 {
1451 // Set up a simple color background.
1452 auto fill = std::make_shared<SolidColorContents>();
1453 auto geom = Geometry::MakeFillPath(
1454 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1455 fill->SetGeometry(geom.get());
1456 fill->SetColor(Color::Coral());
1457
1458 // Set the color matrix filter.
1459 ColorMatrix matrix = {
1460 1, 1, 1, 1, 1, //
1461 1, 1, 1, 1, 1, //
1462 1, 1, 1, 1, 1, //
1463 1, 1, 1, 1, 1, //
1464 };
1465
1466 auto filter =
1467 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1468
1469 Entity e;
1470 e.SetTransform(Matrix());
1471
1472 // Confirm that the actual filter coverage matches the expected coverage.
1473 auto actual = filter->GetCoverage(e);
1474 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1475
1476 ASSERT_TRUE(actual.has_value());
1477 ASSERT_RECT_NEAR(actual.value(), expected);
1478 }

References ASSERT_RECT_NEAR, impeller::Color::Coral(), impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [456/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1480 of file entity_unittests.cc.

1480 {
1481 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1482 ASSERT_TRUE(bay_bridge);
1483
1484 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1485 // UI state.
1486 static ColorMatrix color_matrix = {
1487 1, 0, 0, 0, 0, //
1488 0, 3, 0, 0, 0, //
1489 0, 0, 1, 0, 0, //
1490 0, 0, 0, 1, 0, //
1491 };
1492 static float offset[2] = {500, 400};
1493 static float rotation = 0;
1494 static float scale[2] = {0.65, 0.65};
1495 static float skew[2] = {0, 0};
1496
1497 // Define the ImGui
1498 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1499 {
1500 std::string label = "##1";
1501 for (int i = 0; i < 20; i += 5) {
1502 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1503 &(color_matrix.array[i]), 5, nullptr, nullptr,
1504 "%.2f", 0);
1505 label[2]++;
1506 }
1507
1508 ImGui::SliderFloat2("Translation", &offset[0], 0,
1509 pass.GetRenderTargetSize().width);
1510 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1511 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1512 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1513 }
1514 ImGui::End();
1515
1516 // Set the color matrix filter.
1517 auto filter = ColorFilterContents::MakeColorMatrix(
1518 FilterInput::Make(bay_bridge), color_matrix);
1519
1520 // Define the entity with the color matrix filter.
1521 Entity entity;
1522 entity.SetTransform(
1523 Matrix::MakeScale(GetContentScale()) *
1524 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1525 Matrix::MakeRotationZ(Radians(rotation)) *
1526 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1527 Matrix::MakeSkew(skew[0], skew[1]) *
1528 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1529 entity.SetContents(filter);
1530 entity.Render(context, pass);
1531
1532 return true;
1533 };
1534
1535 ASSERT_TRUE(OpenPlaygroundHere(callback));
1536 }

References impeller::ColorMatrix::array, impeller::kPi, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [457/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2061 of file entity_unittests.cc.

2061 {
2062 Matrix matrix;
2063 ConicalGradientContents contents;
2064 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2065 contents.SetGeometry(geom.get());
2066
2067 contents.SetColors({Color::CornflowerBlue()});
2068 EXPECT_FALSE(contents.IsOpaque(matrix));
2069 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2070 EXPECT_FALSE(contents.IsOpaque(matrix));
2071
2072 // Create stroked path that required alpha coverage.
2073 geom = Geometry::MakeStrokePath(
2074 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2075 {.width = 0.05f});
2076 contents.SetGeometry(geom.get());
2077 contents.SetColors({Color::CornflowerBlue()});
2078
2079 EXPECT_FALSE(contents.IsOpaque(matrix));
2080 }

References impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::ConicalGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [458/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2240 of file entity_unittests.cc.

2240 {
2241 ContentContextOptions opts;
2242 auto hash_a = opts.ToKey();
2243
2244 opts.blend_mode = BlendMode::kColorBurn;
2245 auto hash_b = opts.ToKey();
2246
2247 opts.has_depth_stencil_attachments = false;
2248 auto hash_c = opts.ToKey();
2249
2250 opts.primitive_type = PrimitiveType::kPoint;
2251 auto hash_d = opts.ToKey();
2252
2253 EXPECT_NE(hash_a, hash_b);
2254 EXPECT_NE(hash_b, hash_c);
2255 EXPECT_NE(hash_c, hash_d);
2256 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::kColorBurn, impeller::kPoint, impeller::ContentContextOptions::primitive_type, and impeller::ContentContextOptions::ToKey().

## ◆ TEST_P() [459/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1246 of file entity_unittests.cc.

1246 {
1247 Entity entity;
1248 entity.SetContents(std::make_shared<SolidColorContents>());
1249 ASSERT_FALSE(entity.GetCoverage().has_value());
1250 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [460/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2016 of file entity_unittests.cc.

2016 {
2017 auto arrow_head = flutter::DlPathBuilder{}
2018 .MoveTo({50, 120})
2019 .LineTo({120, 190})
2020 .LineTo({190, 120})
2021 .TakePath();
2022 auto geometry = Geometry::MakeStrokePath(arrow_head, //
2023 {
2024 .width = 15.0f,
2025 .cap = Cap::kRound,
2026 .join = Join::kRound,
2027 .miter_limit = 4.0f,
2028 });
2029
2030 auto transform = Matrix::MakeTranslation({300, 300}) *
2031 Matrix::MakeRotationZ(Radians(kPiOver2));
2032 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2033 // due to floating point inaccuracy in the transcendental trig functions.
2034 // e[1][0] is the intended negative value that we care about (-1.0) as it
2035 // comes from the rotation of pi/2.
2036 EXPECT_LT(transform.e[1][0], 0.0f);
2037 auto coverage = geometry->GetCoverage(transform);
2038 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2039 }

References ASSERT_RECT_NEAR, impeller::kPiOver2, impeller::kRound, impeller::LineTo(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [461/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 453 of file entity_unittests.cc.

453 {
454 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
455 flutter::DlPath path =
456 flutter::DlPathBuilder{}
457 .MoveTo({359.934, 96.6335})
458 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
459 {354.673, 96.8895})
460 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
461 {354.367, 96.9075})
462 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
463 {349.259, 97.2355})
464 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
465 {348.625, 97.2834})
466 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
467 {343.789, 97.6722})
468 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
469 {342.703, 97.7734})
470 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
471 {338.246, 98.207})
472 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
473 {336.612, 98.3894})
474 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
475 {332.623, 98.8476})
476 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
477 {332.237, 98.8982})
478 .LineTo({332.237, 102.601})
479 .LineTo({321.778, 102.601})
480 .LineTo({321.778, 100.382})
481 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
482 {321.161, 100.476})
483 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
484 {315.332, 101.479})
485 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
486 {315.301, 101.484})
487 .LineTo({310.017, 105.94})
488 .LineTo({309.779, 105.427})
489 .LineTo({314.403, 101.651})
490 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
491 {314.368, 101.658})
492 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
493 {308.846, 102.748})
494 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
495 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
496 {303.425, 103.936})
497 .LineTo({299.105, 107.578})
498 .LineTo({298.867, 107.065})
499 .LineTo({302.394, 104.185})
500 .LineTo({302.412, 104.171})
501 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
502 {299.344, 104.921})
503 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
504 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
505 {291.462, 106.979})
506 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
507 {290.471, 107.257})
508 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
509 {287.449, 108.139})
510 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
511 {284.536, 109.035})
512 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
513 {281.952, 109.859})
514 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
515 {279.633, 110.638})
516 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
517 {276.803, 111.607})
518 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
519 {276.672, 111.653})
520 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
521 {271.721, 113.463})
522 .LineTo({271.717, 113.449})
523 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
524 {270.963, 113.628})
525 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
526 {270.748, 113.682})
527 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
528 {269.839, 113.926})
529 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
530 {269.681, 113.972})
531 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
532 {268.756, 114.239})
533 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
534 {268.367, 114.354})
535 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
536 {267.752, 114.54})
537 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
538 {253.564, 119.252})
539 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
540 {253.538, 119.261})
541 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
542 {248.189, 121.131})
543 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
544 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
545 {245.975, 121.912})
546 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
547 {244.698, 122.364})
548 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
549 {242.794, 123.04})
550 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
551 {240.961, 123.693})
552 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
553 {240.052, 124.018})
554 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
555 .LineTo({237.164, 125.003})
556 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
557 {235.81, 125.538})
558 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
559 {234.592, 125.977})
560 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
561 {234.59, 125.977})
562 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
563 {192.381, 141.429})
564 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
565 .LineTo({360, 160})
566 .LineTo({360, 119.256})
567 .LineTo({360, 106.332})
568 .LineTo({360, 96.6307})
569 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
570 {359.934, 96.6335})
571 .Close()
572 .MoveTo({337.336, 124.143})
573 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
574 {338.903, 121.511})
575 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
576 {337.336, 124.143})
577 .Close()
578 .MoveTo({340.082, 121.849})
579 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
580 {340.046, 122.075})
581 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
582 {340.023, 122.177})
583 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
584 {339.952, 122.437})
585 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
586 {339.918, 122.544})
587 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
588 {339.75, 122.938})
589 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
590 {339.74, 122.955})
591 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
592 {339.501, 123.328})
593 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
594 {339.41, 123.438})
595 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
596 {339.145, 123.714})
597 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
598 {339.025, 123.821})
599 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
600 {338.539, 124.143})
601 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
602 {338.58, 123.626})
603 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
604 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
605 {338.704, 123.151})
606 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
607 {338.714, 123.117})
608 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
609 {338.905, 122.712})
610 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
611 {338.922, 122.682})
612 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
613 {339.155, 122.34})
614 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
615 {339.172, 122.319})
616 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
617 {339.425, 122.037})
618 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
619 {339.435, 122.027})
620 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
621 {340.106, 121.511})
622 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
623 {340.082, 121.849})
624 .Close()
625 .MoveTo({340.678, 113.245})
626 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
627 {340.135, 113.775})
628 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
629 {339.115, 114.151})
630 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
631 {336.448, 114.516})
632 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
633 {334.384, 114.513})
634 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
635 {333.605, 114.424})
636 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
637 {331.41, 113.883})
638 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
639 {330.672, 112.813})
640 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
641 {334.526, 113.833})
642 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
643 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
644 {332.76, 110.402})
645 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
646 {335.228, 113.395})
647 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
648 {335.661, 109.592})
649 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
650 {336.07, 113.389})
651 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
652 {338.563, 110.402})
653 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
654 {336.753, 113.784})
655 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
656 {336.796, 113.833})
657 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
658 {340.65, 112.813})
659 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
660 {340.678, 113.245})
661 .Close()
662 .MoveTo({346.357, 106.771})
663 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
664 {347.924, 104.139})
665 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
666 {346.357, 106.771})
667 .Close()
668 .MoveTo({347.56, 106.771})
669 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
670 {349.127, 104.139})
671 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
672 {347.56, 106.771})
673 .Close()
674 .TakePath();
675 Entity entity;
676 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
677
678 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
679
680 auto contents = std::make_shared<SolidColorContents>();
681 contents->SetColor(Color::Red());
682 contents->SetGeometry(geom.get());
683
684 entity.SetContents(contents);
685 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
686 }

References impeller::Close(), impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [462/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 371 of file entity_unittests.cc.

371 {
372 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
373 flutter::DlPath path =
374 flutter::DlPathBuilder{}
375 .MoveTo({237.164, 125.003})
376 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
377 {235.81, 125.538})
378 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
379 {234.592, 125.977})
380 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
381 {234.59, 125.977})
382 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
383 {192.381, 141.429})
384 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
385 .Close()
386 .TakePath();
387 Entity entity;
388 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
389
390 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
391
392 auto contents = std::make_shared<SolidColorContents>();
393 contents->SetColor(Color::Red());
394 contents->SetGeometry(geom.get());
395
396 entity.SetContents(contents);
397 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
398 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [463/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2224 of file entity_unittests.cc.

2224 {
2225 auto content_context = GetContentContext();
2226 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2227 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2228 });
2229
2230 auto decal_supported = static_cast<Scalar>(
2231 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2232 std::vector<Scalar> expected_constants = {decal_supported};
2233 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2234 expected_constants);
2235 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [464/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipse |
| ) |  |

Definition at line 2510 of file entity_unittests.cc.

2510 {
2511 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2512 // UI state.
2513 static int style_index = 0;
2514 static float center[2] = {830, 830};
2515 static float size[2] = {600, 600};
2516 static bool horizontal_symmetry = true;
2517 static bool vertical_symmetry = true;
2518 static bool corner_symmetry = true;
2519
2520 const char* style_options[] = {"Fill", "Stroke"};
2521
2522 // Initially radius_tl[0] will be mirrored to all 8 values since all 3
2523 // symmetries are enabled.
2524 static std::array<float, 2> radius_tl = {200};
2525 static std::array<float, 2> radius_tr;
2526 static std::array<float, 2> radius_bl;
2527 static std::array<float, 2> radius_br;
2528
2529 auto AddRadiusControl = [](std::array<float, 2>& radii, const char* tb_name,
2530 const char* lr_name) {
2531 std::string name = "Radius";
2532 if (!horizontal_symmetry || !vertical_symmetry) {
2533 name += ":";
2534 }
2535 if (!vertical_symmetry) {
2536 name = name + " " + tb_name;
2537 }
2538 if (!horizontal_symmetry) {
2539 name = name + " " + lr_name;
2540 }
2541 if (corner_symmetry) {
2542 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2543 } else {
2544 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2545 }
2546 };
2547
2548 if (corner_symmetry) {
2549 radius_tl[1] = radius_tl[0];
2550 radius_tr[1] = radius_tr[0];
2551 radius_bl[1] = radius_bl[0];
2552 radius_br[1] = radius_br[0];
2553 }
2554
2555 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2556 {
2557 ImGui::Combo("Style", &style_index, style_options,
2558 sizeof(style_options) / sizeof(char*));
2559 ImGui::SliderFloat2("Center", center, 0, 1000);
2560 ImGui::SliderFloat2("Size", size, 0, 1000);
2561 ImGui::Checkbox("Symmetry: Horizontal", &horizontal_symmetry);
2562 ImGui::Checkbox("Symmetry: Vertical", &vertical_symmetry);
2563 ImGui::Checkbox("Symmetry: Corners", &corner_symmetry);
2564 AddRadiusControl(radius_tl, "Top", "Left");
2565 if (!horizontal_symmetry) {
2566 AddRadiusControl(radius_tr, "Top", "Right");
2567 } else {
2568 radius_tr = radius_tl;
2569 }
2570 if (!vertical_symmetry) {
2571 AddRadiusControl(radius_bl, "Bottom", "Left");
2572 } else {
2573 radius_bl = radius_tl;
2574 }
2575 if (!horizontal_symmetry && !vertical_symmetry) {
2576 AddRadiusControl(radius_br, "Bottom", "Right");
2577 } else {
2578 if (horizontal_symmetry) {
2579 radius_br = radius_bl;
2580 } else {
2581 radius_br = radius_tr;
2582 }
2583 }
2584 }
2585
2586 ImGui::End();
2587
2588 RoundingRadii radii{
2589 .top_left = {radius_tl[0], radius_tl[1]},
2590 .top_right = {radius_tr[0], radius_tr[1]},
2591 .bottom_left = {radius_bl[0], radius_bl[1]},
2592 .bottom_right = {radius_br[0], radius_br[1]},
2593 };
2594
2595 auto rse = RoundSuperellipse::MakeRectRadii(
2596 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}), radii);
2597
2598 flutter::DlPath path;
2599 std::unique_ptr<Geometry> geom;
2600 if (style_index == 0) {
2601 geom = std::make_unique<RoundSuperellipseGeometry>(
2602 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}),
2603 radii);
2604 } else {
2605 path = flutter::DlPath::MakeRoundSuperellipse(rse);
2606 geom = Geometry::MakeStrokePath(path, {.width = 2.0f});
2607 }
2608
2609 auto contents = std::make_shared<SolidColorContents>();
2610 contents->SetColor(Color::Red());
2611 contents->SetGeometry(geom.get());
2612
2613 Entity entity;
2614 entity.SetContents(contents);
2615
2616 return entity.Render(context, pass);
2617 };
2618
2619 ASSERT_TRUE(OpenPlaygroundHere(callback));
2620 }
impeller::testing::RectMakeCenterSize
Rect RectMakeCenterSize(Point center, Size size)
Definition: entity_unittests.cc:69

References impeller::RoundSuperellipse::MakeRectRadii(), impeller::Geometry::MakeStrokePath(), RectMakeCenterSize(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [465/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipseWithLargeN |
| ) |  |

Definition at line 2622 of file entity_unittests.cc.

2622 {
2623 // This playground shows the enlarged corner of a rounded superellipse to
2624 // compare pathing algorithm against the filling algorithm (benchmark) at very
2625 // large ratio.
2626 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2627 constexpr float corner_radius = 100.0;
2628
2629 // UI state.
2630 static float logarithm_of_ratio = 1.5; // ratio = size / corner_radius
2631
2632 float ratio = std::exp(logarithm_of_ratio);
2633
2634 float rect_size = corner_radius * ratio;
2635 Rect rect = Rect::MakeLTRB(0, 0, rect_size, rect_size);
2636 constexpr float screen_canvas_padding = 200.0f;
2637 constexpr float screen_canvas_size = 1000.0f;
2638
2639 // Scale so that "corner radius" is as long as half the canvas.
2640 float scale = screen_canvas_size / 2 / corner_radius;
2641
2642 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2643 {
2644 ImGui::SliderFloat("log(Ratio)", &logarithm_of_ratio, 1.0, 8.0);
2645 ImGui::LabelText("Ratio", "%.2g", static_cast<double>(ratio));
2646 ImGui::Text(" where Ratio = RectSize / CornerRadius");
2647 }
2648 ImGui::End();
2649
2650 auto top_right = Vector2(screen_canvas_size * 1.3f, screen_canvas_padding);
2651 auto transform = Matrix::MakeTranslation(top_right) *
2652 Matrix::MakeScale(Vector2(scale, scale)) *
2653 Matrix::MakeTranslation(Vector2(-rect_size, 0));
2654 bool success = true;
2655
2656 auto fill_geom =
2657 std::make_unique<RoundSuperellipseGeometry>(rect, corner_radius);
2658 // Fill
2659 {
2660 auto contents = std::make_shared<SolidColorContents>();
2661 contents->SetColor(Color::Red());
2662 contents->SetGeometry(fill_geom.get());
2663
2664 Entity entity;
2665 entity.SetContents(contents);
2666 entity.SetTransform(transform);
2667
2668 success = success && entity.Render(context, pass);
2669 }
2670
2671 // Stroke
2672 auto path = flutter::DlPath::MakeRoundSuperellipse(
2673 RoundSuperellipse::MakeRectRadius(rect, corner_radius));
2674 auto stroke_geom = Geometry::MakeStrokePath(path, {.width = 2 / scale});
2675 {
2676 auto contents = std::make_shared<SolidColorContents>();
2677 contents->SetColor(Color::Blue());
2678 contents->SetGeometry(stroke_geom.get());
2679
2680 Entity entity;
2681 entity.SetContents(contents);
2682 entity.SetTransform(transform);
2683
2684 success = success && entity.Render(context, pass);
2685 }
2686
2687 // Draw a ruler to show the length in portion of rect size.
2688 auto screen_top_right =
2689 Matrix::MakeScale(GetContentScale()).Invert() * top_right;
2690 constexpr float font_size = 13.0f;
2691 for (int i = -1; i < 100; i++) {
2692 float screen_offset_y = static_cast<float>(i) * 20.0f;
2693 std::string label;
2694 if (i == -1) {
2695 label = "Ruler: (in portion of rect size)";
2696 } else if (i == 0) {
2697 label = "- 0.0";
2698 } else {
2699 float portion_of_rect =
2700 screen_offset_y * GetContentScale().y / scale / rect_size;
2701 label = std::format("- {:.2g}", portion_of_rect);
2702 }
2703 ImGui::GetBackgroundDrawList()->AddText(
2704 nullptr, font_size,
2705 // Draw the ruler at around the flat part of the curve, which is
2706 // somewhere to the left of the top right corner.
2707 //
2708 // Offset vertically by font_size/2 so that the hyphen aligns with the
2709 // top of shape.
2710 {screen_top_right.x - 500,
2711 screen_top_right.y + screen_offset_y - font_size / 2},
2712 IM_COL32_WHITE, label.c_str());
2713 }
2714 return success;
2715 };
2716
2717 ASSERT_TRUE(OpenPlaygroundHere(callback));
2718 }

References impeller::Color::Blue(), font_size, impeller::Matrix::Invert(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and transform.

## ◆ TEST_P() [466/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2477 of file entity_unittests.cc.

2477 {
2478 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2479 // UI state.
2480 static float alpha = 10;
2481 static float beta = 10;
2482 static float radius = 40;
2483 static int degree = 4;
2484 static Color color = Color::Red();
2485
2486 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2487 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2488 ImGui::SliderFloat("Beta", &beta, 0, 100);
2489 ImGui::SliderInt("Degreee", &degree, 1, 20);
2490 ImGui::SliderFloat("Radius", &radius, 0, 400);
2491 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2492 ImGui::End();
2493
2494 auto contents = std::make_shared<SolidColorContents>();
2495 std::unique_ptr<SuperellipseGeometry> geom =
2496 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2497 alpha, beta);
2498 contents->SetColor(color);
2499 contents->SetGeometry(geom.get());
2500
2501 Entity entity;
2502 entity.SetContents(contents);
2503
2504 return entity.Render(context, pass);
2505 };
2506
2507 ASSERT_TRUE(OpenPlaygroundHere(callback));
2508 }

References impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [467/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2426 of file entity_unittests.cc.

2426 {
2427 if (GetParam() != PlaygroundBackend::kVulkan) {
2428 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2429 }
2430 EXPECT_DEATH(
2431 // The easiest way to trigger a validation error is to try to compile
2432 // a shader with an unsupported pixel format.
2433 GetContentContext()->GetBlendColorBurnPipeline({
2434 .color_attachment_pixel_format = PixelFormat::kUnknown,
2435 .has_depth_stencil_attachments = false,
2436 }),
2437 "");
2438 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [468/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2284 of file entity_unittests.cc.

2284 {
2285 RenderTarget target;
2286 testing::MockRenderPass mock_pass(GetContext(), target);
2287
2288 auto get_result = [this, &mock_pass](const flutter::DlPath& path) {
2289 auto geometry = Geometry::MakeFillPath(
2290 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2291 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2292 };
2293
2294 // Convex path
2295 {
2296 GeometryResult result =
2297 get_result(flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 100, 100)));
2298 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2299 }
2300
2301 // Concave path
2302 {
2303 flutter::DlPath path = flutter::DlPathBuilder{}
2304 .MoveTo({0, 0})
2305 .LineTo({100, 0})
2306 .LineTo({100, 100})
2307 .LineTo({51, 50})
2308 .Close()
2309 .TakePath();
2310 GeometryResult result = get_result(path);
2311 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2312 }
2313 }

References impeller::Close(), impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::GeometryResult::mode.

## ◆ TEST_P() [469/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 78 of file entity_unittests.cc.

78 {
79 auto image = CreateTextureForFixture("boston.jpg");
80 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
81 FilterInput::Make({image}));
82
83 // Without the crop rect (default behavior).
84 {
85 auto actual = filter->GetCoverage({});
86 auto expected = Rect::MakeSize(image->GetSize());
87
88 ASSERT_TRUE(actual.has_value());
89 ASSERT_RECT_NEAR(actual.value(), expected);
90 }
91
92 // With the crop rect.
93 {
94 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
95 filter->SetCoverageHint(expected);
96 auto actual = filter->GetCoverage({});
97
98 ASSERT_TRUE(actual.has_value());
99 ASSERT_RECT_NEAR(actual.value(), expected);
100 }
101 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [470/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 921 of file entity_unittests.cc.

921 {
922 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
923 auto boston = CreateTextureForFixture("boston.jpg");
924 auto kalimba = CreateTextureForFixture("kalimba.jpg");
925 ASSERT_TRUE(bridge && boston && kalimba);
926
927 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
928 auto fi_bridge = FilterInput::Make(bridge);
929 auto fi_boston = FilterInput::Make(boston);
930 auto fi_kalimba = FilterInput::Make(kalimba);
931
932 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
933 BlendMode::kModulate, {fi_kalimba, fi_boston});
934
935 auto blend1 = ColorFilterContents::MakeBlend(
936 BlendMode::kScreen,
937 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
938
939 Entity entity;
940 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
941 Matrix::MakeTranslation({500, 300}) *
942 Matrix::MakeScale(Vector2{0.5, 0.5}));
943 entity.SetContents(blend1);
944 return entity.Render(context, pass);
945 };
946 ASSERT_TRUE(OpenPlaygroundHere(callback));
947 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [471/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 949 of file entity_unittests.cc.

949 {
950 auto boston =
951 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
952 ASSERT_TRUE(boston);
953
954 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
955 const char* input_type_names[] = {"Texture", "Solid Color"};
956 const char* blur_type_names[] = {"Image blur", "Mask blur"};
957 const char* pass_variation_names[] = {"New"};
958 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
959 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
960 const FilterContents::BlurStyle blur_styles[] = {
961 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
962 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
963 const Entity::TileMode tile_modes[] = {
964 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
965 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
966
967 // UI state.
968 static int selected_input_type = 0;
969 static Color input_color = Color::Black();
970 static int selected_blur_type = 0;
971 static int selected_pass_variation = 0;
972 static bool combined_sigma = false;
973 static float blur_amount_coarse[2] = {0, 0};
974 static float blur_amount_fine[2] = {10, 10};
975 static int selected_blur_style = 0;
976 static int selected_tile_mode = 3;
977 static Color cover_color(1, 0, 0, 0.2);
978 static Color bounds_color(0, 1, 0, 0.1);
979 static float offset[2] = {500, 400};
980 static float rotation = 0;
981 static float scale[2] = {0.65, 0.65};
982 static float skew[2] = {0, 0};
983 static float path_rect[4] = {0, 0,
984 static_cast<float>(boston->GetSize().width),
985 static_cast<float>(boston->GetSize().height)};
986
987 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
988 {
989 ImGui::Combo("Input type", &selected_input_type, input_type_names,
990 sizeof(input_type_names) / sizeof(char*));
991 if (selected_input_type == 0) {
992 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
993 } else {
994 ImGui::ColorEdit4("Input color",
995 reinterpret_cast<float*>(&input_color));
996 }
997 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
998 sizeof(blur_type_names) / sizeof(char*));
999 if (selected_blur_type == 0) {
1000 ImGui::Combo("Pass variation", &selected_pass_variation,
1001 pass_variation_names,
1002 sizeof(pass_variation_names) / sizeof(char*));
1003 }
1004 ImGui::Checkbox("Combined sigma", &combined_sigma);
1005 if (combined_sigma) {
1006 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1007 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1008 blur_amount_coarse[1] = blur_amount_coarse[0];
1009 blur_amount_fine[1] = blur_amount_fine[0];
1010 } else {
1011 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1012 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1013 }
1014 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1015 sizeof(blur_style_names) / sizeof(char*));
1016 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1017 sizeof(tile_mode_names) / sizeof(char*));
1018 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1019 ImGui::ColorEdit4("Bounds color ",
1020 reinterpret_cast<float*>(&bounds_color));
1021 ImGui::SliderFloat2("Translation", offset, 0,
1022 pass.GetRenderTargetSize().width);
1023 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1024 ImGui::SliderFloat2("Scale", scale, 0, 3);
1025 ImGui::SliderFloat2("Skew", skew, -3, 3);
1026 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1027 }
1028 ImGui::End();
1029
1030 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1031 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1032
1033 std::shared_ptr<Contents> input;
1034 Size input_size;
1035
1036 auto input_rect =
1037 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1038
1039 std::unique_ptr<Geometry> solid_color_input;
1040 if (selected_input_type == 0) {
1041 auto texture = std::make_shared<TextureContents>();
1042 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1043 texture->SetDestinationRect(input_rect);
1044 texture->SetTexture(boston);
1045 texture->SetOpacity(input_color.alpha);
1046
1047 input = texture;
1048 input_size = input_rect.GetSize();
1049 } else {
1050 auto fill = std::make_shared<SolidColorContents>();
1051 fill->SetColor(input_color);
1052 solid_color_input =
1053 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1054
1055 fill->SetGeometry(solid_color_input.get());
1056
1057 input = fill;
1058 input_size = input_rect.GetSize();
1059 }
1060
1061 std::shared_ptr<FilterContents> blur;
1062 switch (selected_pass_variation) {
1063 case 0:
1064 blur = std::make_shared<GaussianBlurFilterContents>(
1065 blur_sigma_x.sigma, blur_sigma_y.sigma,
1066 tile_modes[selected_tile_mode], /*bounds=*/std::nullopt,
1067 blur_styles[selected_blur_style],
1068 /*geometry=*/nullptr);
1069 blur->SetInputs({FilterInput::Make(input)});
1070 break;
1071 case 1:
1072 blur = FilterContents::MakeGaussianBlur(
1073 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1074 tile_modes[selected_tile_mode],
1075 /*bounds=*/std::nullopt, blur_styles[selected_blur_style]);
1076 break;
1077 };
1078 FML_CHECK(blur);
1079
1080 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1081 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1082 blur_styles[selected_blur_style]);
1083
1084 auto ctm = Matrix::MakeScale(GetContentScale()) *
1085 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1086 Matrix::MakeRotationZ(Radians(rotation)) *
1087 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1088 Matrix::MakeSkew(skew[0], skew[1]) *
1089 Matrix::MakeTranslation(-Point(input_size) / 2);
1090
1091 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1092
1093 Entity entity;
1094 entity.SetContents(target_contents);
1095 entity.SetTransform(ctm);
1096
1097 entity.Render(context, pass);
1098
1099 // Renders a red "cover" rectangle that shows the original position of the
1100 // unfiltered input.
1101 Entity cover_entity;
1102 std::unique_ptr<Geometry> geom =
1103 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1104 auto contents = std::make_shared<SolidColorContents>();
1105 contents->SetColor(cover_color);
1106 contents->SetGeometry(geom.get());
1107 cover_entity.SetContents(std::move(contents));
1108 cover_entity.SetTransform(ctm);
1109 cover_entity.Render(context, pass);
1110
1111 // Renders a green bounding rect of the target filter.
1112 Entity bounds_entity;
1113 std::optional<Rect> target_contents_coverage =
1114 target_contents->GetCoverage(entity);
1115 if (target_contents_coverage.has_value()) {
1116 std::unique_ptr<Geometry> geom =
1117 Geometry::MakeFillPath(flutter::DlPath::MakeRect(
1118 target_contents->GetCoverage(entity).value()));
1119 auto contents = std::make_shared<SolidColorContents>();
1120 contents->SetColor(bounds_color);
1121 contents->SetGeometry(geom.get());
1122
1123 bounds_entity.SetContents(contents);
1124 bounds_entity.SetTransform(Matrix());
1125 bounds_entity.Render(context, pass);
1126 }
1127
1128 return true;
1129 };
1130 ASSERT_TRUE(OpenPlaygroundHere(callback));
1131 }

References impeller::Color::alpha, impeller::Color::Black(), impeller::Entity::GetCoverage(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::FilterContents::kInner, impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::FilterContents::kOuter, impeller::kPi, impeller::Entity::kRepeat, impeller::FilterContents::kSolid, impeller::FilterInput::Make(), impeller::FilterContents::MakeBorderMaskBlur(), impeller::Geometry::MakeFillPath(), impeller::FilterContents::MakeGaussianBlur(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [472/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 103 of file entity_unittests.cc.

103 {
104 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
105 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
106
107 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
108 Rect::MakeXYWH(200, 200, 200, 200));
109 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [473/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantStrokePathAllocation |
| ) |  |

Definition at line 2826 of file entity_unittests.cc.

2826 {
2827 flutter::DlPathBuilder builder;
2828 for (int i = 0; i < 10000; i++) {
2829 builder.LineTo(Point(i, i));
2830 }
2831 flutter::DlPath path = builder.TakePath();
2832 auto geom = Geometry::MakeStrokePath(path, {.width = 10.0f});
2833
2834 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2835 Entity entity;
2836
2837 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2838
2839 RenderTargetAllocator allocator(
2840 content_context.GetContext()->GetResourceAllocator());
2841
2842 auto render_target = allocator.CreateOffscreen(
2843 *content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);
2844 auto pass = cmd_buffer->CreateRenderPass(render_target);
2845
2846 GeometryResult result =
2847 geom->GetPositionBuffer(content_context, entity, *pass);
2848
2849 // Validate the buffer data overflowed the small buffer
2850 EXPECT_GT(result.vertex_buffer.vertex_count, kPointArenaSize);
2851
2852 // Validate that there are no uninitialized points near the gap.
2853 Point* written_data = reinterpret_cast<Point*>(
2854 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2855 result.vertex_buffer.vertex_buffer.GetRange().offset));
2856
2857 std::vector<Point> expected = {
2858 Point(2043.46, 2050.54), //
2859 Point(2050.54, 2043.46), //
2860 Point(2044.46, 2051.54), //
2861 Point(2051.54, 2044.46), //
2862 Point(2045.46, 2052.54) //
2863 };
2864
2865 Point point = written_data[kPointArenaSize - 2];
2866 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2867 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2868
2869 point = written_data[kPointArenaSize - 1];
2870 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2871 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2872
2873 point = written_data[kPointArenaSize];
2874 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2875 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2876
2877 point = written_data[kPointArenaSize + 1];
2878 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2879 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2880
2881 point = written_data[kPointArenaSize + 2];
2882 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2883 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2884 }
impeller::kPointArenaSize
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition: tessellator.h:25

References impeller::RenderTargetAllocator::CreateOffscreen(), impeller::BufferView::GetBuffer(), impeller::BufferView::GetRange(), impeller::kPointArenaSize, impeller::Geometry::MakeStrokePath(), impeller::Range::offset, impeller::DeviceBuffer::OnGetContents(), impeller::VertexBuffer::vertex_buffer, impeller::GeometryResult::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [474/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2082 of file entity_unittests.cc.

2082 {
2083 Matrix matrix;
2084 LinearGradientContents contents;
2085 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2086 contents.SetGeometry(geom.get());
2087
2088 contents.SetColors({Color::CornflowerBlue()});
2089 EXPECT_TRUE(contents.IsOpaque(matrix));
2090 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2091 EXPECT_FALSE(contents.IsOpaque(matrix));
2092 contents.SetColors({Color::CornflowerBlue()});
2093 contents.SetTileMode(Entity::TileMode::kDecal);
2094 EXPECT_FALSE(contents.IsOpaque(matrix));
2095
2096 // Create stroked path that required alpha coverage.
2097 geom = Geometry::MakeStrokePath(
2098 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2099 {.width = 0.05f});
2100 contents.SetGeometry(geom.get());
2101 contents.SetColors({Color::CornflowerBlue()});
2102
2103 EXPECT_FALSE(contents.IsOpaque(matrix));
2104 }

References impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::LinearGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [475/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1560 of file entity_unittests.cc.

1560 {
1561 auto image = CreateTextureForFixture("kalimba.jpg");
1562 ASSERT_TRUE(image);
1563
1564 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1565 auto filtered =
1566 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1567
1568 // Define the entity that will serve as the control image as a Gaussian blur
1569 // filter with no filter at all.
1570 Entity entity_left;
1571 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1572 Matrix::MakeTranslation({100, 300}) *
1573 Matrix::MakeScale(Vector2{0.5, 0.5}));
1574 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1575 Sigma{0}, Sigma{0});
1576 entity_left.SetContents(unfiltered);
1577
1578 // Define the entity that will be filtered from linear to sRGB.
1579 Entity entity_right;
1580 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1581 Matrix::MakeTranslation({500, 300}) *
1582 Matrix::MakeScale(Vector2{0.5, 0.5}));
1583 entity_right.SetContents(filtered);
1584 return entity_left.Render(context, pass) &&
1585 entity_right.Render(context, pass);
1586 };
1587
1588 ASSERT_TRUE(OpenPlaygroundHere(callback));
1589 }

References impeller::FilterInput::Make(), impeller::FilterContents::MakeGaussianBlur(), impeller::ColorFilterContents::MakeLinearToSrgbFilter(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [476/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1538 of file entity_unittests.cc.

1538 {
1539 // Set up a simple color background.
1540 auto geom = Geometry::MakeFillPath(
1541 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1542 auto fill = std::make_shared<SolidColorContents>();
1543 fill->SetGeometry(geom.get());
1544 fill->SetColor(Color::MintCream());
1545
1546 auto filter =
1547 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1548
1549 Entity e;
1550 e.SetTransform(Matrix());
1551
1552 // Confirm that the actual filter coverage matches the expected coverage.
1553 auto actual = filter->GetCoverage(e);
1554 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1555
1556 ASSERT_TRUE(actual.has_value());
1557 ASSERT_RECT_NEAR(actual.value(), expected);
1558 }

References ASSERT_RECT_NEAR, impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), impeller::ColorFilterContents::MakeLinearToSrgbFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::MintCream(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [477/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1133 of file entity_unittests.cc.

1133 {
1134 auto boston = CreateTextureForFixture("boston.jpg");
1135 ASSERT_TRUE(boston);
1136
1137 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1138 const char* morphology_type_names[] = {"Dilate", "Erode"};
1139 const FilterContents::MorphType morphology_types[] = {
1140 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1141 static Color input_color = Color::Black();
1142 // UI state.
1143 static int selected_morphology_type = 0;
1144 static float radius[2] = {20, 20};
1145 static Color cover_color(1, 0, 0, 0.2);
1146 static Color bounds_color(0, 1, 0, 0.1);
1147 static float offset[2] = {500, 400};
1148 static float rotation = 0;
1149 static float scale[2] = {0.65, 0.65};
1150 static float skew[2] = {0, 0};
1151 static float path_rect[4] = {0, 0,
1152 static_cast<float>(boston->GetSize().width),
1153 static_cast<float>(boston->GetSize().height)};
1154 static float effect_transform_scale = 1;
1155
1156 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1157 {
1158 ImGui::Combo("Morphology type", &selected_morphology_type,
1159 morphology_type_names,
1160 sizeof(morphology_type_names) / sizeof(char*));
1161 ImGui::SliderFloat2("Radius", radius, 0, 200);
1162 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1163 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1164 ImGui::ColorEdit4("Bounds color ",
1165 reinterpret_cast<float*>(&bounds_color));
1166 ImGui::SliderFloat2("Translation", offset, 0,
1167 pass.GetRenderTargetSize().width);
1168 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1169 ImGui::SliderFloat2("Scale", scale, 0, 3);
1170 ImGui::SliderFloat2("Skew", skew, -3, 3);
1171 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1172 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1173 3);
1174 }
1175 ImGui::End();
1176
1177 std::shared_ptr<Contents> input;
1178 Size input_size;
1179
1180 auto input_rect =
1181 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1182 auto texture = std::make_shared<TextureContents>();
1183 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1184 texture->SetDestinationRect(input_rect);
1185 texture->SetTexture(boston);
1186 texture->SetOpacity(input_color.alpha);
1187
1188 input = texture;
1189 input_size = input_rect.GetSize();
1190
1191 auto contents = FilterContents::MakeMorphology(
1192 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1193 morphology_types[selected_morphology_type]);
1194 contents->SetEffectTransform(Matrix::MakeScale(
1195 Vector2{effect_transform_scale, effect_transform_scale}));
1196
1197 auto ctm = Matrix::MakeScale(GetContentScale()) *
1198 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1199 Matrix::MakeRotationZ(Radians(rotation)) *
1200 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1201 Matrix::MakeSkew(skew[0], skew[1]) *
1202 Matrix::MakeTranslation(-Point(input_size) / 2);
1203
1204 Entity entity;
1205 entity.SetContents(contents);
1206 entity.SetTransform(ctm);
1207
1208 entity.Render(context, pass);
1209
1210 // Renders a red "cover" rectangle that shows the original position of the
1211 // unfiltered input.
1212 Entity cover_entity;
1213 std::unique_ptr<Geometry> geom =
1214 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1215 auto cover_contents = std::make_shared<SolidColorContents>();
1216 cover_contents->SetColor(cover_color);
1217 cover_contents->SetGeometry(geom.get());
1218 cover_entity.SetContents(cover_contents);
1219 cover_entity.SetTransform(ctm);
1220 cover_entity.Render(context, pass);
1221
1222 // Renders a green bounding rect of the target filter.
1223 Entity bounds_entity;
1224 std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1225 flutter::DlPath::MakeRect(contents->GetCoverage(entity).value()));
1226 auto bounds_contents = std::make_shared<SolidColorContents>();
1227 bounds_contents->SetColor(bounds_color);
1228 bounds_contents->SetGeometry(bounds_geom.get());
1229 bounds_entity.SetContents(std::move(bounds_contents));
1230 bounds_entity.SetTransform(Matrix());
1231
1232 bounds_entity.Render(context, pass);
1233
1234 return true;
1235 };
1236 ASSERT_TRUE(OpenPlaygroundHere(callback));
1237 }

References impeller::Color::alpha, impeller::Color::Black(), impeller::FilterContents::kDilate, impeller::FilterContents::kErode, impeller::kPi, impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), impeller::FilterContents::MakeMorphology(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [478/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2165 of file entity_unittests.cc.

2165 {
2166 std::vector<Point> points = {{10, 20}, {100, 200}};
2167 PointFieldGeometry geometry(points.data(), 2, 5.0, false);
2168 ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2169 ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2170 Rect::MakeLTRB(35, 15, 135, 205));
2171 }

References impeller::PointFieldGeometry::GetCoverage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and points.

## ◆ TEST_P() [479/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2106 of file entity_unittests.cc.

2106 {
2107 Matrix matrix;
2108 RadialGradientContents contents;
2109 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2110 contents.SetGeometry(geom.get());
2111
2112 contents.SetColors({Color::CornflowerBlue()});
2113 EXPECT_TRUE(contents.IsOpaque(matrix));
2114 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2115 EXPECT_FALSE(contents.IsOpaque(matrix));
2116 contents.SetColors({Color::CornflowerBlue()});
2117 contents.SetTileMode(Entity::TileMode::kDecal);
2118 EXPECT_FALSE(contents.IsOpaque(matrix));
2119
2120 // Create stroked path that required alpha coverage.
2121 geom = Geometry::MakeStrokePath(
2122 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2123 {.width = 0.05});
2124 contents.SetGeometry(geom.get());
2125 contents.SetColors({Color::CornflowerBlue()});
2126
2127 EXPECT_FALSE(contents.IsOpaque(matrix));
2128 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::RadialGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [480/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RoundSuperellipseGetPositionBufferFlushes |
| ) |  |

Definition at line 2947 of file entity_unittests.cc.

2947 {
2948 RenderTarget target;
2949 testing::MockRenderPass mock_pass(GetContext(), target);
2950
2951 auto content_context = std::make_shared<FlushTestContentContext>(
2952 GetContext(), GetTypographerContext(),
2953 std::make_shared<FlushTestAllocator>());
2954 auto geometry =
2955 Geometry::MakeRoundSuperellipse(Rect::MakeLTRB(0, 0, 100, 100), 5);
2956 auto result = geometry->GetPositionBuffer(*content_context, {}, mock_pass);
2957
2958 auto device_buffer = reinterpret_cast<const FlushTestDeviceBuffer*>(
2959 result.vertex_buffer.vertex_buffer.GetBuffer());
2960 EXPECT_TRUE(device_buffer->flush_called());
2961 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::Geometry::MakeRoundSuperellipse().

## ◆ TEST_P() [481/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1396 of file entity_unittests.cc.

1396 {
1397 auto callback = [&](ContentContext& context, RenderPass& pass) {
1398 static Color color = Color::Red();
1399 static float corner_radius = 100;
1400 static float blur_radius = 100;
1401 static bool show_coverage = false;
1402 static Color coverage_color = Color::Green().WithAlpha(0.2);
1403 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1404 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1405 Color::White());
1406
1407 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1408 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1409 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1410 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1411 ImGui::Checkbox("Show coverage", &show_coverage);
1412 if (show_coverage) {
1413 ImGui::ColorEdit4("Coverage color",
1414 reinterpret_cast<Scalar*>(&coverage_color));
1415 }
1416 ImGui::End();
1417
1418 auto [top_left, bottom_right] =
1419 DrawPlaygroundLine(top_left_point, bottom_right_point);
1420 auto rect =
1421 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1422
1423 auto contents = std::make_unique<SolidRRectBlurContents>();
1424 contents->SetShape(rect, corner_radius);
1425 contents->SetColor(color);
1426 contents->SetSigma(Radius(blur_radius));
1427
1428 Entity entity;
1429 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1430 entity.SetContents(std::move(contents));
1431 entity.Render(context, pass);
1432
1433 auto coverage = entity.GetCoverage();
1434 if (show_coverage && coverage.has_value()) {
1435 auto bounds_contents = std::make_unique<SolidColorContents>();
1436 auto geom = Geometry::MakeFillPath(
1437 flutter::DlPath::MakeRect(entity.GetCoverage().value()));
1438 bounds_contents->SetGeometry(geom.get());
1439 bounds_contents->SetColor(coverage_color.Premultiply());
1440 Entity bounds_entity;
1441 bounds_entity.SetContents(std::move(bounds_contents));
1442 bounds_entity.Render(context, pass);
1443 }
1444
1445 return true;
1446 };
1447 ASSERT_TRUE(OpenPlaygroundHere(callback));
1448 }

References blur_radius, impeller::DrawPlaygroundLine(), impeller::Entity::GetCoverage(), impeller::Color::Green(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Premultiply(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [482/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1757 of file entity_unittests.cc.

1757 {
1758 auto runtime_stages_result =
1759 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1760 ABSL_ASSERT_OK(runtime_stages_result);
1761 std::shared_ptr<RuntimeStage> runtime_stage =
1762 runtime_stages_result
1763 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1764 ASSERT_TRUE(runtime_stage);
1765 ASSERT_TRUE(runtime_stage->IsDirty());
1766
1767 bool expect_dirty = true;
1768
1769 PipelineRef first_pipeline;
1770 std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1771
1772 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1773 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1774
1775 auto contents = std::make_shared<RuntimeEffectContents>();
1776 contents->SetGeometry(geom.get());
1777 contents->SetRuntimeStage(runtime_stage);
1778
1779 struct FragUniforms {
1780 Vector2 iResolution;
1781 Scalar iTime;
1782 } frag_uniforms = {
1783 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1784 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1785 };
1786 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1787 uniform_data->resize(sizeof(FragUniforms));
1788 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1789 contents->SetUniformData(uniform_data);
1790
1791 Entity entity;
1792 entity.SetContents(contents);
1793 bool result = contents->Render(context, entity, pass);
1794
1795 if (expect_dirty) {
1796 first_pipeline = pass.GetCommands().back().pipeline;
1797 } else {
1798 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1799 }
1800 expect_dirty = false;
1801 return result;
1802 };
1803
1804 // Simulate some renders and hot reloading of the shader.
1805 auto content_context = GetContentContext();
1806 {
1807 RenderTarget target =
1808 content_context->GetRenderTargetCache()->CreateOffscreen(
1809 *content_context->GetContext(), {1, 1}, 1u);
1810
1811 testing::MockRenderPass mock_pass(GetContext(), target);
1812 callback(*content_context, mock_pass);
1813 callback(*content_context, mock_pass);
1814
1815 // Dirty the runtime stage.
1816 auto runtime_stages_result =
1817 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1818 ABSL_ASSERT_OK(runtime_stages_result);
1819 runtime_stage =
1820 runtime_stages_result
1821 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1822
1823 ASSERT_TRUE(runtime_stage->IsDirty());
1824 expect_dirty = true;
1825
1826 callback(*content_context, mock_pass);
1827 }
1828 }
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:89

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [483/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1879 of file entity_unittests.cc.

1879 {
1880 auto runtime_stages_result =
1881 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1882 ABSL_ASSERT_OK(runtime_stages_result);
1883 std::shared_ptr<RuntimeStage> runtime_stage =
1884 runtime_stages_result
1885 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1886 ASSERT_TRUE(runtime_stage);
1887 ASSERT_TRUE(runtime_stage->IsDirty());
1888
1889 auto contents = std::make_shared<RuntimeEffectContents>();
1890 contents->SetRuntimeStage(runtime_stage);
1891
1892 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1893 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [484/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1830 of file entity_unittests.cc.

1830 {
1831 auto runtime_stages_result =
1832 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1833 ABSL_ASSERT_OK(runtime_stages_result);
1834 auto runtime_stage =
1835 runtime_stages_result
1836 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1837 ASSERT_TRUE(runtime_stage);
1838 ASSERT_TRUE(runtime_stage->IsDirty());
1839
1840 auto contents = std::make_shared<RuntimeEffectContents>();
1841 auto geom = Geometry::MakeCover();
1842 contents->SetGeometry(geom.get());
1843 contents->SetRuntimeStage(runtime_stage);
1844
1845 struct FragUniforms {
1846 Vector2 iResolution;
1847 Scalar iTime;
1848 } frag_uniforms = {
1849 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1850 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1851 };
1852 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1853 uniform_data->resize(sizeof(FragUniforms));
1854 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1855 contents->SetUniformData(uniform_data);
1856
1857 Entity entity;
1858 entity.SetContents(contents);
1859
1860 // Create a render target with a depth-stencil, similar to how EntityPass
1861 // does.
1862 RenderTarget target =
1863 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1864 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1865 "RuntimeEffect Texture");
1866 testing::MockRenderPass pass(GetContext(), target);
1867
1868 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1869 ASSERT_EQ(pass.GetCommands().size(), 1u);
1870 const auto& command = pass.GetCommands()[0];
1871 ASSERT_TRUE(command.pipeline->GetDescriptor()
1872 .GetDepthStencilAttachmentDescriptor()
1873 .has_value());
1874 ASSERT_TRUE(command.pipeline->GetDescriptor()
1875 .GetFrontStencilAttachmentDescriptor()
1876 .has_value());
1877 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [485/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1895 of file entity_unittests.cc.

1895 {
1896 if (GetBackend() != PlaygroundBackend::kVulkan) {
1897 GTEST_SKIP() << "Test only applies to Vulkan";
1898 }
1899
1900 auto runtime_stages_result =
1901 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1902 ABSL_ASSERT_OK(runtime_stages_result);
1903 auto runtime_stage =
1904 runtime_stages_result
1905 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1906 ASSERT_TRUE(runtime_stage);
1907 ASSERT_TRUE(runtime_stage->IsDirty());
1908
1909 auto contents = std::make_shared<RuntimeEffectContents>();
1910 auto geom = Geometry::MakeCover();
1911 contents->SetGeometry(geom.get());
1912 contents->SetRuntimeStage(runtime_stage);
1913
1914 struct FragUniforms {
1915 Vector2 iResolution;
1916 Scalar iTime;
1917 } frag_uniforms = {
1918 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1919 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1920 };
1921 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1922 uniform_data->resize(sizeof(FragUniforms));
1923 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1924
1925 auto buffer_view = RuntimeEffectContents::EmplaceUniform(
1926 uniform_data->data(), GetContentContext()->GetTransientsDataBuffer(),
1927 runtime_stage->GetUniforms()[0]);
1928
1929 // 16 bytes:
1930 // 8 bytes for iResolution
1931 // 4 bytes for iTime
1932 // 4 bytes padding
1933 EXPECT_EQ(buffer_view.GetRange().length, 16u);
1934 }

References buffer_view, impeller::RuntimeEffectContents::EmplaceUniform(), impeller::kVulkan, impeller::Geometry::MakeCover(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [486/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1239 of file entity_unittests.cc.

1239 {
1240 Entity entity;
1241 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSrcOver);
1242 entity.SetBlendMode(BlendMode::kClear);
1243 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1244 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSrcOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [487/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2796 of file entity_unittests.cc.

2796 {
2797 auto contents = SolidColorContents();
2798 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2799 auto result = contents.ApplyColorFilter([](const Color& color) {
2800 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2801 });
2802 ASSERT_TRUE(result);
2803 ASSERT_COLOR_NEAR(contents.GetColor(),
2804 Color(0.424452, 0.828743, 0.79105, 0.9375));
2805 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [488/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2041 of file entity_unittests.cc.

2041 {
2042 Matrix matrix;
2043 SolidColorContents contents;
2044 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2045 contents.SetGeometry(geom.get());
2046
2047 contents.SetColor(Color::CornflowerBlue());
2048 EXPECT_TRUE(contents.IsOpaque(matrix));
2049 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2050 EXPECT_FALSE(contents.IsOpaque(matrix));
2051
2052 // Create stroked path that required alpha coverage.
2053 geom = Geometry::MakeStrokePath(flutter::DlPath::MakeLine({0, 0}, {100, 100}),
2054 {.width = 0.05});
2055 contents.SetGeometry(geom.get());
2056 contents.SetColor(Color::CornflowerBlue());
2057
2058 EXPECT_FALSE(contents.IsOpaque(matrix));
2059 }

References impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::SolidColorContents::SetColor(), and impeller::ColorSourceContents::SetGeometry().

## ◆ TEST_P() [489/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 720 of file entity_unittests.cc.

720 {
721 {
722 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{});
723 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
724 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
725 }
726
727 {
728 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
729 {
730 .width = 1.0f,
731 .miter_limit = 8.0f,
732 });
733 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
734 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
735 }
736
737 {
738 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
739 {
740 .width = 1.0f,
741 .miter_limit = -1.0f,
742 });
743 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
744 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
745 }
746 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [490/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 688 of file entity_unittests.cc.

688 {
689 {
690 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{});
691 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
692 // Defaults.
693 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
694 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
695 }
696
697 {
698 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
699 {
700 .width = 1.0f,
701 .cap = Cap::kSquare,
702 .miter_limit = 4.0f,
703 });
704 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
705 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
706 }
707
708 {
709 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
710 {
711 .width = 1.0f,
712 .cap = Cap::kRound,
713 .miter_limit = 4.0f,
714 });
715 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
716 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
717 }
718 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [491/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1351 of file entity_unittests.cc.

1351 {
1352 // No transform
1353 {
1354 auto fill = std::make_shared<SolidColorContents>();
1355 fill->SetColor(Color::CornflowerBlue());
1356 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1357 auto geom = Geometry::MakeFillPath(flutter::DlPath::MakeRect(expected));
1358 fill->SetGeometry(geom.get());
1359
1360 auto coverage = fill->GetCoverage({});
1361 ASSERT_TRUE(coverage.has_value());
1362 ASSERT_RECT_NEAR(coverage.value(), expected);
1363 }
1364
1365 // Entity transform
1366 {
1367 auto fill = std::make_shared<SolidColorContents>();
1368 auto geom = Geometry::MakeFillPath(
1369 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1370 fill->SetColor(Color::CornflowerBlue());
1371 fill->SetGeometry(geom.get());
1372
1373 Entity entity;
1374 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1375 entity.SetContents(std::move(fill));
1376
1377 auto coverage = entity.GetCoverage();
1378 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1379 ASSERT_TRUE(coverage.has_value());
1380 ASSERT_RECT_NEAR(coverage.value(), expected);
1381 }
1382
1383 // No coverage for fully transparent colors
1384 {
1385 auto fill = std::make_shared<SolidColorContents>();
1386 auto geom = Geometry::MakeFillPath(
1387 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1388 fill->SetColor(Color::WhiteTransparent());
1389 fill->SetGeometry(geom.get());
1390
1391 auto coverage = fill->GetCoverage({});
1392 ASSERT_FALSE(coverage.has_value());
1393 }
1394 }

References ASSERT_RECT_NEAR, impeller::Color::CornflowerBlue(), impeller::Entity::GetCoverage(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Color::WhiteTransparent().

## ◆ TEST_P() [492/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1252 of file entity_unittests.cc.

1252 {
1253 {
1254 auto geometry = Geometry::MakeStrokePath(
1255 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1256 {
1257 .width = 4.0f,
1258 .cap = Cap::kButt,
1259 .join = Join::kBevel,
1260 .miter_limit = 4.0f,
1261 });
1262
1263 Entity entity;
1264 auto contents = std::make_unique<SolidColorContents>();
1265 contents->SetGeometry(geometry.get());
1266 contents->SetColor(Color::Black());
1267 entity.SetContents(std::move(contents));
1268 auto actual = entity.GetCoverage();
1269 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1270
1271 ASSERT_TRUE(actual.has_value());
1272 ASSERT_RECT_NEAR(actual.value(), expected);
1273 }
1274
1275 // Cover the Cap::kSquare case.
1276 {
1277 auto geometry = Geometry::MakeStrokePath(
1278 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1279 {
1280 .width = 4.0,
1281 .cap = Cap::kSquare,
1282 .join = Join::kBevel,
1283 .miter_limit = 4.0,
1284 });
1285
1286 Entity entity;
1287 auto contents = std::make_unique<SolidColorContents>();
1288 contents->SetGeometry(geometry.get());
1289 contents->SetColor(Color::Black());
1290 entity.SetContents(std::move(contents));
1291 auto actual = entity.GetCoverage();
1292 auto expected =
1293 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1294
1295 ASSERT_TRUE(actual.has_value());
1296 ASSERT_RECT_NEAR(actual.value(), expected);
1297 }
1298
1299 // Cover the Join::kMiter case.
1300 {
1301 auto geometry = Geometry::MakeStrokePath(
1302 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1303 {
1304 .width = 4.0f,
1305 .cap = Cap::kSquare,
1306 .join = Join::kMiter,
1307 .miter_limit = 2.0f,
1308 });
1309
1310 Entity entity;
1311 auto contents = std::make_unique<SolidColorContents>();
1312 contents->SetGeometry(geometry.get());
1313 contents->SetColor(Color::Black());
1314 entity.SetContents(std::move(contents));
1315 auto actual = entity.GetCoverage();
1316 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1317
1318 ASSERT_TRUE(actual.has_value());
1319 ASSERT_RECT_NEAR(actual.value(), expected);
1320 }
1321 }

References ASSERT_RECT_NEAR, impeller::Color::Black(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kSquare, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [493/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2201 of file entity_unittests.cc.

2201 {
2202 auto content_context = GetContentContext();
2203
2204 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2205 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2206 .has_depth_stencil_attachments = false,
2207 });
2208 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2209 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2210 .has_depth_stencil_attachments = true});
2211
2212 EXPECT_NE(default_gyph, alt_gyph);
2213 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2214 alt_gyph->GetDescriptor().GetSpecializationConstants());
2215
2216 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2217 PixelFormat::kA8UNormInt;
2218
2219 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2220 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2221 expected_constants);
2222 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [494/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1613 of file entity_unittests.cc.

1613 {
1614 auto image = CreateTextureForFixture("embarcadero.jpg");
1615 ASSERT_TRUE(image);
1616
1617 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1618 auto filtered =
1619 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1620
1621 // Define the entity that will serve as the control image as a Gaussian blur
1622 // filter with no filter at all.
1623 Entity entity_left;
1624 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1625 Matrix::MakeTranslation({100, 300}) *
1626 Matrix::MakeScale(Vector2{0.5, 0.5}));
1627 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1628 Sigma{0}, Sigma{0});
1629 entity_left.SetContents(unfiltered);
1630
1631 // Define the entity that will be filtered from sRGB to linear.
1632 Entity entity_right;
1633 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1634 Matrix::MakeTranslation({500, 300}) *
1635 Matrix::MakeScale(Vector2{0.5, 0.5}));
1636 entity_right.SetContents(filtered);
1637 return entity_left.Render(context, pass) &&
1638 entity_right.Render(context, pass);
1639 };
1640
1641 ASSERT_TRUE(OpenPlaygroundHere(callback));
1642 }

References impeller::FilterInput::Make(), impeller::FilterContents::MakeGaussianBlur(), impeller::Matrix::MakeScale(), impeller::ColorFilterContents::MakeSrgbToLinearFilter(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [495/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1591 of file entity_unittests.cc.

1591 {
1592 // Set up a simple color background.
1593 auto fill = std::make_shared<SolidColorContents>();
1594 auto geom = Geometry::MakeFillPath(
1595 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1596 fill->SetGeometry(geom.get());
1597 fill->SetColor(Color::DeepPink());
1598
1599 auto filter =
1600 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1601
1602 Entity e;
1603 e.SetTransform(Matrix());
1604
1605 // Confirm that the actual filter coverage matches the expected coverage.
1606 auto actual = filter->GetCoverage(e);
1607 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1608
1609 ASSERT_TRUE(actual.has_value());
1610 ASSERT_RECT_NEAR(actual.value(), expected);
1611 }

References ASSERT_RECT_NEAR, impeller::Color::DeepPink(), impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), impeller::ColorFilterContents::MakeSrgbToLinearFilter(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [496/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeArcGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2315 of file entity_unittests.cc.

2315 {
2316 RenderTarget target;
2317 testing::MockRenderPass mock_pass(GetContext(), target);
2318 Rect oval_bounds = Rect::MakeLTRB(100, 100, 200, 200);
2319
2320 // Butt caps never overlap
2321 {
2322 StrokeParameters stroke = {.width = 50.0f, .cap = Cap::kButt};
2323 for (auto start = 0; start < 360; start += 60) {
2324 for (auto sweep = 0; sweep < 360; sweep += 12) {
2325 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
2326 Degrees(sweep), stroke);
2327
2328 GeometryResult result =
2329 geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2330
2331 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal)
2332 << "start: " << start << " sweep: " << sweep;
2333 }
2334 }
2335 }
2336
2337 // Round caps with 10 stroke width overlap starting at 348.6 degrees
2338 {
2339 StrokeParameters stroke = {.width = 10.0f, .cap = Cap::kRound};
2340 for (auto start = 0; start < 360; start += 60) {
2341 for (auto sweep = 0; sweep < 360; sweep += 12) {
2342 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
2343 Degrees(sweep), stroke);
2344
2345 GeometryResult result =
2346 geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2347
2348 if (sweep < 348.6) {
2349 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal)
2350 << "start: " << start << " sweep: " << sweep;
2351 } else {
2352 EXPECT_EQ(result.mode, GeometryResult::Mode::kPreventOverdraw)
2353 << "start: " << start << " sweep: " << sweep;
2354 }
2355 }
2356 }
2357 }
2358
2359 // Round caps with 50 stroke width overlap starting at 300.1 degrees
2360 {
2361 StrokeParameters stroke = {.width = 50.0f, .cap = Cap::kRound};
2362 for (auto start = 0; start < 360; start += 60) {
2363 for (auto sweep = 0; sweep < 360; sweep += 12) {
2364 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
2365 Degrees(sweep), stroke);
2366
2367 GeometryResult result =
2368 geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2369
2370 if (sweep < 300.0) {
2371 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal)
2372 << "start: " << start << " sweep: " << sweep;
2373 } else {
2374 EXPECT_EQ(result.mode, GeometryResult::Mode::kPreventOverdraw)
2375 << "start: " << start << " sweep: " << sweep;
2376 }
2377 }
2378 }
2379 }
2380
2381 // Square caps with 10 stroke width overlap starting at 347.4 degrees
2382 {
2383 StrokeParameters stroke = {.width = 10.0f, .cap = Cap::kSquare};
2384 for (auto start = 0; start < 360; start += 60) {
2385 for (auto sweep = 0; sweep < 360; sweep += 12) {
2386 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
2387 Degrees(sweep), stroke);
2388
2389 GeometryResult result =
2390 geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2391
2392 if (sweep < 347.4) {
2393 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal)
2394 << "start: " << start << " sweep: " << sweep;
2395 } else {
2396 EXPECT_EQ(result.mode, GeometryResult::Mode::kPreventOverdraw)
2397 << "start: " << start << " sweep: " << sweep;
2398 }
2399 }
2400 }
2401 }
2402
2403 // Square caps with 50 stroke width overlap starting at 270.1 degrees
2404 {
2405 StrokeParameters stroke = {.width = 50.0f, .cap = Cap::kSquare};
2406 for (auto start = 0; start < 360; start += 60) {
2407 for (auto sweep = 0; sweep < 360; sweep += 12) {
2408 auto geometry = Geometry::MakeStrokedArc(oval_bounds, Degrees(start),
2409 Degrees(sweep), stroke);
2410
2411 GeometryResult result =
2412 geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2413
2414 if (sweep < 270.1) {
2415 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal)
2416 << "start: " << start << " sweep: " << sweep;
2417 } else {
2418 EXPECT_EQ(result.mode, GeometryResult::Mode::kPreventOverdraw)
2419 << "start: " << start << " sweep: " << sweep;
2420 }
2421 }
2422 }
2423 }
2424 }

References impeller::kButt, impeller::GeometryResult::kNormal, impeller::GeometryResult::kPreventOverdraw, impeller::kRound, impeller::kSquare, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeStrokedArc(), impeller::GeometryResult::mode, start, and impeller::StrokeParameters::width.

## ◆ TEST_P() [497/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 201 of file entity_unittests.cc.

201 {
202 const Point padding(300, 250);
203 const Point margin(140, 180);
204
205 auto callback = [&](ContentContext& context, RenderPass& pass) {
206 // Slightly above sqrt(2) by default, so that right angles are just below
207 // the limit and acute angles are over the limit (causing them to get
208 // beveled).
209 static Scalar miter_limit = 1.41421357;
210 static Scalar width = 30;
211
212 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
213 {
214 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
215 ImGui::SliderFloat("Stroke width", &width, 0, 100);
216 if (ImGui::Button("Reset")) {
217 miter_limit = 1.41421357;
218 width = 30;
219 }
220 }
221 ImGui::End();
222
223 auto world_matrix = Matrix::MakeScale(GetContentScale());
224 auto render_path = [width = width, &context, &pass, &world_matrix](
225 const flutter::DlPath& path, Cap cap, Join join) {
226 auto contents = std::make_unique<SolidColorContents>();
227 std::unique_ptr<Geometry> geom =
228 Geometry::MakeStrokePath(path, {
229 .width = width,
230 .cap = cap,
231 .join = join,
232 .miter_limit = miter_limit,
233 });
234 contents->SetGeometry(geom.get());
235 contents->SetColor(Color::Red());
236
237 Entity entity;
238 entity.SetTransform(world_matrix);
239 entity.SetContents(std::move(contents));
240
241 auto coverage = entity.GetCoverage();
242 if (coverage.has_value()) {
243 auto bounds_contents = std::make_unique<SolidColorContents>();
244
245 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
246 flutter::DlPath::MakeRect(entity.GetCoverage().value()));
247
248 bounds_contents->SetGeometry(geom.get());
249 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
250 Entity bounds_entity;
251 bounds_entity.SetContents(std::move(bounds_contents));
252 bounds_entity.Render(context, pass);
253 }
254
255 entity.Render(context, pass);
256 };
257
258 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
259 e_def(75, 75);
260 const Scalar r = 30;
261 // Cap::kButt demo.
262 {
263 Point off = Point(0, 0) * padding + margin;
264 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
265 static PlaygroundPoint point_b(off + b_def, r, Color::White());
266 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
267 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
268 static PlaygroundPoint point_d(off + d_def, r, Color::White());
269 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
270 render_path(flutter::DlPathBuilder{} //
271 .MoveTo(a)
272 .CubicCurveTo(b, d, c)
273 .TakePath(),
274 Cap::kButt, Join::kBevel);
275 }
276
277 // Cap::kSquare demo.
278 {
279 Point off = Point(1, 0) * padding + margin;
280 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
281 static PlaygroundPoint point_b(off + b_def, r, Color::White());
282 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
283 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
284 static PlaygroundPoint point_d(off + d_def, r, Color::White());
285 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
286 render_path(flutter::DlPathBuilder{} //
287 .MoveTo(a)
288 .CubicCurveTo(b, d, c)
289 .TakePath(),
290 Cap::kSquare, Join::kBevel);
291 }
292
293 // Cap::kRound demo.
294 {
295 Point off = Point(2, 0) * padding + margin;
296 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
297 static PlaygroundPoint point_b(off + b_def, r, Color::White());
298 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
299 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
300 static PlaygroundPoint point_d(off + d_def, r, Color::White());
301 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
302 render_path(flutter::DlPathBuilder{} //
303 .MoveTo(a)
304 .CubicCurveTo(b, d, c)
305 .TakePath(),
306 Cap::kRound, Join::kBevel);
307 }
308
309 // Join::kBevel demo.
310 {
311 Point off = Point(0, 1) * padding + margin;
312 static PlaygroundPoint point_a =
313 PlaygroundPoint(off + a_def, r, Color::White());
314 static PlaygroundPoint point_b =
315 PlaygroundPoint(off + e_def, r, Color::White());
316 static PlaygroundPoint point_c =
317 PlaygroundPoint(off + c_def, r, Color::White());
318 Point a = DrawPlaygroundPoint(point_a);
319 Point b = DrawPlaygroundPoint(point_b);
320 Point c = DrawPlaygroundPoint(point_c);
321 render_path(flutter::DlPathBuilder{} //
322 .MoveTo(a)
323 .LineTo(b)
324 .LineTo(c)
325 .Close()
326 .TakePath(),
327 Cap::kButt, Join::kBevel);
328 }
329
330 // Join::kMiter demo.
331 {
332 Point off = Point(1, 1) * padding + margin;
333 static PlaygroundPoint point_a(off + a_def, r, Color::White());
334 static PlaygroundPoint point_b(off + e_def, r, Color::White());
335 static PlaygroundPoint point_c(off + c_def, r, Color::White());
336 Point a = DrawPlaygroundPoint(point_a);
337 Point b = DrawPlaygroundPoint(point_b);
338 Point c = DrawPlaygroundPoint(point_c);
339 render_path(flutter::DlPathBuilder{} //
340 .MoveTo(a)
341 .LineTo(b)
342 .LineTo(c)
343 .Close()
344 .TakePath(),
345 Cap::kButt, Join::kMiter);
346 }
347
348 // Join::kRound demo.
349 {
350 Point off = Point(2, 1) * padding + margin;
351 static PlaygroundPoint point_a(off + a_def, r, Color::White());
352 static PlaygroundPoint point_b(off + e_def, r, Color::White());
353 static PlaygroundPoint point_c(off + c_def, r, Color::White());
354 Point a = DrawPlaygroundPoint(point_a);
355 Point b = DrawPlaygroundPoint(point_b);
356 Point c = DrawPlaygroundPoint(point_c);
357 render_path(flutter::DlPathBuilder{} //
358 .MoveTo(a)
359 .LineTo(b)
360 .LineTo(c)
361 .Close()
362 .TakePath(),
363 Cap::kButt, Join::kRound);
364 }
365
366 return true;
367 };
368 ASSERT_TRUE(OpenPlaygroundHere(callback));
369 }
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:87
impeller::Join
Join
An enum that describes ways to join two segments of a path.
Definition: stroke_parameters.h:20
impeller::Cap
Cap
An enum that describes ways to decorate the end of a path contour.
Definition: stroke_parameters.h:13

References impeller::saturated::b, impeller::Color::Black(), c, impeller::Close(), impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::Entity::GetCoverage(), impeller::Color::Green(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), padding, impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Color::White().

## ◆ TEST_P() [498/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 133 of file entity_unittests.cc.

133 {
134 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
135 flutter::DlPath path = flutter::DlPathBuilder{}
136 .MoveTo({100, 100})
137 .LineTo({100, 200})
138 .MoveTo({100, 300})
139 .LineTo({100, 400})
140 .MoveTo({100, 500})
141 .LineTo({100, 600})
142 .TakePath();
143
144 Entity entity;
145 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
146 auto contents = std::make_unique<TiledTextureContents>();
147 std::unique_ptr<Geometry> geom =
148 Geometry::MakeStrokePath(path, {.width = 100.0f});
149 contents->SetGeometry(geom.get());
150 contents->SetTexture(bridge);
151 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
152 entity.SetContents(std::move(contents));
153 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
154 }

References impeller::Entity::kClamp, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [499/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2130 of file entity_unittests.cc.

2130 {
2131 Matrix matrix;
2132 RadialGradientContents contents;
2133 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2134 contents.SetGeometry(geom.get());
2135
2136 contents.SetColors({Color::CornflowerBlue()});
2137 EXPECT_TRUE(contents.IsOpaque(matrix));
2138 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2139 EXPECT_FALSE(contents.IsOpaque(matrix));
2140 contents.SetColors({Color::CornflowerBlue()});
2141 contents.SetTileMode(Entity::TileMode::kDecal);
2142 EXPECT_FALSE(contents.IsOpaque(matrix));
2143
2144 // Create stroked path that required alpha coverage.
2145 geom = Geometry::MakeStrokePath(
2146 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2147 {.width = 0.05f});
2148 contents.SetGeometry(geom.get());
2149 contents.SetColors({Color::CornflowerBlue()});
2150
2151 EXPECT_FALSE(contents.IsOpaque(matrix));
2152 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::RadialGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [500/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2193 of file entity_unittests.cc.

2193 {
2194 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f), Rational(43, 100));
2195 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f), Rational(53, 100));
2196 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f), Rational(21, 10));
2197 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f), Rational(0, 1));
2198 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f), Rational(48, 1));
2199 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [501/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 111 of file entity_unittests.cc.

111 {
112 flutter::DlPath path = flutter::DlPathBuilder{}
113 .MoveTo({100, 100})
114 .LineTo({100, 200})
115 .MoveTo({100, 300})
116 .LineTo({100, 400})
117 .MoveTo({100, 500})
118 .LineTo({100, 600})
119 .TakePath();
120
121 Entity entity;
122 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
123 auto contents = std::make_unique<SolidColorContents>();
124
125 std::unique_ptr<Geometry> geom =
126 Geometry::MakeStrokePath(path, {.width = 5.0f});
127 contents->SetGeometry(geom.get());
128 contents->SetColor(Color::Red());
129 entity.SetContents(std::move(contents));
130 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
131 }

References impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [502/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2154 of file entity_unittests.cc.

2154 {
2155 Matrix matrix;
2156 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2157 TiledTextureContents contents;
2158 contents.SetTexture(bay_bridge);
2159 // This is a placeholder test. Images currently never decompress as opaque
2160 // (whether in Flutter or the playground), and so this should currently always
2161 // return false in practice.
2162 EXPECT_FALSE(contents.IsOpaque(matrix));
2163 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [503/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipeline |
| ) |  |

Definition at line 21 of file tiled_texture_contents_unittests.cc.

21 {
22 TextureDescriptor texture_desc;
23 texture_desc.size = {100, 100};
24 texture_desc.type = TextureType::kTexture2D;
25 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
26 texture_desc.storage_mode = StorageMode::kDevicePrivate;
27 auto texture =
28 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
29
30 auto geom = Geometry::MakeCover();
31 TiledTextureContents contents;
32 contents.SetTexture(texture);
33 contents.SetGeometry(geom.get());
34
35 auto content_context = GetContentContext();
36 auto buffer = content_context->GetContext()->CreateCommandBuffer();
37 auto render_target =
38 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
39 *content_context->GetContext(), {100, 100},
40 /*mip_count=*/1);
41 auto render_pass = buffer->CreateRenderPass(render_target);
42 auto recording_pass = std::make_shared<RecordingRenderPass>(
43 render_pass, GetContext(), render_target);
44
45 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass));
46 const std::vector<Command>& commands = recording_pass->GetCommands();
47
48 ASSERT_EQ(commands.size(), 1u);
49 #ifdef IMPELLER_DEBUG
50 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
51 "TextureFill Pipeline") != std::string::npos);
52 #endif // IMPELLER_DEBUG
53 auto options = OptionsFromPassAndEntity(*recording_pass, {});
54 options.primitive_type = PrimitiveType::kTriangleStrip;
55 EXPECT_EQ(commands[0].pipeline,
56 GetContentContext()->GetTiledTexturePipeline(options));
57
58 if (GetParam() == PlaygroundBackend::kMetal) {
59 recording_pass->EncodeCommands();
60 }
61 }
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
impeller::ContentContextOptions::primitive_type
PrimitiveType primitive_type
Definition: content_context.h:81

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kMetal, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::kTriangleStrip, impeller::Geometry::MakeCover(), impeller::OptionsFromPassAndEntity(), impeller::ContentContextOptions::primitive_type, impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [504/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipelineExternalOES |
| ) |  |

Definition at line 65 of file tiled_texture_contents_unittests.cc.

65 {
66 if (GetParam() != PlaygroundBackend::kOpenGLES) {
67 GTEST_SKIP()
68 << "External OES textures are only valid for the OpenGLES backend.";
69 }
70
71 TextureDescriptor texture_desc;
72 texture_desc.size = {100, 100};
73 texture_desc.type = TextureType::kTextureExternalOES;
74 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
75 texture_desc.storage_mode = StorageMode::kDevicePrivate;
76 auto texture =
77 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
78 auto contents = TextureContents::MakeRect(Rect::MakeSize(texture->GetSize()));
79 contents->SetTexture(texture);
80 contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
81 contents->SetStrictSourceRect(false);
82
83 auto content_context = GetContentContext();
84 auto buffer = content_context->GetContext()->CreateCommandBuffer();
85 auto render_target =
86 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
87 *content_context->GetContext(), {100, 100},
88 /*mip_count=*/1);
89 auto render_pass = buffer->CreateRenderPass(render_target);
90
91 ASSERT_TRUE(contents->Render(*GetContentContext(), {}, *render_pass));
92 const std::vector<Command>& commands = render_pass->GetCommands();
93
94 ASSERT_EQ(commands.size(), 1u);
95
96 auto options = OptionsFromPassAndEntity(*render_pass, {});
97 options.primitive_type = PrimitiveType::kTriangleStrip;
98 EXPECT_EQ(commands[0].pipeline,
99 GetContentContext()->GetTiledTextureExternalPipeline(options));
100 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kTextureExternalOES, impeller::kTriangleStrip, impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::OptionsFromPassAndEntity(), impeller::ContentContextOptions::primitive_type, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [505/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 156 of file entity_unittests.cc.

156 {
157 auto callback = [&](ContentContext& context, RenderPass& pass) {
158 Point offset(100, 100);
159
160 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
161 Point a = DrawPlaygroundPoint(point_a);
162 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
163 Point b = DrawPlaygroundPoint(point_b);
164 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
165 Color::White());
166 Point c = DrawPlaygroundPoint(point_c);
167 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
168 Point d = DrawPlaygroundPoint(point_d);
169 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
170 Point e = DrawPlaygroundPoint(point_e);
171 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
172 Point f = DrawPlaygroundPoint(point_f);
173 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
174 Point g = DrawPlaygroundPoint(point_g);
175 flutter::DlPath path = flutter::DlPathBuilder{}
176 .MoveTo(a)
177 .LineTo(b)
178 .LineTo(c)
179 .LineTo(d)
180 .Close()
181 .MoveTo(e)
182 .LineTo(f)
183 .LineTo(g)
184 .Close()
185 .TakePath();
186
187 Entity entity;
188 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
189 auto contents = std::make_unique<SolidColorContents>();
190 std::unique_ptr<Geometry> geom =
191 Geometry::MakeStrokePath(path, {.width = 20.0});
192 contents->SetGeometry(geom.get());
193 contents->SetColor(Color::Red());
194 entity.SetContents(std::move(contents));
195
196 return entity.Render(context, pass);
197 };
198 ASSERT_TRUE(OpenPlaygroundHere(callback));
199 }

References impeller::saturated::b, c, impeller::DrawPlaygroundPoint(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Color::White().

## ◆ TEST_P() [506/603]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1722 of file entity_unittests.cc.

1722 {
1723 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1724 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1725 GTEST_SKIP()
1726 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1727 }
1728
1729 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1730 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1731 YUVColorSpace::kBT601LimitedRange};
1732 for (int i = 0; i < 2; i++) {
1733 auto yuv_color_space = yuv_color_space_array[i];
1734 auto textures =
1735 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1736 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1737 textures[0], textures[1], yuv_color_space);
1738 Entity filter_entity;
1739 filter_entity.SetContents(filter_contents);
1740 auto snapshot =
1741 filter_contents->RenderToSnapshot(context, filter_entity, {});
1742
1743 Entity entity;
1744 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1745 contents->SetTexture(snapshot->texture);
1746 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1747 entity.SetContents(contents);
1748 entity.SetTransform(
1749 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1750 entity.Render(context, pass);
1751 }
1752 return true;
1753 };
1754 ASSERT_TRUE(OpenPlaygroundHere(callback));
1755 }
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1661
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:54

References CreateTestYUVTextures(), impeller::kBT601FullRange, impeller::kBT601LimitedRange, impeller::kOpenGLES, impeller::TRect< Scalar >::MakeLTRB(), impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslation(), impeller::FilterContents::MakeYUVToRGBFilter(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [507/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 344 of file gaussian_blur_filter_contents_unittests.cc.

344 {
345 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
346 auto filter_input = FilterInput::Make(texture);
347 Entity entity;
348 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
349 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
350 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
351 EXPECT_TRUE(uvs_bounds.has_value());
352 if (uvs_bounds.has_value()) {
353 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
354 }
355 }
uvs
Quad uvs
Definition: gaussian_blur_filter_contents.cc:298

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and uvs.

## ◆ TEST_P() [508/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 191 of file gaussian_blur_filter_contents_unittests.cc.

191 {
192 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
193 fml::StatusOr<Scalar> sigma_radius_1 =
194 CalculateSigmaForBlurRadius(1.0, effect_transform);
195 ASSERT_TRUE(sigma_radius_1.ok());
196 GaussianBlurFilterContents contents(
197 /*sigma_x=*/sigma_radius_1.value(),
198 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
199 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
200 /*mask_geometry=*/nullptr);
201 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
202 FilterInput::Vector inputs = {FilterInput::Make(texture)};
203 Entity entity;
204 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
205 std::optional<Rect> coverage =
206 contents.GetFilterCoverage(inputs, entity, effect_transform);
207 EXPECT_TRUE(coverage.has_value());
208 if (coverage.has_value()) {
209 EXPECT_RECT_NEAR(coverage.value(),
210 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
211 }
212 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [509/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 169 of file gaussian_blur_filter_contents_unittests.cc.

169 {
170 fml::StatusOr<Scalar> sigma_radius_1 =
171 CalculateSigmaForBlurRadius(1.0, Matrix());
172 ASSERT_TRUE(sigma_radius_1.ok());
173 GaussianBlurFilterContents contents(
174 /*sigma_X=*/sigma_radius_1.value(),
175 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
176 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
177 /*mask_geometry=*/nullptr);
178 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
179 FilterInput::Vector inputs = {FilterInput::Make(texture)};
180 Entity entity;
181 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
182 std::optional<Rect> coverage =
183 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
184
185 EXPECT_TRUE(coverage.has_value());
186 if (coverage.has_value()) {
187 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
188 }
189 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [510/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 245 of file gaussian_blur_filter_contents_unittests.cc.

245 {
246 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
247 fml::StatusOr<Scalar> sigma_radius_1 =
248 CalculateSigmaForBlurRadius(1.0, Matrix());
249 ASSERT_TRUE(sigma_radius_1.ok());
250 auto contents = std::make_unique<GaussianBlurFilterContents>(
251 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
252 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
253 /*mask_geometry=*/nullptr);
254 contents->SetInputs({FilterInput::Make(texture)});
255 std::shared_ptr<ContentContext> renderer = GetContentContext();
256
257 Entity entity;
258 std::optional<Entity> result =
259 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
260 EXPECT_TRUE(result.has_value());
261 if (result.has_value()) {
262 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
263 std::optional<Rect> result_coverage = result.value().GetCoverage();
264 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
265 EXPECT_TRUE(result_coverage.has_value());
266 EXPECT_TRUE(contents_coverage.has_value());
267 if (result_coverage.has_value() && contents_coverage.has_value()) {
268 EXPECT_TRUE(RectNear(contents_coverage.value(),
269 Rect::MakeLTRB(-1, -1, 101, 101)));
270 EXPECT_TRUE(
271 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
272 }
273 }
274 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), and RectNear().

## ◆ TEST_P() [511/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 310 of file gaussian_blur_filter_contents_unittests.cc.

311 {
312 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
313 fml::StatusOr<Scalar> sigma_radius_1 =
314 CalculateSigmaForBlurRadius(1.0, Matrix());
315 auto contents = std::make_unique<GaussianBlurFilterContents>(
316 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
317 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
318 /*mask_geometry=*/nullptr);
319 contents->SetInputs({FilterInput::Make(texture)});
320 std::shared_ptr<ContentContext> renderer = GetContentContext();
321
322 Entity entity;
323 // Rotate around the top left corner, then push it over to (100, 100).
324 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
325 Matrix::MakeRotationZ(Degrees(90.0)));
326 std::optional<Entity> result =
327 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
328 EXPECT_TRUE(result.has_value());
329 if (result.has_value()) {
330 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
331 std::optional<Rect> result_coverage = result.value().GetCoverage();
332 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
333 EXPECT_TRUE(result_coverage.has_value());
334 EXPECT_TRUE(contents_coverage.has_value());
335 if (result_coverage.has_value() && contents_coverage.has_value()) {
336 EXPECT_TRUE(RectNear(contents_coverage.value(),
337 Rect::MakeLTRB(99, 99, 401, 501)));
338 EXPECT_TRUE(
339 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
340 }
341 }
342 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [512/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 276 of file gaussian_blur_filter_contents_unittests.cc.

277 {
278 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
279 fml::StatusOr<Scalar> sigma_radius_1 =
280 CalculateSigmaForBlurRadius(1.0, Matrix());
281 ASSERT_TRUE(sigma_radius_1.ok());
282 auto contents = std::make_unique<GaussianBlurFilterContents>(
283 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
284 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
285 /*mask_geometry=*/nullptr);
286 contents->SetInputs({FilterInput::Make(texture)});
287 std::shared_ptr<ContentContext> renderer = GetContentContext();
288
289 Entity entity;
290 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
291 std::optional<Entity> result =
292 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
293
294 EXPECT_TRUE(result.has_value());
295 if (result.has_value()) {
296 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
297 std::optional<Rect> result_coverage = result.value().GetCoverage();
298 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
299 EXPECT_TRUE(result_coverage.has_value());
300 EXPECT_TRUE(contents_coverage.has_value());
301 if (result_coverage.has_value() && contents_coverage.has_value()) {
302 EXPECT_TRUE(RectNear(contents_coverage.value(),
303 Rect::MakeLTRB(99, 199, 201, 301)));
304 EXPECT_TRUE(
305 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
306 }
307 }
308 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [513/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 357 of file gaussian_blur_filter_contents_unittests.cc.

357 {
358 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
359 auto texture_contents = std::make_shared<TextureContents>();
360 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
361 texture_contents->SetTexture(texture);
362 texture_contents->SetDestinationRect(Rect::MakeXYWH(
363 50, 40, texture->GetSize().width, texture->GetSize().height));
364
365 fml::StatusOr<Scalar> sigma_radius_1 =
366 CalculateSigmaForBlurRadius(1.0, Matrix());
367 auto contents = std::make_unique<GaussianBlurFilterContents>(
368 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
369 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
370 /*mask_geometry=*/nullptr);
371 contents->SetInputs({FilterInput::Make(texture_contents)});
372 std::shared_ptr<ContentContext> renderer = GetContentContext();
373
374 Entity entity;
375 std::optional<Entity> result =
376 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
377 EXPECT_TRUE(result.has_value());
378 if (result.has_value()) {
379 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
380 std::optional<Rect> result_coverage = result.value().GetCoverage();
381 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
382 EXPECT_TRUE(result_coverage.has_value());
383 EXPECT_TRUE(contents_coverage.has_value());
384 if (result_coverage.has_value() && contents_coverage.has_value()) {
385 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
386 EXPECT_TRUE(RectNear(result_coverage.value(),
387 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
388 }
389 }
390 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [514/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 392 of file gaussian_blur_filter_contents_unittests.cc.

393 {
394 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
395 auto texture_contents = std::make_shared<TextureContents>();
396 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
397 texture_contents->SetTexture(texture);
398 texture_contents->SetDestinationRect(Rect::MakeXYWH(
399 50, 40, texture->GetSize().width, texture->GetSize().height));
400
401 fml::StatusOr<Scalar> sigma_radius_1 =
402 CalculateSigmaForBlurRadius(1.0, Matrix());
403 auto contents = std::make_unique<GaussianBlurFilterContents>(
404 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
405 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
406 /*mask_geometry=*/nullptr);
407 contents->SetInputs({FilterInput::Make(texture_contents)});
408 std::shared_ptr<ContentContext> renderer = GetContentContext();
409
410 Entity entity;
411 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
412 std::optional<Entity> result =
413 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
414 EXPECT_TRUE(result.has_value());
415 if (result.has_value()) {
416 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
417 std::optional<Rect> result_coverage = result.value().GetCoverage();
418 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
419 EXPECT_TRUE(result_coverage.has_value());
420 EXPECT_TRUE(contents_coverage.has_value());
421 if (result_coverage.has_value() && contents_coverage.has_value()) {
422 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
423 // Scaling a blurred entity doesn't seem to scale the blur radius linearly
424 // when comparing results with rrect_blur. That's why this is not
425 // Rect::MakeXYWH(98.f, 78.f, 204.0f, 204.f).
426 EXPECT_TRUE(RectNear(contents_coverage.value(),
427 Rect::MakeXYWH(94.f, 74.f, 212.0f, 212.f)));
428 }
429 }
430 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [515/603]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithEffectTransform |
| ) |  |

Definition at line 432 of file gaussian_blur_filter_contents_unittests.cc.

432 {
433 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
434 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
435 auto texture_contents = std::make_shared<TextureContents>();
436 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
437 texture_contents->SetTexture(texture);
438 texture_contents->SetDestinationRect(Rect::MakeXYWH(
439 50, 40, texture->GetSize().width, texture->GetSize().height));
440
441 fml::StatusOr<Scalar> sigma_radius_1 =
442 CalculateSigmaForBlurRadius(1.0, effect_transform);
443 ASSERT_TRUE(sigma_radius_1.ok());
444 auto contents = std::make_unique<GaussianBlurFilterContents>(
445 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
446 /*bounds=*/std::nullopt, FilterContents::BlurStyle::kNormal,
447 /*mask_geometry=*/nullptr);
448 contents->SetInputs({FilterInput::Make(texture_contents)});
449 contents->SetEffectTransform(effect_transform);
450 std::shared_ptr<ContentContext> renderer = GetContentContext();
451
452 Entity entity;
453 std::optional<Entity> result =
454 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
455 EXPECT_TRUE(result.has_value());
456 if (result.has_value()) {
457 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
458 std::optional<Rect> result_coverage = result.value().GetCoverage();
459 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
460 EXPECT_TRUE(result_coverage.has_value());
461 EXPECT_TRUE(contents_coverage.has_value());
462 if (result_coverage.has_value() && contents_coverage.has_value()) {
463 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
464 EXPECT_TRUE(RectNear(contents_coverage.value(),
465 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
466 }
467 }
468 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSrcOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [516/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | CanEmplace |
| ) |  |

Definition at line 36 of file host_buffer_unittests.cc.

36 {
37 struct Length2 {
38 uint8_t pad[2];
39 };
40 static_assert(sizeof(Length2) == 2u);
41
42 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
43 GetContext()->GetIdleWaiter(), 256);
44
45 for (size_t i = 0; i < 12500; i++) {
46 auto view = buffer->Emplace(Length2{});
47 ASSERT_TRUE(view);
48 ASSERT_EQ(view.GetRange(), Range(i * sizeof(Length2), 2u));
49 }
50 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [517/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | CanEmplaceWithAlignment |
| ) |  |

Definition at line 52 of file host_buffer_unittests.cc.

52 {
53 struct Length2 {
54 uint8_t pad[2];
55 };
56 static_assert(sizeof(Length2) == 2);
57 struct alignas(16) Align16 {
58 uint8_t pad[2];
59 };
60 static_assert(alignof(Align16) == 16);
61 static_assert(sizeof(Align16) == 16);
62
63 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
64 GetContext()->GetIdleWaiter(), 256);
65 ASSERT_TRUE(buffer);
66
67 {
68 auto view = buffer->Emplace(Length2{});
69 ASSERT_TRUE(view);
70 ASSERT_EQ(view.GetRange(), Range(0u, 2u));
71 }
72
73 {
74 auto view = buffer->Emplace(Align16{});
75 ASSERT_TRUE(view);
76 ASSERT_EQ(view.GetRange().offset, 16u);
77 ASSERT_EQ(view.GetRange().length, 16u);
78 }
79 {
80 auto view = buffer->Emplace(Length2{});
81 ASSERT_TRUE(view);
82 ASSERT_EQ(view.GetRange(), Range(32u, 2u));
83 }
84
85 {
86 auto view = buffer->Emplace(Align16{});
87 ASSERT_TRUE(view);
88 ASSERT_EQ(view.GetRange().offset, 48u);
89 ASSERT_EQ(view.GetRange().length, 16u);
90 }
91 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [518/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithFailingAllocationDoesntCrash |
| ) |  |

Definition at line 222 of file host_buffer_unittests.cc.

222 {
223 ScopedValidationDisable disable;
224 std::shared_ptr<FailingAllocator> allocator =
225 std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
226 auto buffer =
227 HostBuffer::Create(allocator, GetContext()->GetIdleWaiter(), 256);
228
229 auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
230
231 EXPECT_EQ(view.GetBuffer(), nullptr);
232 EXPECT_EQ(view.GetRange().offset, 0u);
233 EXPECT_EQ(view.GetRange().length, 0u);
234 }
impeller::testing::kMagicFailingAllocation
static constexpr const size_t kMagicFailingAllocation
Definition: host_buffer_unittests.cc:191

References impeller::HostBuffer::Create(), and kMagicFailingAllocation.

## ◆ TEST_P() [519/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithProcIsAligned |
| ) |  |

Definition at line 180 of file host_buffer_unittests.cc.

180 {
181 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
182 GetContext()->GetIdleWaiter(), 256);
183
184 BufferView view = buffer->Emplace(std::array<char, 21>());
185 EXPECT_EQ(view.GetRange(), Range(0, 21));
186
187 view = buffer->Emplace(64, 16, [](uint8_t*) {});
188 EXPECT_EQ(view.GetRange(), Range(32, 64));
189 }

References impeller::HostBuffer::Create(), and impeller::BufferView::GetRange().

## ◆ TEST_P() [520/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBuffer |
| ) |  |

Definition at line 135 of file host_buffer_unittests.cc.

135 {
136 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
137 GetContext()->GetIdleWaiter(), 256);
138
139 // Emplace an amount larger than the block size, to verify that the host
140 // buffer does not create a buffer.
141 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
142
143 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
144 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
145 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
146 }

References buffer_view, and impeller::HostBuffer::Create().

## ◆ TEST_P() [521/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback |
| ) |  |

Definition at line 121 of file host_buffer_unittests.cc.

122 {
123 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
124 GetContext()->GetIdleWaiter(), 256);
125
126 // Emplace an amount larger than the block size, to verify that the host
127 // buffer does not create a buffer.
128 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
129
130 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
131 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
132 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
133 }

References buffer_view, impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [522/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | HostBufferInitialState |
| ) |  |

Definition at line 93 of file host_buffer_unittests.cc.

93 {
94 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
95 GetContext()->GetIdleWaiter(), 256);
96
97 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
98 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
99 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
100 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [523/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | IdleWaiter |
| ) |  |

Definition at line 27 of file host_buffer_unittests.cc.

27 {
28 auto mock_idle_waiter = std::make_shared<MockIdleWaiter>();
29 {
30 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
31 mock_idle_waiter, 256);
32 EXPECT_CALL(*mock_idle_waiter, WaitIdle());
33 }
34 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [524/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | ResetIncrementsFrameCounter |
| ) |  |

Definition at line 102 of file host_buffer_unittests.cc.

102 {
103 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
104 GetContext()->GetIdleWaiter(), 256);
105
106 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
107
108 buffer->Reset();
109 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
110
111 buffer->Reset();
112 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
113
114 buffer->Reset();
115 EXPECT_EQ(buffer->GetStateForTest().current_frame, 3u);
116
117 buffer->Reset();
118 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
119 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [525/603]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | UnusedBuffersAreDiscardedWhenResetting |
| ) |  |

Definition at line 148 of file host_buffer_unittests.cc.

148 {
149 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
150 GetContext()->GetIdleWaiter(), 256);
151
152 // Emplace two large allocations to force the allocation of a second buffer.
153 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
154 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
155
156 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
157 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
158 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
159
160 // Reset until we get back to this frame.
161 for (auto i = 0; i < 4; i++) {
162 buffer->Reset();
163 }
164
165 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
166 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
167 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
168
169 // Now when we reset, the buffer should get dropped.
170 // Reset until we get back to this frame.
171 for (auto i = 0; i < 4; i++) {
172 buffer->Reset();
173 }
174
175 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
176 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
177 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
178 }

References impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [526/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassScale |
| ) |  |

Definition at line 175 of file matrix_filter_contents_unittests.cc.

176 {
177 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
178 MatrixFilterContents contents;
179 contents.SetInputs({FilterInput::Make(texture)});
180 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
181 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
182 contents.SetRenderingMode(
183 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
184
185 Entity entity;
186 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
187
188 std::shared_ptr<ContentContext> renderer = GetContentContext();
189 std::optional<Entity> result =
190 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
191 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
192 Rect::MakeXYWH(100, 200, 300, 300));
193 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [527/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassTranslate |
| ) |  |

Definition at line 138 of file matrix_filter_contents_unittests.cc.

139 {
140 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
141 MatrixFilterContents contents;
142 contents.SetInputs({FilterInput::Make(texture)});
143 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
144 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
145 contents.SetRenderingMode(
146 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
147
148 Entity entity;
149 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
150
151 std::shared_ptr<ContentContext> renderer = GetContentContext();
152 std::optional<Entity> result =
153 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
154 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
155 Rect::MakeXYWH(200, 400, 100, 100));
156 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [528/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageIdentity |
| ) |  |

Definition at line 106 of file matrix_filter_contents_unittests.cc.

106 {
107 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
108 MatrixFilterContents contents;
109 contents.SetInputs({FilterInput::Make(texture)});
110
111 Entity entity;
112 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
113
114 std::shared_ptr<ContentContext> renderer = GetContentContext();
115 std::optional<Entity> result =
116 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
117 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
118 Rect::MakeXYWH(100, 200, 100, 100));
119 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetInputs(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [529/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageScale |
| ) |  |

Definition at line 158 of file matrix_filter_contents_unittests.cc.

158 {
159 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
160 MatrixFilterContents contents;
161 contents.SetInputs({FilterInput::Make(texture)});
162 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
163 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
164
165 Entity entity;
166 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
167
168 std::shared_ptr<ContentContext> renderer = GetContentContext();
169 std::optional<Entity> result =
170 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
171 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
172 Rect::MakeXYWH(100, 200, 300, 300));
173 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [530/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageSubpassScale |
| ) |  |

Definition at line 195 of file matrix_filter_contents_unittests.cc.

195 {
196 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
197 MatrixFilterContents contents;
198 contents.SetInputs({FilterInput::Make(texture)});
199 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
200 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
201 contents.SetRenderingMode(
202 Entity::RenderingMode::kSubpassPrependSnapshotTransform);
203
204 Entity entity;
205 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
206
207 std::shared_ptr<ContentContext> renderer = GetContentContext();
208 std::optional<Entity> result =
209 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
210 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
211 Rect::MakeXYWH(300, 600, 300, 300));
212 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [531/603]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 121 of file matrix_filter_contents_unittests.cc.

121 {
122 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
123 MatrixFilterContents contents;
124 contents.SetInputs({FilterInput::Make(texture)});
125 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
126 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
127
128 Entity entity;
129 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
130
131 std::shared_ptr<ContentContext> renderer = GetContentContext();
132 std::optional<Entity> result =
133 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
134 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
135 Rect::MakeXYWH(150, 300, 100, 100));
136 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [532/603]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | CanPersistAndRetrievePipelineCache |
| ) |  |

Definition at line 117 of file pipeline_cache_data_vk_unittests.cc.

117 {
118 fml::ScopedTemporaryDirectory temp_dir;
119 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
120 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
121 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
122
123 {
124 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
125 ASSERT_EQ(cache.result, vk::Result::eSuccess);
126 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
127 ASSERT_TRUE(PipelineCacheDataPersist(
128 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
129 }
130 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
131
132 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(),
133 caps.GetPhysicalDeviceProperties());
134 ASSERT_NE(mapping, nullptr);
135 // Assert that the utility has stripped away the cache header giving us clean
136 // pipeline cache bootstrap information.
137 vk::PipelineCacheHeaderVersionOne vk_cache_header;
138 ASSERT_GE(mapping->GetSize(), sizeof(vk_cache_header));
139 std::memcpy(&vk_cache_header, mapping->GetMapping(), sizeof(vk_cache_header));
140 ASSERT_EQ(vk_cache_header.headerVersion,
141 vk::PipelineCacheHeaderVersion::eOne);
142 }
impeller::PipelineCacheDataRetrieve
std::unique_ptr< fml::Mapping > PipelineCacheDataRetrieve(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props)
Retrieve the previously persisted pipeline cache data. This function provides integrity checks the Vu...
Definition: pipeline_cache_data_vk.cc:65

References impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [533/603]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | IntegrityChecksArePerformedOnPersistedData |
| ) |  |

Definition at line 144 of file pipeline_cache_data_vk_unittests.cc.

145 {
146 fml::ScopedTemporaryDirectory temp_dir;
147 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
148 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
149 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
150
151 {
152 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
153 ASSERT_EQ(cache.result, vk::Result::eSuccess);
154 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
155 ASSERT_TRUE(PipelineCacheDataPersist(
156 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
157 }
158 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
159 auto incompatible_caps = caps.GetPhysicalDeviceProperties();
160 // Simulate a driver version bump.
161 incompatible_caps.driverVersion =
162 caps.GetPhysicalDeviceProperties().driverVersion + 1u;
163 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(), incompatible_caps);
164 ASSERT_EQ(mapping, nullptr);
165 }

References impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [534/603]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateRenderPassAndSubmit |
| ) |  |

Definition at line 300 of file renderer_dart_unittests.cc.

300 {
301 ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
302 }

## ◆ TEST_P() [535/603]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateShaderLibrary |
| ) |  |

Definition at line 292 of file renderer_dart_unittests.cc.

292 {
293 ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
294 }

## ◆ TEST_P() [536/603]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

These test entries correspond to Dart functions located in `flutter/impeller/fixtures/dart_tests.dart`

Definition at line 288 of file renderer_dart_unittests.cc.

288 {
289 ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
290 }

## ◆ TEST_P() [537/603]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanReflectUniformStructs |
| ) |  |

Definition at line 296 of file renderer_dart_unittests.cc.

296 {
297 ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
298 }

## ◆ TEST_P() [538/603]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 273 of file renderer_dart_unittests.cc.

273 {
274 SinglePassCallback callback = [&](RenderPass& pass) {
275 ImGui::Begin("Dart test", nullptr);
276 ImGui::Text(
277 "This test executes Dart code during the playground frame callback.");
278 ImGui::End();
279
280 return RunDartFunction("sayHi");
281 };
282 ASSERT_TRUE(OpenPlaygroundHere(callback));
283 }

## ◆ TEST_P() [539/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 1023 of file renderer_unittests.cc.

1023 {
1024 using VS = ArrayVertexShader;
1025 using FS = ArrayFragmentShader;
1026
1027 auto context = GetContext();
1028 auto pipeline_descriptor =
1029 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1030 ASSERT_TRUE(pipeline_descriptor.has_value());
1031 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1032 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1033 auto pipeline =
1034 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1035 ASSERT_TRUE(pipeline && pipeline->IsValid());
1036
1037 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1038 SinglePassCallback callback = [&](RenderPass& pass) {
1039 auto size = pass.GetRenderTargetSize();
1040
1041 pass.SetPipeline(pipeline);
1042 pass.SetCommandLabel("Google Dots");
1043 VertexBufferBuilder<VS::PerVertexData> builder;
1044 builder.AddVertices({{Point()},
1045 {Point(0, size.height)},
1046 {Point(size.width, 0)},
1047 {Point(size.width, 0)},
1048 {Point(0, size.height)},
1049 {Point(size.width, size.height)}});
1050 pass.SetVertexBuffer(
1051 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1052
1053 VS::FrameInfo frame_info;
1054 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1055 frame_info.mvp =
1056 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1057 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1058
1059 auto time = GetSecondsElapsed();
1060 auto y_pos = [&time](float x) {
1061 return 400 + 10 * std::cos(time * 5 + x / 6);
1062 };
1063
1064 FS::FragInfo fs_uniform = {
1065 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1066 Point(530, y_pos(2)), Point(580, y_pos(3))},
1067 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1068 Color::MakeRGBA8(219, 68, 55, 255),
1069 Color::MakeRGBA8(244, 180, 0, 255),
1070 Color::MakeRGBA8(15, 157, 88, 255)},
1071 };
1072 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1073
1074 pass.Draw();
1075 data_host_buffer->Reset();
1076 return true;
1077 };
1078 OpenPlaygroundHere(callback);
1079 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Color::MakeRGBA8(), impeller::Matrix::MakeScale(), and x.

## ◆ TEST_P() [540/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BabysFirstTriangle |
| ) |  |

Definition at line 138 of file renderer_unittests.cc.

138 {
139 auto context = GetContext();
140 ASSERT_TRUE(context);
141
142 // Declare a shorthand for the shaders we are going to use.
143 using VS = BabyVertexShader;
144 using FS = BabyFragmentShader;
145
146 // Create a pipeline descriptor that uses the shaders together and default
147 // initializes the fixed function state.
148 //
149 // If the vertex shader outputs disagree with the fragment shader inputs, this
150 // will be a compile time error.
151 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
152 ASSERT_TRUE(desc.has_value());
153
154 // Modify the descriptor for our environment. This is specific to our test.
155 desc->SetSampleCount(SampleCount::kCount4);
156 desc->SetStencilAttachmentDescriptors(std::nullopt);
157
158 // Create a pipeline from our descriptor. This is expensive to do. So just do
159 // it once.
160 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
161
162 // Specify the vertex buffer information.
163 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
164 vertex_buffer_builder.AddVertices({
165 {{-0.5, -0.5}, Color::Red(), Color::Green()},
166 {{0.0, 0.5}, Color::Green(), Color::Blue()},
167 {{0.5, -0.5}, Color::Blue(), Color::Red()},
168 });
169
170 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
171 *context->GetResourceAllocator());
172
173 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
174 SinglePassCallback callback = [&](RenderPass& pass) {
175 pass.SetPipeline(pipeline);
176 pass.SetVertexBuffer(vertex_buffer);
177
178 FS::FragInfo frag_info;
179 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
180
181 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(frag_info));
182
183 return pass.Draw().ok();
184 };
185 OpenPlaygroundHere(callback);
186 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Color::Blue(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Color::Red().

## ◆ TEST_P() [541/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BindingNullTexturesDoesNotCrash |
| ) |  |

Definition at line 1618 of file renderer_unittests.cc.

1618 {
1619 using FS = BoxFadeFragmentShader;
1620
1621 auto context = GetContext();
1622 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1623 auto command_buffer = context->CreateCommandBuffer();
1624
1625 RenderTargetAllocator allocator(context->GetResourceAllocator());
1626 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1627
1628 auto pass = command_buffer->CreateRenderPass(target);
1629 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1630 }

References impeller::RenderTargetAllocator::CreateOffscreen().

## ◆ TEST_P() [542/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebuffer |
| ) |  |

Definition at line 17 of file render_pass_cache_unittests.cc.

17 {
18 if (GetBackend() != PlaygroundBackend::kVulkan) {
19 GTEST_SKIP() << "Test only applies to Vulkan";
20 }
21
22 auto allocator = std::make_shared<RenderTargetAllocator>(
23 GetContext()->GetResourceAllocator());
24
25 RenderTarget render_target =
26 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
27 std::shared_ptr<Texture> resolve_texture =
28 render_target.GetColorAttachment(0).resolve_texture;
29 TextureVK& texture_vk = TextureVK::Cast(*resolve_texture);
30
31 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
32 nullptr);
33 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
34 nullptr);
35
36 auto buffer = GetContext()->CreateCommandBuffer();
37 auto render_pass = buffer->CreateRenderPass(render_target);
38
39 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
40 nullptr);
41 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
42 nullptr);
43
44 render_pass->EncodeCommands();
45 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer}).ok());
46
47 // Can be reused without error.
48 auto buffer_2 = GetContext()->CreateCommandBuffer();
49 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
50
51 EXPECT_TRUE(render_pass_2->EncodeCommands());
52 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
53 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), impeller::FramebufferAndRenderPass::framebuffer, impeller::TextureVK::GetCachedFrameData(), impeller::RenderTarget::GetColorAttachment(), impeller::kCount4, impeller::kVulkan, impeller::FramebufferAndRenderPass::render_pass, and impeller::Attachment::resolve_texture.

## ◆ TEST_P() [543/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebufferMixed |
| ) |  |

Definition at line 93 of file render_pass_cache_unittests.cc.

93 {
94 if (GetBackend() != PlaygroundBackend::kVulkan) {
95 GTEST_SKIP() << "Test only applies to Vulkan";
96 }
97
98 auto allocator = std::make_shared<RenderTargetAllocator>(
99 GetContext()->GetResourceAllocator());
100
101 RenderTarget render_target =
102 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
103 std::shared_ptr<Texture> resolve_texture =
104 render_target.GetColorAttachment(0).resolve_texture;
105 TextureVK& texture_vk = TextureVK::Cast(*resolve_texture);
106
107 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
108 nullptr);
109 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
110 nullptr);
111
112 auto buffer = GetContext()->CreateCommandBuffer();
113 auto render_pass = buffer->CreateRenderPass(render_target);
114
115 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).framebuffer,
116 nullptr);
117 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount4).render_pass,
118 nullptr);
119
120 render_pass->EncodeCommands();
121 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer}).ok());
122
123 // Can be reused without error.
124 auto buffer_2 = GetContext()->CreateCommandBuffer();
125 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
126
127 EXPECT_TRUE(render_pass_2->EncodeCommands());
128 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
129
130 // Now switch to single sample count and demonstrate no validation errors.
131 {
132 RenderTarget other_target;
133 ColorAttachment color0;
134 color0.load_action = LoadAction::kLoad;
135 color0.store_action = StoreAction::kStore;
136 color0.texture = resolve_texture;
137 other_target.SetColorAttachment(color0, 0);
138 other_target.SetDepthAttachment(std::nullopt);
139 other_target.SetStencilAttachment(std::nullopt);
140
141 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount1).framebuffer,
142 nullptr);
143 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount1).render_pass,
144 nullptr);
145
146 auto buffer_3 = GetContext()->CreateCommandBuffer();
147 auto render_pass_3 = buffer_3->CreateRenderPass(other_target);
148
149 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).framebuffer,
150 nullptr);
151 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).render_pass,
152 nullptr);
153
154 EXPECT_TRUE(render_pass_3->EncodeCommands());
155 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_3}).ok());
156 }
157 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), impeller::FramebufferAndRenderPass::framebuffer, impeller::TextureVK::GetCachedFrameData(), impeller::RenderTarget::GetColorAttachment(), impeller::kCount1, impeller::kCount4, impeller::kLoad, impeller::kStore, impeller::kVulkan, impeller::Attachment::load_action, impeller::FramebufferAndRenderPass::render_pass, impeller::Attachment::resolve_texture, impeller::RenderTarget::SetColorAttachment(), impeller::RenderTarget::SetDepthAttachment(), impeller::RenderTarget::SetStencilAttachment(), impeller::Attachment::store_action, and impeller::Attachment::texture.

## ◆ TEST_P() [544/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebufferNonMSAA |
| ) |  |

Definition at line 55 of file render_pass_cache_unittests.cc.

55 {
56 if (GetBackend() != PlaygroundBackend::kVulkan) {
57 GTEST_SKIP() << "Test only applies to Vulkan";
58 }
59
60 auto allocator = std::make_shared<RenderTargetAllocator>(
61 GetContext()->GetResourceAllocator());
62
63 RenderTarget render_target =
64 allocator->CreateOffscreen(*GetContext(), {100, 100}, 1);
65 std::shared_ptr<Texture> color_texture =
66 render_target.GetColorAttachment(0).texture;
67 TextureVK& texture_vk = TextureVK::Cast(*color_texture);
68
69 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount1).framebuffer,
70 nullptr);
71 EXPECT_EQ(texture_vk.GetCachedFrameData(SampleCount::kCount1).render_pass,
72 nullptr);
73
74 auto buffer = GetContext()->CreateCommandBuffer();
75 auto render_pass = buffer->CreateRenderPass(render_target);
76
77 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).framebuffer,
78 nullptr);
79 EXPECT_NE(texture_vk.GetCachedFrameData(SampleCount::kCount1).render_pass,
80 nullptr);
81
82 render_pass->EncodeCommands();
83 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer}).ok());
84
85 // Can be reused without error.
86 auto buffer_2 = GetContext()->CreateCommandBuffer();
87 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
88
89 EXPECT_TRUE(render_pass_2->EncodeCommands());
90 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
91 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), impeller::FramebufferAndRenderPass::framebuffer, impeller::TextureVK::GetCachedFrameData(), impeller::RenderTarget::GetColorAttachment(), impeller::kCount1, impeller::kVulkan, impeller::FramebufferAndRenderPass::render_pass, and impeller::Attachment::texture.

## ◆ TEST_P() [545/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 643 of file renderer_unittests.cc.

643 {
644 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
645 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
646 }
647 auto context = GetContext();
648 ASSERT_TRUE(context);
649
650 using VS = MipmapsVertexShader;
651 using FS = MipmapsFragmentShader;
652 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
653 ASSERT_TRUE(desc.has_value());
654 desc->SetSampleCount(SampleCount::kCount4);
655 desc->SetStencilAttachmentDescriptors(std::nullopt);
656 auto mipmaps_pipeline =
657 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
658 ASSERT_TRUE(mipmaps_pipeline);
659
660 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
661 auto boston = CreateTextureForFixture("boston.jpg");
662 ASSERT_TRUE(bridge && boston);
663 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
664 ASSERT_TRUE(sampler);
665
666 TextureDescriptor texture_desc;
667 texture_desc.storage_mode = StorageMode::kHostVisible;
668 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
669 texture_desc.size = bridge->GetTextureDescriptor().size;
670 texture_desc.mip_count = 1u;
671 texture_desc.usage = TextureUsage::kRenderTarget |
672 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
673 DeviceBufferDescriptor device_buffer_desc;
674 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
675 device_buffer_desc.size =
676 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
677 auto device_buffer =
678 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
679
680 // Vertex buffer.
681 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
682 vertex_builder.SetLabel("Box");
683 auto size = Point(boston->GetSize());
684 vertex_builder.AddVertices({
685 {{0, 0}, {0.0, 0.0}}, // 1
686 {{size.x, 0}, {1.0, 0.0}}, // 2
687 {{size.x, size.y}, {1.0, 1.0}}, // 3
688 {{0, 0}, {0.0, 0.0}}, // 1
689 {{size.x, size.y}, {1.0, 1.0}}, // 3
690 {{0, size.y}, {0.0, 1.0}}, // 4
691 });
692 auto vertex_buffer =
693 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
694 ASSERT_TRUE(vertex_buffer);
695
696 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
697 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
698 {
699 auto buffer = context->CreateCommandBuffer();
700 if (!buffer) {
701 return false;
702 }
703 buffer->SetLabel("Playground Command Buffer");
704 auto pass = buffer->CreateBlitPass();
705 if (!pass) {
706 return false;
707 }
708 pass->SetLabel("Playground Blit Pass");
709
710 // Blit `bridge` to the top left corner of the texture.
711 pass->AddCopy(bridge, device_buffer);
712 pass->EncodeCommands();
713
714 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
715 return false;
716 }
717 }
718
719 {
720 auto buffer = context->CreateCommandBuffer();
721 if (!buffer) {
722 return false;
723 }
724 buffer->SetLabel("Playground Command Buffer");
725
726 auto pass = buffer->CreateRenderPass(render_target);
727 if (!pass) {
728 return false;
729 }
730 pass->SetLabel("Playground Render Pass");
731 {
732 pass->SetCommandLabel("Image");
733 pass->SetPipeline(mipmaps_pipeline);
734 pass->SetVertexBuffer(vertex_buffer);
735
736 VS::FrameInfo frame_info;
737 EXPECT_EQ(pass->GetOrthographicTransform(),
738 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
739 frame_info.mvp = pass->GetOrthographicTransform() *
740 Matrix::MakeScale(GetContentScale());
741 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
742
743 FS::FragInfo frag_info;
744 frag_info.lod = 0;
745 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
746
747 raw_ptr<const Sampler> sampler =
748 context->GetSamplerLibrary()->GetSampler({});
749 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
750 auto texture =
751 context->GetResourceAllocator()->CreateTexture(texture_desc);
752 if (!texture->SetContents(device_buffer->OnGetContents(),
753 buffer_view.GetRange().length)) {
754 VALIDATION_LOG << "Could not upload texture to device memory";
755 return false;
756 }
757 FS::BindTex(*pass, texture, sampler);
758
759 pass->Draw().ok();
760 }
761 pass->EncodeCommands();
762 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
763 return false;
764 }
765 }
766 data_host_buffer->Reset();
767 return true;
768 };
769 OpenPlaygroundHere(callback);
770 }
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::DeviceBuffer::AsBufferView(), buffer_view, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::kShaderWrite, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, impeller::TextureDescriptor::storage_mode, impeller::TextureDescriptor::usage, and VALIDATION_LOG.

## ◆ TEST_P() [546/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 533 of file renderer_unittests.cc.

533 {
534 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
535 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
536 }
537 auto context = GetContext();
538 ASSERT_TRUE(context);
539
540 using VS = MipmapsVertexShader;
541 using FS = MipmapsFragmentShader;
542 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
543 ASSERT_TRUE(desc.has_value());
544 desc->SetSampleCount(SampleCount::kCount4);
545 desc->SetStencilAttachmentDescriptors(std::nullopt);
546 auto mipmaps_pipeline =
547 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
548 ASSERT_TRUE(mipmaps_pipeline);
549
550 TextureDescriptor texture_desc;
551 texture_desc.storage_mode = StorageMode::kHostVisible;
552 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
553 texture_desc.size = {800, 600};
554 texture_desc.mip_count = 1u;
555 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
556 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
557 ASSERT_TRUE(texture);
558
559 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
560 auto boston = CreateTextureForFixture("boston.jpg");
561 ASSERT_TRUE(bridge && boston);
562 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
563 ASSERT_TRUE(sampler);
564
565 // Vertex buffer.
566 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
567 vertex_builder.SetLabel("Box");
568 auto size = Point(boston->GetSize());
569 vertex_builder.AddVertices({
570 {{0, 0}, {0.0, 0.0}}, // 1
571 {{size.x, 0}, {1.0, 0.0}}, // 2
572 {{size.x, size.y}, {1.0, 1.0}}, // 3
573 {{0, 0}, {0.0, 0.0}}, // 1
574 {{size.x, size.y}, {1.0, 1.0}}, // 3
575 {{0, size.y}, {0.0, 1.0}}, // 4
576 });
577 auto vertex_buffer =
578 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
579 ASSERT_TRUE(vertex_buffer);
580
581 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
582 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
583 auto buffer = context->CreateCommandBuffer();
584 if (!buffer) {
585 return false;
586 }
587 buffer->SetLabel("Playground Command Buffer");
588
589 {
590 auto pass = buffer->CreateBlitPass();
591 if (!pass) {
592 return false;
593 }
594 pass->SetLabel("Playground Blit Pass");
595
596 // Blit `bridge` to the top left corner of the texture.
597 pass->AddCopy(bridge, texture);
598
599 if (!pass->EncodeCommands()) {
600 return false;
601 }
602 }
603
604 {
605 auto pass = buffer->CreateRenderPass(render_target);
606 if (!pass) {
607 return false;
608 }
609 pass->SetLabel("Playground Render Pass");
610 {
611 pass->SetCommandLabel("Image");
612 pass->SetPipeline(mipmaps_pipeline);
613 pass->SetVertexBuffer(vertex_buffer);
614
615 VS::FrameInfo frame_info;
616 EXPECT_EQ(pass->GetOrthographicTransform(),
617 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
618 frame_info.mvp = pass->GetOrthographicTransform() *
619 Matrix::MakeScale(GetContentScale());
620 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
621
622 FS::FragInfo frag_info;
623 frag_info.lod = 0;
624 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
625
626 auto sampler = context->GetSamplerLibrary()->GetSampler({});
627 FS::BindTex(*pass, texture, sampler);
628
629 pass->Draw();
630 }
631 pass->EncodeCommands();
632 }
633
634 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
635 return false;
636 }
637 data_host_buffer->Reset();
638 return true;
639 };
640 OpenPlaygroundHere(callback);
641 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [547/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 70 of file renderer_unittests.cc.

70 {
71 using VS = BoxFadeVertexShader;
72 using FS = BoxFadeFragmentShader;
73 auto context = GetContext();
74 ASSERT_TRUE(context);
75 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
76 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
77 ASSERT_TRUE(desc.has_value());
78 desc->SetSampleCount(SampleCount::kCount4);
79 desc->SetStencilAttachmentDescriptors(std::nullopt);
80
81 // Vertex buffer.
82 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
83 vertex_builder.SetLabel("Box");
84 vertex_builder.AddVertices({
85 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
86 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
87 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
88 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
89 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
90 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
91 });
92 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
93 auto boston = CreateTextureForFixture("boston.jpg");
94 ASSERT_TRUE(bridge && boston);
95 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
96 ASSERT_TRUE(sampler);
97
98 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
99 SinglePassCallback callback = [&](RenderPass& pass) {
100 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
101 static bool wireframe;
102 ImGui::Checkbox("Wireframe", &wireframe);
103 ImGui::End();
104
105 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
106 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
107
108 assert(pipeline && pipeline->IsValid());
109
110 pass.SetCommandLabel("Box");
111 pass.SetPipeline(pipeline);
112 pass.SetVertexBuffer(
113 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
114
115 VS::UniformBuffer uniforms;
116 EXPECT_EQ(pass.GetOrthographicTransform(),
117 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
118 uniforms.mvp =
119 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
120 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
121
122 FS::FrameInfo frame_info;
123 frame_info.current_time = GetSecondsElapsed();
124 frame_info.cursor_position = GetCursorPosition();
125 frame_info.window_size.x = GetWindowSize().width;
126 frame_info.window_size.y = GetWindowSize().height;
127
128 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
129 FS::BindContents1(pass, boston, sampler);
130 FS::BindContents2(pass, bridge, sampler);
131
132 data_host_buffer->Reset();
133 return pass.Draw().ok();
134 };
135 OpenPlaygroundHere(callback);
136 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::kFill, impeller::kLine, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [548/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 772 of file renderer_unittests.cc.

772 {
773 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
774 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
775 }
776 auto context = GetContext();
777 ASSERT_TRUE(context);
778
779 using VS = MipmapsVertexShader;
780 using FS = MipmapsFragmentShader;
781 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
782 ASSERT_TRUE(desc.has_value());
783 desc->SetSampleCount(SampleCount::kCount4);
784 desc->SetStencilAttachmentDescriptors(std::nullopt);
785 auto mipmaps_pipeline =
786 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
787 ASSERT_TRUE(mipmaps_pipeline);
788
789 auto boston = CreateTextureForFixture("boston.jpg", true);
790 ASSERT_TRUE(boston);
791
792 // Vertex buffer.
793 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
794 vertex_builder.SetLabel("Box");
795 auto size = Point(boston->GetSize());
796 vertex_builder.AddVertices({
797 {{0, 0}, {0.0, 0.0}}, // 1
798 {{size.x, 0}, {1.0, 0.0}}, // 2
799 {{size.x, size.y}, {1.0, 1.0}}, // 3
800 {{0, 0}, {0.0, 0.0}}, // 1
801 {{size.x, size.y}, {1.0, 1.0}}, // 3
802 {{0, size.y}, {0.0, 1.0}}, // 4
803 });
804 auto vertex_buffer =
805 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
806 ASSERT_TRUE(vertex_buffer);
807
808 bool first_frame = true;
809 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
810 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
811 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
812 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
813 MipFilter::kLinear};
814 const char* min_filter_names[] = {"Nearest", "Linear"};
815 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
816 MinMagFilter::kLinear};
817
818 // UI state.
819 static int selected_mip_filter = 1;
820 static int selected_min_filter = 0;
821 static float lod = 4.5;
822
823 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
824 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
825 sizeof(mip_filter_names) / sizeof(char*));
826 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
827 sizeof(min_filter_names) / sizeof(char*));
828 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
829 ImGui::End();
830
831 auto buffer = context->CreateCommandBuffer();
832 if (!buffer) {
833 return false;
834 }
835 buffer->SetLabel("Playground Command Buffer");
836
837 if (first_frame) {
838 auto pass = buffer->CreateBlitPass();
839 if (!pass) {
840 return false;
841 }
842 pass->SetLabel("Playground Blit Pass");
843
844 pass->GenerateMipmap(boston, "Boston Mipmap");
845
846 pass->EncodeCommands();
847 }
848
849 first_frame = false;
850
851 {
852 auto pass = buffer->CreateRenderPass(render_target);
853 if (!pass) {
854 return false;
855 }
856 pass->SetLabel("Playground Render Pass");
857 {
858 pass->SetCommandLabel("Image LOD");
859 pass->SetPipeline(mipmaps_pipeline);
860 pass->SetVertexBuffer(vertex_buffer);
861
862 VS::FrameInfo frame_info;
863 EXPECT_EQ(pass->GetOrthographicTransform(),
864 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
865 frame_info.mvp = pass->GetOrthographicTransform() *
866 Matrix::MakeScale(GetContentScale());
867 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
868
869 FS::FragInfo frag_info;
870 frag_info.lod = lod;
871 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
872
873 SamplerDescriptor sampler_desc;
874 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
875 sampler_desc.min_filter = min_filters[selected_min_filter];
876 raw_ptr<const Sampler> sampler =
877 context->GetSamplerLibrary()->GetSampler(sampler_desc);
878 FS::BindTex(*pass, boston, sampler);
879
880 pass->Draw();
881 }
882 pass->EncodeCommands();
883 }
884
885 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
886 return false;
887 }
888 data_host_buffer->Reset();
889 return true;
890 };
891 OpenPlaygroundHere(callback);
892 }
impeller::MipFilter
MipFilter
Options for selecting and filtering between mipmap levels.
Definition: formats.h:428
impeller::MinMagFilter
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
Definition: formats.h:418

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kBase, impeller::kCount4, impeller::kLinear, impeller::kNearest, impeller::kOpenGLES, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::SamplerDescriptor::min_filter, impeller::SamplerDescriptor::mip_filter, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [549/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1368 of file renderer_unittests.cc.

1368 {
1369 auto context = GetContext();
1370 auto cmd_buffer = context->CreateCommandBuffer();
1371 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1372 GetContext()->GetResourceAllocator());
1373
1374 auto render_target = render_target_cache->CreateOffscreen(
1375 *context, {100, 100}, /*mip_count=*/1);
1376 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1377
1378 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1379 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1380 render_target.GetRenderTargetPixelFormat());
1381 EXPECT_EQ(render_pass->HasStencilAttachment(),
1382 render_target.GetStencilAttachment().has_value());
1383 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1384 render_target.GetRenderTargetSize());
1385 render_pass->EncodeCommands();
1386 }

## ◆ TEST_P() [550/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 473 of file renderer_unittests.cc.

473 {
474 if (GetParam() == PlaygroundBackend::kOpenGLES) {
475 GTEST_SKIP() << "Instancing is not supported on OpenGL.";
476 }
477 using VS = InstancedDrawVertexShader;
478 using FS = InstancedDrawFragmentShader;
479
480 VertexBufferBuilder<VS::PerVertexData> builder;
481 builder.AddVertices({
482 VS::PerVertexData{Point{10, 10}},
483 VS::PerVertexData{Point{10, 110}},
484 VS::PerVertexData{Point{110, 10}},
485 VS::PerVertexData{Point{10, 110}},
486 VS::PerVertexData{Point{110, 10}},
487 VS::PerVertexData{Point{110, 110}},
488 });
489
490 ASSERT_NE(GetContext(), nullptr);
491 auto pipeline =
492 GetContext()
493 ->GetPipelineLibrary()
494 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
495 *GetContext())
496 ->SetSampleCount(SampleCount::kCount4)
497 .SetStencilAttachmentDescriptors(std::nullopt))
498
499 .Get();
500 ASSERT_TRUE(pipeline && pipeline->IsValid());
501
502 static constexpr size_t kInstancesCount = 5u;
503 VS::InstanceInfo<kInstancesCount> instances;
504 for (size_t i = 0; i < kInstancesCount; i++) {
505 instances.colors[i] = Color::Random();
506 }
507
508 auto [data_host_buffer, indexes_host_buffer] =
509 createHostBuffers(GetContext());
510 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
511 pass.SetPipeline(pipeline);
512 pass.SetCommandLabel("InstancedDraw");
513
514 VS::FrameInfo frame_info;
515 EXPECT_EQ(pass.GetOrthographicTransform(),
516 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
517 frame_info.mvp =
518 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
519 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
520 VS::BindInstanceInfo(pass,
521 data_host_buffer->EmplaceStorageBuffer(instances));
522 pass.SetVertexBuffer(
523 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
524
525 pass.SetInstanceCount(kInstancesCount);
526 pass.Draw();
527
528 data_host_buffer->Reset();
529 return true;
530 }));
531 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::RenderPass::Draw(), impeller::RenderPass::GetOrthographicTransform(), impeller::RenderPass::GetRenderTargetSize(), impeller::kCount4, impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Color::Random(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetInstanceCount(), impeller::RenderPass::SetPipeline(), and impeller::RenderPass::SetVertexBuffer().

## ◆ TEST_P() [551/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 299 of file renderer_unittests.cc.

299 {
300 using VS = BoxFadeVertexShader;
301 using FS = BoxFadeFragmentShader;
302 auto context = GetContext();
303 ASSERT_TRUE(context);
304 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
305 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
306 ASSERT_TRUE(desc.has_value());
307 desc->SetSampleCount(SampleCount::kCount4);
308 desc->SetStencilAttachmentDescriptors(std::nullopt);
309 auto box_pipeline =
310 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
311 ASSERT_TRUE(box_pipeline);
312
313 // Vertex buffer.
314 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
315 vertex_builder.SetLabel("Box");
316 vertex_builder.AddVertices({
317 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
318 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
319 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
320 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
321 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
322 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
323 });
324 auto vertex_buffer =
325 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
326 ASSERT_TRUE(vertex_buffer);
327
328 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
329 auto boston = CreateTextureForFixture("boston.jpg");
330 ASSERT_TRUE(bridge && boston);
331 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
332 ASSERT_TRUE(sampler);
333
334 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
335 SinglePassCallback callback = [&](RenderPass& pass) {
336 for (size_t i = 0; i < 1; i++) {
337 for (size_t j = 0; j < 1; j++) {
338 pass.SetCommandLabel("Box");
339 pass.SetPipeline(box_pipeline);
340 pass.SetVertexBuffer(vertex_buffer);
341
342 FS::FrameInfo frame_info;
343 frame_info.current_time = GetSecondsElapsed();
344 frame_info.cursor_position = GetCursorPosition();
345 frame_info.window_size.x = GetWindowSize().width;
346 frame_info.window_size.y = GetWindowSize().height;
347
348 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
349 FS::BindContents1(pass, boston, sampler);
350 FS::BindContents2(pass, bridge, sampler);
351
352 VS::UniformBuffer uniforms;
353 EXPECT_EQ(pass.GetOrthographicTransform(),
354 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
355 uniforms.mvp = pass.GetOrthographicTransform() *
356 Matrix::MakeScale(GetContentScale()) *
357 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
358 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
359 if (!pass.Draw().ok()) {
360 return false;
361 }
362 }
363 }
364
365 data_host_buffer->Reset();
366 return true;
367 };
368 OpenPlaygroundHere(callback);
369 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [552/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 188 of file renderer_unittests.cc.

188 {
189 using VS = ColorsVertexShader;
190 using FS = ColorsFragmentShader;
191 auto context = GetContext();
192 ASSERT_TRUE(context);
193 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
194 ASSERT_TRUE(desc.has_value());
195 desc->SetCullMode(CullMode::kBackFace);
196 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
197 desc->SetSampleCount(SampleCount::kCount4);
198 desc->ClearStencilAttachments();
199
200 // Setup the vertex layout to take two bindings. The first for positions and
201 // the second for colors.
202 auto vertex_desc = std::make_shared<VertexDescriptor>();
203 ShaderStageIOSlot position_slot = VS::kInputPosition;
204 ShaderStageIOSlot color_slot = VS::kInputColor;
205 position_slot.binding = 0;
206 position_slot.offset = 0;
207 color_slot.binding = 1;
208 color_slot.offset = 0;
209 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
210 const std::vector<ShaderStageBufferLayout> layouts = {
211 ShaderStageBufferLayout{.stride = 12u, .binding = 0},
212 ShaderStageBufferLayout{.stride = 16u, .binding = 1}};
213 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
214 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
215 vertex_desc->SetStageInputs(io_slots, layouts);
216 desc->SetVertexDescriptor(std::move(vertex_desc));
217 auto pipeline =
218 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
219 ASSERT_TRUE(pipeline);
220
221 struct Cube {
222 Vector3 positions[8] = {
223 // -Z
224 {-1, -1, -1},
225 {1, -1, -1},
226 {1, 1, -1},
227 {-1, 1, -1},
228 // +Z
229 {-1, -1, 1},
230 {1, -1, 1},
231 {1, 1, 1},
232 {-1, 1, 1},
233 };
234 Color colors[8] = {
235 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
236 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
237 };
238 uint16_t indices[36] = {
239 1, 5, 2, 2, 5, 6, // +X
240 4, 0, 7, 7, 0, 3, // -X
241 4, 5, 0, 0, 5, 1, // +Y
242 3, 2, 7, 7, 2, 6, // -Y
243 5, 4, 6, 6, 4, 7, // +Z
244 0, 1, 3, 3, 1, 2, // -Z
245 };
246 } cube;
247
248 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
249 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
250
251 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
252 ASSERT_TRUE(sampler);
253
254 Vector3 euler_angles;
255 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
256 SinglePassCallback callback = [&](RenderPass& pass) {
257 static Degrees fov_y(60);
258 static Scalar distance = 10;
259
260 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
261 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
262 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
263 ImGui::End();
264
265 pass.SetCommandLabel("Perspective Cube");
266 pass.SetPipeline(pipeline);
267
268 std::array<BufferView, 2> vertex_buffers = {
269 BufferView(device_buffer,
270 Range(offsetof(Cube, positions), sizeof(Cube::positions))),
271 BufferView(device_buffer,
272 Range(offsetof(Cube, colors), sizeof(Cube::colors))),
273 };
274
275 BufferView index_buffer(
276 device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
277 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
278 pass.SetElementCount(36);
279 pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
280
281 VS::UniformBuffer uniforms;
282 Scalar time = GetSecondsElapsed();
283 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
284
285 uniforms.mvp =
286 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
287 Matrix::MakeTranslation({0, 0, distance}) *
288 Matrix::MakeRotationX(Radians(euler_angles.x)) *
289 Matrix::MakeRotationY(Radians(euler_angles.y)) *
290 Matrix::MakeRotationZ(Radians(euler_angles.z));
291 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
292
293 data_host_buffer->Reset();
294 return pass.Draw().ok();
295 };
296 OpenPlaygroundHere(callback);
297 }

References impeller::ShaderStageIOSlot::binding, impeller::Color::Blue(), impeller::Degrees::degrees, impeller::saturated::distance, impeller::Color::Green(), impeller::k16bit, impeller::kBackFace, impeller::kCount4, impeller::kCounterClockwise, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakePerspective(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::ShaderStageIOSlot::offset, impeller::Color::Red(), impeller::ShaderStageBufferLayout::stride, impeller::Vector3::x, impeller::Vector3::y, impeller::Color::Yellow(), and impeller::Vector3::z.

## ◆ TEST_P() [553/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 371 of file renderer_unittests.cc.

371 {
372 using VS = BoxFadeVertexShader;
373 using FS = BoxFadeFragmentShader;
374 auto context = GetContext();
375 ASSERT_TRUE(context);
376 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
377 auto pipeline_desc =
378 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
379 pipeline_desc->SetSampleCount(SampleCount::kCount1);
380 pipeline_desc->ClearDepthAttachment();
381 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
382
383 ASSERT_TRUE(pipeline_desc.has_value());
384 auto box_pipeline =
385 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
386 ASSERT_TRUE(box_pipeline);
387 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
388
389 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
390 vertex_builder.SetLabel("Box");
391 vertex_builder.AddVertices({
392 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
393 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
394 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
395 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
396 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
397 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
398 });
399 auto vertex_buffer =
400 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
401 ASSERT_TRUE(vertex_buffer);
402
403 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
404 auto boston = CreateTextureForFixture("boston.jpg");
405 ASSERT_TRUE(bridge && boston);
406 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
407 ASSERT_TRUE(sampler);
408
409 std::shared_ptr<RenderPass> r2t_pass;
410 auto cmd_buffer = context->CreateCommandBuffer();
411 ASSERT_TRUE(cmd_buffer);
412 {
413 ColorAttachment color0;
414 color0.load_action = LoadAction::kClear;
415 color0.store_action = StoreAction::kStore;
416
417 TextureDescriptor texture_descriptor;
418 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
419 texture_descriptor.format =
420 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
421 texture_descriptor.storage_mode = StorageMode::kHostVisible;
422 texture_descriptor.size = {400, 400};
423 texture_descriptor.mip_count = 1u;
424 texture_descriptor.usage = TextureUsage::kRenderTarget;
425
426 color0.texture =
427 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
428
429 ASSERT_TRUE(color0.IsValid());
430
431 color0.texture->SetLabel("r2t_target");
432
433 StencilAttachment stencil0;
434 stencil0.load_action = LoadAction::kClear;
435 stencil0.store_action = StoreAction::kDontCare;
436 TextureDescriptor stencil_texture_desc;
437 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
438 stencil_texture_desc.size = texture_descriptor.size;
439 stencil_texture_desc.format = PixelFormat::kS8UInt;
440 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
441 stencil0.texture =
442 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
443
444 RenderTarget r2t_desc;
445 r2t_desc.SetColorAttachment(color0, 0u);
446 r2t_desc.SetStencilAttachment(stencil0);
447 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
448 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
449 }
450
451 r2t_pass->SetCommandLabel("Box");
452 r2t_pass->SetPipeline(box_pipeline);
453 r2t_pass->SetVertexBuffer(vertex_buffer);
454
455 FS::FrameInfo frame_info;
456 frame_info.current_time = GetSecondsElapsed();
457 frame_info.cursor_position = GetCursorPosition();
458 frame_info.window_size.x = GetWindowSize().width;
459 frame_info.window_size.y = GetWindowSize().height;
460
461 FS::BindFrameInfo(*r2t_pass, data_host_buffer->EmplaceUniform(frame_info));
462 FS::BindContents1(*r2t_pass, boston, sampler);
463 FS::BindContents2(*r2t_pass, bridge, sampler);
464
465 VS::UniformBuffer uniforms;
466 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
467 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
468 VS::BindUniformBuffer(*r2t_pass, data_host_buffer->EmplaceUniform(uniforms));
469 ASSERT_TRUE(r2t_pass->Draw().ok());
470 ASSERT_TRUE(r2t_pass->EncodeCommands());
471 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::TextureDescriptor::format, impeller::Attachment::IsValid(), impeller::kClear, impeller::kCount1, impeller::kDeviceTransient, impeller::kDontCare, impeller::kHostVisible, impeller::kRenderTarget, impeller::kS8UInt, impeller::kStore, impeller::Attachment::load_action, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeTranslation(), impeller::TextureDescriptor::mip_count, impeller::RenderTarget::SetColorAttachment(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::RenderTarget::SetStencilAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [554/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1510 of file renderer_unittests.cc.

1510 {
1511 // Define shader types
1512 using TextureVS = TextureVertexShader;
1513 using TextureFS = TextureFragmentShader;
1514
1515 using SwizzleVS = SepiaVertexShader;
1516 using SwizzleFS = SwizzleFragmentShader;
1517
1518 using SepiaVS = SepiaVertexShader;
1519 using SepiaFS = SepiaFragmentShader;
1520
1521 auto context = GetContext();
1522 ASSERT_TRUE(context);
1523
1524 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1525 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1526 "support it.";
1527 return;
1528 }
1529
1530 // Create pipelines.
1531 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1532 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1533 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1534
1535 ASSERT_TRUE(texture_pipeline);
1536 ASSERT_TRUE(swizzle_pipeline);
1537 ASSERT_TRUE(sepia_pipeline);
1538
1539 // Vertex buffer builders.
1540 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1541 texture_vtx_builder.AddVertices({
1542 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1543 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1544 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1545 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1546 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1547 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1548 });
1549
1550 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1551 sepia_vtx_builder.AddVertices({
1552 {{100, 100, 0.0}}, // 1
1553 {{800, 100, 0.0}}, // 2
1554 {{800, 800, 0.0}}, // 3
1555 {{100, 100, 0.0}}, // 1
1556 {{800, 800, 0.0}}, // 3
1557 {{100, 800, 0.0}}, // 4
1558 });
1559
1560 auto boston = CreateTextureForFixture("boston.jpg");
1561 ASSERT_TRUE(boston);
1562
1563 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1564 ASSERT_TRUE(sampler);
1565
1566 auto data_buffer = HostBuffer::Create(
1567 context->GetResourceAllocator(), context->GetIdleWaiter(),
1568 context->GetCapabilities()->GetMinimumUniformAlignment());
1569 SinglePassCallback callback = [&](RenderPass& pass) {
1570 // Draw the texture.
1571 {
1572 pass.SetPipeline(texture_pipeline);
1573 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1574 *context->GetResourceAllocator()));
1575 TextureVS::UniformBuffer uniforms;
1576 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1577 Matrix::MakeScale(GetContentScale());
1578 TextureVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1579 TextureFS::BindTextureContents(pass, boston, sampler);
1580 if (!pass.Draw().ok()) {
1581 return false;
1582 }
1583 }
1584
1585 // Draw the sepia toner.
1586 {
1587 pass.SetPipeline(sepia_pipeline);
1588 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1589 *context->GetResourceAllocator()));
1590 SepiaVS::UniformBuffer uniforms;
1591 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1592 Matrix::MakeScale(GetContentScale());
1593 SepiaVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1594 if (!pass.Draw().ok()) {
1595 return false;
1596 }
1597 }
1598
1599 // Draw the swizzle.
1600 {
1601 pass.SetPipeline(swizzle_pipeline);
1602 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1603 *context->GetResourceAllocator()));
1604 SwizzleVS::UniformBuffer uniforms;
1605 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1606 Matrix::MakeScale(GetContentScale());
1607 SwizzleVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1608 if (!pass.Draw().ok()) {
1609 return false;
1610 }
1611 }
1612
1613 return true;
1614 };
1615 OpenPlaygroundHere(callback);
1616 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [555/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1421 of file renderer_unittests.cc.

1421 {
1422 // Define shader types
1423 using TextureVS = TextureVertexShader;
1424 using TextureFS = TextureFragmentShader;
1425
1426 using SepiaVS = SepiaVertexShader;
1427 using SepiaFS = SepiaFragmentShader;
1428
1429 auto context = GetContext();
1430 ASSERT_TRUE(context);
1431
1432 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1433 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1434 "support it.";
1435 return;
1436 }
1437
1438 // Create pipelines.
1439 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1440 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1441
1442 ASSERT_TRUE(texture_pipeline);
1443 ASSERT_TRUE(sepia_pipeline);
1444
1445 // Vertex buffer builders.
1446 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1447 texture_vtx_builder.AddVertices({
1448 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1449 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1450 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1451 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1452 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1453 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1454 });
1455
1456 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1457 sepia_vtx_builder.AddVertices({
1458 {{100, 100, 0.0}}, // 1
1459 {{800, 100, 0.0}}, // 2
1460 {{800, 800, 0.0}}, // 3
1461 {{100, 100, 0.0}}, // 1
1462 {{800, 800, 0.0}}, // 3
1463 {{100, 800, 0.0}}, // 4
1464 });
1465
1466 auto boston = CreateTextureForFixture("boston.jpg");
1467 ASSERT_TRUE(boston);
1468
1469 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1470 ASSERT_TRUE(sampler);
1471
1472 auto buffer = HostBuffer::Create(
1473 context->GetResourceAllocator(), context->GetIdleWaiter(),
1474 context->GetCapabilities()->GetMinimumUniformAlignment());
1475 SinglePassCallback callback = [&](RenderPass& pass) {
1476 // Draw the texture.
1477 {
1478 pass.SetPipeline(texture_pipeline);
1479 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1480 *context->GetResourceAllocator()));
1481 TextureVS::UniformBuffer uniforms;
1482 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1483 Matrix::MakeScale(GetContentScale());
1484 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1485 TextureFS::BindTextureContents(pass, boston, sampler);
1486 if (!pass.Draw().ok()) {
1487 return false;
1488 }
1489 }
1490
1491 // Draw the sepia toner.
1492 {
1493 pass.SetPipeline(sepia_pipeline);
1494 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1495 *context->GetResourceAllocator()));
1496 SepiaVS::UniformBuffer uniforms;
1497 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1498 Matrix::MakeScale(GetContentScale());
1499 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1500 if (!pass.Draw().ok()) {
1501 return false;
1502 }
1503 }
1504
1505 return true;
1506 };
1507 OpenPlaygroundHere(callback);
1508 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [556/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1139 of file renderer_unittests.cc.

1139 {
1140 using VS = BoxFadeVertexShader;
1141
1142 // Do not create any index buffer if no indices were provided.
1143 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1144 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1145 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [557/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1129 of file renderer_unittests.cc.

1129 {
1130 using VS = BoxFadeVertexShader;
1131
1132 // Default to 16bit index buffer size, as this is a reasonable default and
1133 // supported on all backends without extensions.
1134 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1135 vertex_builder.AppendIndex(0u);
1136 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1137 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [558/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 1081 of file renderer_unittests.cc.

1081 {
1082 using VS = InactiveUniformsVertexShader;
1083 using FS = InactiveUniformsFragmentShader;
1084
1085 auto context = GetContext();
1086 auto pipeline_descriptor =
1087 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1088 ASSERT_TRUE(pipeline_descriptor.has_value());
1089 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1090 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1091 auto pipeline =
1092 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1093 ASSERT_TRUE(pipeline && pipeline->IsValid());
1094
1095 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1096 SinglePassCallback callback = [&](RenderPass& pass) {
1097 auto size = pass.GetRenderTargetSize();
1098
1099 pass.SetPipeline(pipeline);
1100 pass.SetCommandLabel("Inactive Uniform");
1101
1102 VertexBufferBuilder<VS::PerVertexData> builder;
1103 builder.AddVertices({{Point()},
1104 {Point(0, size.height)},
1105 {Point(size.width, 0)},
1106 {Point(size.width, 0)},
1107 {Point(0, size.height)},
1108 {Point(size.width, size.height)}});
1109 pass.SetVertexBuffer(
1110 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1111
1112 VS::FrameInfo frame_info;
1113 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1114 frame_info.mvp =
1115 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1116 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1117
1118 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1119 .color = Color::Green()};
1120 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1121
1122 pass.Draw().ok();
1123 data_host_buffer->Reset();
1124 return true;
1125 };
1126 OpenPlaygroundHere(callback);
1127 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), and impeller::Color::Red().

## ◆ TEST_P() [559/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | Planet |
| ) |  |

Definition at line 957 of file renderer_unittests.cc.

957 {
958 using VS = PlanetVertexShader;
959 using FS = PlanetFragmentShader;
960
961 auto context = GetContext();
962 auto pipeline_descriptor =
963 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
964 ASSERT_TRUE(pipeline_descriptor.has_value());
965 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
966 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
967 auto pipeline =
968 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
969 ASSERT_TRUE(pipeline && pipeline->IsValid());
970
971 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
972 SinglePassCallback callback = [&](RenderPass& pass) {
973 static Scalar speed = 0.1;
974 static Scalar planet_size = 550.0;
975 static bool show_normals = false;
976 static bool show_noise = false;
977 static Scalar seed_value = 42.0;
978
979 auto size = pass.GetRenderTargetSize();
980
981 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
982 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
983 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
984 ImGui::Checkbox("Show Normals", &show_normals);
985 ImGui::Checkbox("Show Noise", &show_noise);
986 ImGui::InputFloat("Seed Value", &seed_value);
987 ImGui::End();
988
989 pass.SetPipeline(pipeline);
990 pass.SetCommandLabel("Planet scene");
991 VertexBufferBuilder<VS::PerVertexData> builder;
992 builder.AddVertices({{Point()},
993 {Point(0, size.height)},
994 {Point(size.width, 0)},
995 {Point(size.width, 0)},
996 {Point(0, size.height)},
997 {Point(size.width, size.height)}});
998 pass.SetVertexBuffer(
999 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1000
1001 VS::FrameInfo frame_info;
1002 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1003 frame_info.mvp = pass.GetOrthographicTransform();
1004 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1005
1006 FS::FragInfo fs_uniform;
1007 fs_uniform.resolution = Point(size);
1008 fs_uniform.time = GetSecondsElapsed();
1009 fs_uniform.speed = speed;
1010 fs_uniform.planet_size = planet_size;
1011 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1012 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1013 fs_uniform.seed_value = seed_value;
1014 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1015
1016 pass.Draw().ok();
1017 data_host_buffer->Reset();
1018 return true;
1019 };
1020 OpenPlaygroundHere(callback);
1021 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Matrix::MakeOrthographic().

## ◆ TEST_P() [560/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1388 of file renderer_unittests.cc.

1389 {
1390 auto context = GetContext();
1391 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1392 GetContext()->GetResourceAllocator());
1393
1394 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1395 *context, {100, 100}, /*mip_count=*/1);
1396 EXPECT_EQ(render_target.GetDepthAttachment()
1397 ->texture->GetTextureDescriptor()
1398 .format,
1399 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1400 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [561/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1217 of file renderer_unittests.cc.

1217 {
1218 using VS = BoxFadeVertexShader;
1219 using FS = BoxFadeFragmentShader;
1220 auto context = GetContext();
1221 ASSERT_TRUE(context);
1222 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1223 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1224 ASSERT_TRUE(desc.has_value());
1225
1226 // Vertex buffer.
1227 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1228 vertex_builder.SetLabel("Box");
1229 vertex_builder.AddVertices({
1230 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1231 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1232 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1233 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1234 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1235 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1236 });
1237 auto vertex_buffer =
1238 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1239 ASSERT_TRUE(vertex_buffer);
1240
1241 desc->SetSampleCount(SampleCount::kCount4);
1242 desc->SetStencilAttachmentDescriptors(std::nullopt);
1243
1244 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1245 auto boston = CreateTextureForFixture("boston.jpg");
1246 ASSERT_TRUE(bridge && boston);
1247 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1248 ASSERT_TRUE(sampler);
1249
1250 static bool mirror = false;
1251 static int stencil_reference_write = 0xFF;
1252 static int stencil_reference_read = 0x1;
1253 std::vector<uint8_t> stencil_contents;
1254 static int last_stencil_contents_reference_value = 0;
1255 static int current_front_compare =
1256 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1257 static int current_back_compare =
1258 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1259
1260 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1261 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1262 auto buffer = context->CreateCommandBuffer();
1263 if (!buffer) {
1264 return false;
1265 }
1266 buffer->SetLabel("Playground Command Buffer");
1267
1268 {
1269 // Configure the stencil attachment for the test.
1270 RenderTarget::AttachmentConfig stencil_config;
1271 stencil_config.load_action = LoadAction::kLoad;
1272 stencil_config.store_action = StoreAction::kDontCare;
1273 stencil_config.storage_mode = StorageMode::kHostVisible;
1274 render_target.SetupDepthStencilAttachments(
1275 *context, *context->GetResourceAllocator(),
1276 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1277 // Fill the stencil buffer with an checkerboard pattern.
1278 const auto target_width = render_target.GetRenderTargetSize().width;
1279 const auto target_height = render_target.GetRenderTargetSize().height;
1280 const size_t target_size = target_width * target_height;
1281 if (stencil_contents.size() != target_size ||
1282 last_stencil_contents_reference_value != stencil_reference_write) {
1283 stencil_contents.resize(target_size);
1284 last_stencil_contents_reference_value = stencil_reference_write;
1285 for (int y = 0; y < target_height; y++) {
1286 for (int x = 0; x < target_width; x++) {
1287 const auto index = y * target_width + x;
1288 const auto kCheckSize = 64;
1289 const auto value =
1290 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1291 stencil_reference_write;
1292 stencil_contents[index] = value;
1293 }
1294 }
1295 }
1296 if (!render_target.GetStencilAttachment()->texture->SetContents(
1297 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1298 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1299 return false;
1300 }
1301 auto pass = buffer->CreateRenderPass(render_target);
1302 if (!pass) {
1303 return false;
1304 }
1305 pass->SetLabel("Stencil Buffer");
1306 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1307 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1308 0xFF);
1309 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1310 0xFF);
1311 ImGui::Checkbox("Back face mode", &mirror);
1312 ImGui::ListBox("Front face compare function", &current_front_compare,
1313 CompareFunctionUI().labels(), CompareFunctionUI().size());
1314 ImGui::ListBox("Back face compare function", &current_back_compare,
1315 CompareFunctionUI().labels(), CompareFunctionUI().size());
1316 ImGui::End();
1317
1318 StencilAttachmentDescriptor front;
1319 front.stencil_compare =
1320 CompareFunctionUI().FunctionOf(current_front_compare);
1321 StencilAttachmentDescriptor back;
1322 back.stencil_compare =
1323 CompareFunctionUI().FunctionOf(current_back_compare);
1324 desc->SetStencilAttachmentDescriptors(front, back);
1325 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1326
1327 assert(pipeline && pipeline->IsValid());
1328
1329 pass->SetCommandLabel("Box");
1330 pass->SetPipeline(pipeline);
1331 pass->SetStencilReference(stencil_reference_read);
1332 pass->SetVertexBuffer(vertex_buffer);
1333
1334 VS::UniformBuffer uniforms;
1335 EXPECT_EQ(pass->GetOrthographicTransform(),
1336 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1337 uniforms.mvp = pass->GetOrthographicTransform() *
1338 Matrix::MakeScale(GetContentScale());
1339 if (mirror) {
1340 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1341 }
1342 VS::BindUniformBuffer(*pass, data_host_buffer->EmplaceUniform(uniforms));
1343
1344 FS::FrameInfo frame_info;
1345 frame_info.current_time = GetSecondsElapsed();
1346 frame_info.cursor_position = GetCursorPosition();
1347 frame_info.window_size.x = GetWindowSize().width;
1348 frame_info.window_size.y = GetWindowSize().height;
1349
1350 FS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
1351 FS::BindContents1(*pass, boston, sampler);
1352 FS::BindContents2(*pass, bridge, sampler);
1353 if (!pass->Draw().ok()) {
1354 return false;
1355 }
1356 pass->EncodeCommands();
1357 }
1358
1359 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1360 return false;
1361 }
1362 data_host_buffer->Reset();
1363 return true;
1364 };
1365 OpenPlaygroundHere(callback);
1366 }
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1205
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1195
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1212

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), CompareFunctionUI(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::testing::CompareFunctionUIData::FunctionOf(), impeller::testing::CompareFunctionUIData::IndexOf(), impeller::kCount4, impeller::kDontCare, impeller::kHostVisible, impeller::kLessEqual, impeller::kLoad, impeller::RenderTarget::AttachmentConfig::load_action, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::StencilAttachmentDescriptor::stencil_compare, impeller::RenderTarget::AttachmentConfig::storage_mode, impeller::RenderTarget::AttachmentConfig::store_action, VALIDATION_LOG, value, and x.

## ◆ TEST_P() [562/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 894 of file renderer_unittests.cc.

894 {
895 using VS = ImpellerVertexShader;
896 using FS = ImpellerFragmentShader;
897
898 auto context = GetContext();
899 auto pipeline_descriptor =
900 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
901 ASSERT_TRUE(pipeline_descriptor.has_value());
902 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
903 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
904 auto pipeline =
905 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
906 ASSERT_TRUE(pipeline && pipeline->IsValid());
907
908 auto blue_noise = CreateTextureForFixture("blue_noise.png");
909 SamplerDescriptor noise_sampler_desc;
910 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
911 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
912 raw_ptr<const Sampler> noise_sampler =
913 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
914
915 auto cube_map = CreateTextureCubeForFixture(
916 {"table_mountain_px.png", "table_mountain_nx.png",
917 "table_mountain_py.png", "table_mountain_ny.png",
918 "table_mountain_pz.png", "table_mountain_nz.png"});
919 raw_ptr<const Sampler> cube_map_sampler =
920 context->GetSamplerLibrary()->GetSampler({});
921
922 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
923 SinglePassCallback callback = [&](RenderPass& pass) {
924 auto size = pass.GetRenderTargetSize();
925
926 pass.SetPipeline(pipeline);
927 pass.SetCommandLabel("Impeller SDF scene");
928 VertexBufferBuilder<VS::PerVertexData> builder;
929 builder.AddVertices({{Point()},
930 {Point(0, size.height)},
931 {Point(size.width, 0)},
932 {Point(size.width, 0)},
933 {Point(0, size.height)},
934 {Point(size.width, size.height)}});
935 pass.SetVertexBuffer(
936 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
937
938 VS::FrameInfo frame_info;
939 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
940 frame_info.mvp = pass.GetOrthographicTransform();
941 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
942
943 FS::FragInfo fs_uniform;
944 fs_uniform.texture_size = Point(size);
945 fs_uniform.time = GetSecondsElapsed();
946 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
947 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
948 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
949
950 pass.Draw().ok();
951 data_host_buffer->Reset();
952 return true;
953 };
954 OpenPlaygroundHere(callback);
955 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::SamplerDescriptor::height_address_mode, impeller::kCount4, impeller::kRepeat, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), and impeller::SamplerDescriptor::width_address_mode.

## ◆ TEST_P() [563/603]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1147 of file renderer_unittests.cc.

1147 {
1148 // Does not create index buffer if one is provided.
1149 using VS = BoxFadeVertexShader;
1150 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1151 vertex_builder.SetLabel("Box");
1152 vertex_builder.AddVertices({
1153 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1154 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1155 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1156 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1157 });
1158 vertex_builder.AppendIndex(0);
1159 vertex_builder.AppendIndex(1);
1160 vertex_builder.AppendIndex(2);
1161 vertex_builder.AppendIndex(1);
1162 vertex_builder.AppendIndex(2);
1163 vertex_builder.AppendIndex(3);
1164
1165 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1166 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1167 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexCount(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetVertexCount(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [564/603]

impeller::testing::TEST_P | ( | RenderPassGLESWithDiscardFrameBufferExtTest | ,
|  | DiscardFramebufferExt |
| ) |  |

Definition at line 68 of file render_pass_gles_unittests.cc.

68 {
69 auto mock_gl_impl = std::make_unique<NiceMock<MockGLESImpl>>();
70 auto& mock_gl_impl_ref = *mock_gl_impl;
71 auto mock_gl =
72 MockGLES::Init(std::move(mock_gl_impl), {{"GL_EXT_discard_framebuffer"}});
73
74 auto context = CreateFakeGLESContext();
75 auto dummy_worker = std::make_shared<MockWorker>();
76 context->AddReactorWorker(dummy_worker);
77 auto reactor = context->GetReactor();
78
79 const auto command_buffer =
80 std::static_pointer_cast<Context>(context)->CreateCommandBuffer();
81 auto render_target = RenderTarget{};
82 const auto description = TextureDescriptor{
83 .format = PixelFormat::kR8G8B8A8UNormInt, .size = {10, 10}};
84
85 const auto& test_params = GetParam();
86 auto framebuffer_texture =
87 TextureGLES::WrapFBO(reactor, description, test_params.frame_buffer_id);
88
89 auto color_attachment = ColorAttachment{Attachment{
90 .texture = framebuffer_texture, .store_action = StoreAction::kDontCare}};
91 render_target.SetColorAttachment(color_attachment, 0);
92 const auto render_pass = command_buffer->CreateRenderPass(render_target);
93
94 EXPECT_CALL(mock_gl_impl_ref, GetIntegerv(GL_FRAMEBUFFER_BINDING, _))
95 .WillOnce(SetArgPointee<1>(test_params.frame_buffer_id));
96
97 EXPECT_CALL(mock_gl_impl_ref, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _))
98 .With(Args<2, 1>(ElementsAreArray(test_params.expected_attachments)))
99 .Times(1);
100 ASSERT_TRUE(render_pass->EncodeCommands());
101 ASSERT_TRUE(reactor->React());
102 }

References impeller::TextureDescriptor::format, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::Attachment::texture, and impeller::TextureGLES::WrapFBO().

## ◆ TEST_P() [565/603]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachedTextureGetsNewAttachmentConfig |
| ) |  |

Definition at line 123 of file render_target_cache_unittests.cc.

123 {
124 auto render_target_cache = RenderTargetCache(
125 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
126
127 render_target_cache.Start();
128 RenderTarget::AttachmentConfig color_attachment_config =
129 RenderTarget::kDefaultColorAttachmentConfig;
130 RenderTarget target1 = render_target_cache.CreateOffscreen(
131 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
132 render_target_cache.End();
133
134 render_target_cache.Start();
135 color_attachment_config.clear_color = Color::Red();
136 RenderTarget target2 = render_target_cache.CreateOffscreen(
137 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
138 render_target_cache.End();
139
140 ColorAttachment color1 = target1.GetColorAttachment(0);
141 ColorAttachment color2 = target2.GetColorAttachment(0);
142 // The second color attachment should reuse the first attachment's texture
143 // but with attributes from the second AttachmentConfig.
144 EXPECT_EQ(color2.texture, color1.texture);
145 EXPECT_EQ(color2.clear_color, Color::Red());
146 }

References impeller::ColorAttachment::clear_color, impeller::RenderTarget::AttachmentConfig::clear_color, impeller::RenderTarget::GetColorAttachment(), impeller::RenderTarget::kDefaultColorAttachmentConfig, impeller::Color::Red(), and impeller::Attachment::texture.

## ◆ TEST_P() [566/603]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFrames |
| ) |  |

Definition at line 53 of file render_target_cache_unittests.cc.

53 {
54 auto render_target_cache = RenderTargetCache(
55 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
56
57 render_target_cache.Start();
58 // Create two render targets of the same exact size/shape. Both should be
59 // marked as used this frame, so the cached data set will contain two.
60 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
61 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
62
63 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
64
65 render_target_cache.End();
66 render_target_cache.Start();
67
68 // Next frame, only create one texture. The set will still contain two,
69 // but one will be removed at the end of the frame.
70 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
71 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
72
73 render_target_cache.End();
74 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
75 }

## ◆ TEST_P() [567/603]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFramesWithKeepAlive |
| ) |  |

Definition at line 77 of file render_target_cache_unittests.cc.

77 {
78 auto render_target_cache = RenderTargetCache(
79 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/3);
80
81 render_target_cache.Start();
82 // Create two render targets of the same exact size/shape. Both should be
83 // marked as used this frame, so the cached data set will contain two.
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
86
87 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
88
89 render_target_cache.End();
90 render_target_cache.Start();
91
92 // The unused texture is kept alive until the keep alive countdown
93 // reaches 0.
94 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
95
96 for (auto i = 0; i < 3; i++) {
97 render_target_cache.Start();
98 render_target_cache.End();
99 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
100 }
101 // After the countdown has elapsed the texture is removed.
102 render_target_cache.Start();
103 render_target_cache.End();
104 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
105 }

## ◆ TEST_P() [568/603]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CreateWithEmptySize |
| ) |  |

Definition at line 148 of file render_target_cache_unittests.cc.

148 {
149 auto render_target_cache = RenderTargetCache(
150 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
151
152 render_target_cache.Start();
153 RenderTarget empty_target =
154 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
155 RenderTarget empty_target_msaa =
156 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
157 render_target_cache.End();
158
159 {
160 ScopedValidationDisable disable_validation;
161 EXPECT_FALSE(empty_target.IsValid());
162 EXPECT_FALSE(empty_target_msaa.IsValid());
163 }
164 }

References impeller::RenderTarget::IsValid().

## ◆ TEST_P() [569/603]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | DoesNotPersistFailedAllocations |
| ) |  |

Definition at line 107 of file render_target_cache_unittests.cc.

107 {
108 ScopedValidationDisable disable;
109 auto allocator = std::make_shared<TestAllocator>();
110 auto render_target_cache =
111 RenderTargetCache(allocator, /*keep_alive_frame_count=*/0);
112
113 render_target_cache.Start();
114 allocator->should_fail = true;
115
116 auto render_target =
117 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
118
119 EXPECT_FALSE(render_target.IsValid());
120 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
121 }

## ◆ TEST_P() [570/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 424 of file runtime_stage_unittests.cc.

424 {
425 auto stages_result = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
426 ABSL_ASSERT_OK(stages_result);
427 auto stage =
428 stages_result
429 .value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
430
431 ASSERT_TRUE(stage);
432 ASSERT_NE(stage, nullptr);
433 ASSERT_TRUE(RegisterStage(*stage));
434 auto library = GetContext()->GetShaderLibrary();
435 using VS = RuntimeEffectVertexShader;
436 PipelineDescriptor desc;
437 desc.SetLabel("Runtime Stage InkSparkle");
438 desc.AddStageEntrypoint(
439 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
440 desc.AddStageEntrypoint(
441 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
442 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
443 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
444 VS::kInterleavedBufferLayout);
445
446 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
447 VS::kDescriptorSetLayouts[0],
448 DescriptorSetLayout{
449 .binding = 64u,
450 .descriptor_type = DescriptorType::kUniformBuffer,
451 .shader_stage = ShaderStage::kFragment,
452 },
453 };
454 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
455
456 desc.SetVertexDescriptor(std::move(vertex_descriptor));
457 ColorAttachmentDescriptor color0;
458 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
459 StencilAttachmentDescriptor stencil0;
460 stencil0.stencil_compare = CompareFunction::kEqual;
461 desc.SetColorAttachmentDescriptor(0u, color0);
462 desc.SetStencilAttachmentDescriptors(stencil0);
463 const auto stencil_fmt =
464 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
465 desc.SetStencilPixelFormat(stencil_fmt);
466 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
467 ASSERT_NE(pipeline, nullptr);
468 }

References impeller::PipelineDescriptor::AddStageEntrypoint(), impeller::DescriptorSetLayout::binding, impeller::ColorAttachmentDescriptor::format, impeller::kEqual, impeller::kFragment, impeller::kUniformBuffer, impeller::kVertex, impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::PipelineDescriptor::SetColorAttachmentDescriptor(), impeller::PipelineDescriptor::SetLabel(), impeller::PipelineDescriptor::SetStencilAttachmentDescriptors(), impeller::PipelineDescriptor::SetStencilPixelFormat(), impeller::PipelineDescriptor::SetVertexDescriptor(), and impeller::StencilAttachmentDescriptor::stencil_compare.

## ◆ TEST_P() [571/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniforms |
| ) |  |

Definition at line 75 of file runtime_stage_unittests.cc.

75 {
76 const std::shared_ptr<fml::Mapping> fixture =
77 flutter::testing::OpenFixtureAsMapping(
78 "all_supported_uniforms.frag.iplr");
79 ASSERT_TRUE(fixture);
80 ASSERT_GT(fixture->GetSize(), 0u);
81 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
82 ABSL_ASSERT_OK(stages);
83 auto stage =
84 stages.value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
85
86 ASSERT_TRUE(stage);
87 switch (GetBackend()) {
88 case PlaygroundBackend::kMetal:
89 [[fallthrough]];
90 case PlaygroundBackend::kOpenGLES: {
91 ASSERT_EQ(stage->GetUniforms().size(), 14u);
92 {
93 // uFloat
94 auto uni = stage->GetUniform("uFloat");
95 ASSERT_NE(uni, nullptr);
96 EXPECT_EQ(uni->dimensions.rows, 1u);
97 EXPECT_EQ(uni->dimensions.cols, 1u);
98 EXPECT_EQ(uni->location, 0u);
99 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
100 EXPECT_TRUE(uni->padding_layout.empty());
101 }
102 {
103 // uVec2
104 auto uni = stage->GetUniform("uVec2");
105 ASSERT_NE(uni, nullptr);
106 EXPECT_EQ(uni->dimensions.rows, 2u);
107 EXPECT_EQ(uni->dimensions.cols, 1u);
108 EXPECT_EQ(uni->location, 1u);
109 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
110 EXPECT_TRUE(uni->padding_layout.empty());
111 }
112 {
113 // uVec3
114 auto uni = stage->GetUniform("uVec3");
115 ASSERT_NE(uni, nullptr);
116 EXPECT_EQ(uni->dimensions.rows, 3u);
117 EXPECT_EQ(uni->dimensions.cols, 1u);
118 EXPECT_EQ(uni->location, 2u);
119 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
120 auto padding = uni->padding_layout;
121 if (GetBackend() == PlaygroundBackend::kMetal) {
122 EXPECT_EQ(padding.size(), 4u);
123 EXPECT_EQ(padding[0], RuntimePaddingType::kFloat);
124 EXPECT_EQ(padding[1], RuntimePaddingType::kFloat);
125 EXPECT_EQ(padding[2], RuntimePaddingType::kFloat);
126 EXPECT_EQ(padding[3], RuntimePaddingType::kPadding);
127 } else {
128 EXPECT_TRUE(padding.empty());
129 }
130 }
131 {
132 // uVec4
133 auto uni = stage->GetUniform("uVec4");
134 ASSERT_NE(uni, nullptr);
135 EXPECT_EQ(uni->dimensions.rows, 4u);
136 EXPECT_EQ(uni->dimensions.cols, 1u);
137 EXPECT_EQ(uni->location, 3u);
138 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
139 EXPECT_TRUE(uni->padding_layout.empty());
140 }
141 {
142 // uMat2
143 auto uni = stage->GetUniform("uMat2");
144 ASSERT_NE(uni, nullptr);
145 EXPECT_EQ(uni->dimensions.rows, 2u);
146 EXPECT_EQ(uni->dimensions.cols, 2u);
147 EXPECT_EQ(uni->location, 4u);
148 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
149 EXPECT_TRUE(uni->padding_layout.empty());
150 }
151 {
152 // uMat3
153 auto uni = stage->GetUniform("uMat3");
154 ASSERT_NE(uni, nullptr);
155 EXPECT_EQ(uni->dimensions.rows, 3u);
156 EXPECT_EQ(uni->dimensions.cols, 3u);
157 EXPECT_EQ(uni->location, 5u);
158 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
159 }
160 {
161 // uMat4
162 auto uni = stage->GetUniform("uMat4");
163 ASSERT_NE(uni, nullptr);
164 EXPECT_EQ(uni->dimensions.rows, 4u);
165 EXPECT_EQ(uni->dimensions.cols, 4u);
166 EXPECT_EQ(uni->location, 6u);
167 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
168 EXPECT_TRUE(uni->padding_layout.empty());
169 }
170 {
171 // uFloatArray
172 auto uni = stage->GetUniform("uFloatArray");
173 ASSERT_NE(uni, nullptr);
174 EXPECT_EQ(uni->dimensions.rows, 1u);
175 EXPECT_EQ(uni->dimensions.cols, 1u);
176 EXPECT_EQ(uni->location, 7u);
177 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
178 EXPECT_TRUE(uni->padding_layout.empty());
179 }
180 {
181 auto uni = stage->GetUniform("uVec2Array");
182 ASSERT_NE(uni, nullptr);
183 EXPECT_EQ(uni->dimensions.rows, 2u);
184 EXPECT_EQ(uni->dimensions.cols, 1u);
185 EXPECT_EQ(uni->location, 9u);
186 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
187 EXPECT_TRUE(uni->padding_layout.empty());
188 }
189 {
190 // uVec3Array
191 auto uni = stage->GetUniform("uVec3Array");
192 ASSERT_NE(uni, nullptr);
193 EXPECT_EQ(uni->dimensions.rows, 3u);
194 EXPECT_EQ(uni->dimensions.cols, 1u);
195 EXPECT_EQ(uni->location, 11u);
196 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
197 }
198 {
199 // uVec4Array
200 auto uni = stage->GetUniform("uVec4Array");
201 ASSERT_NE(uni, nullptr);
202 EXPECT_EQ(uni->dimensions.rows, 4u);
203 EXPECT_EQ(uni->dimensions.cols, 1u);
204 EXPECT_EQ(uni->location, 13u);
205 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
206 EXPECT_TRUE(uni->padding_layout.empty());
207 }
208 {
209 // uMat2Array
210 auto uni = stage->GetUniform("uMat2Array");
211 ASSERT_NE(uni, nullptr);
212 EXPECT_EQ(uni->dimensions.rows, 2u);
213 EXPECT_EQ(uni->dimensions.cols, 2u);
214 EXPECT_EQ(uni->location, 15u);
215 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
216 EXPECT_TRUE(uni->padding_layout.empty());
217 }
218 {
219 // uMat3Array
220 auto uni = stage->GetUniform("uMat3Array");
221 ASSERT_NE(uni, nullptr);
222 EXPECT_EQ(uni->dimensions.rows, 3u);
223 EXPECT_EQ(uni->dimensions.cols, 3u);
224 EXPECT_EQ(uni->location, 17u);
225 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
226 }
227 {
228 // uMat4Array
229 auto uni = stage->GetUniform("uMat4Array");
230 ASSERT_NE(uni, nullptr);
231 EXPECT_EQ(uni->dimensions.rows, 4u);
232 EXPECT_EQ(uni->dimensions.cols, 4u);
233 EXPECT_EQ(uni->location, 19u);
234 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
235 EXPECT_TRUE(uni->padding_layout.empty());
236 }
237 break;
238 }
239 case PlaygroundBackend::kVulkan: {
240 EXPECT_EQ(stage->GetUniforms().size(), 1u);
241 const RuntimeUniformDescription* uni =
242 stage->GetUniform(RuntimeStage::kVulkanUBOName);
243 ASSERT_TRUE(uni);
244 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
245 EXPECT_EQ(uni->struct_float_count, 35u);
246
247 EXPECT_EQ(uni->GetGPUSize(), 640u);
248 std::vector<RuntimePaddingType> layout(uni->GetGPUSize() / sizeof(float),
249 RuntimePaddingType::kFloat);
250 // uFloat and uVec2 are packed into a vec4 with 1 byte of padding between.
251 layout[1] = RuntimePaddingType::kPadding;
252 // uVec3 is packed as a vec4 with 1 byte of padding.
253 layout[7] = RuntimePaddingType::kPadding;
254 // uMat2 is packed as two vec4s, with the last 2 bytes of each being
255 // padding.
256 layout[14] = RuntimePaddingType::kPadding;
257 layout[15] = RuntimePaddingType::kPadding;
258 layout[18] = RuntimePaddingType::kPadding;
259 layout[19] = RuntimePaddingType::kPadding;
260 // uMat3 is packed as 3 vec4s, with the last 3 bytes being padding
261 layout[29] = RuntimePaddingType::kPadding;
262 layout[30] = RuntimePaddingType::kPadding;
263 layout[31] = RuntimePaddingType::kPadding;
264 // uFloatArray is packed as 2 vec4s, with the last 3 bytes of each
265 // being padding.
266 layout[49] = RuntimePaddingType::kPadding;
267 layout[50] = RuntimePaddingType::kPadding;
268 layout[51] = RuntimePaddingType::kPadding;
269 layout[53] = RuntimePaddingType::kPadding;
270 layout[54] = RuntimePaddingType::kPadding;
271 layout[55] = RuntimePaddingType::kPadding;
272 // uVec2Array is packed as 2 vec4s, with 2 bytes of padding at the end of
273 // each.
274 layout[58] = RuntimePaddingType::kPadding;
275 layout[59] = RuntimePaddingType::kPadding;
276 layout[62] = RuntimePaddingType::kPadding;
277 layout[63] = RuntimePaddingType::kPadding;
278 // uVec3Array is packed as 2 vec4s, with the last byte of each as padding.
279 layout[67] = RuntimePaddingType::kPadding;
280 layout[71] = RuntimePaddingType::kPadding;
281 // uVec4Array has no padding.
282 // uMat2Array[2] is packed as 4 vec4s, With the last 2 bytes of each being
283 // padding. padding.
284 layout[82] = RuntimePaddingType::kPadding;
285 layout[83] = RuntimePaddingType::kPadding;
286 layout[86] = RuntimePaddingType::kPadding;
287 layout[87] = RuntimePaddingType::kPadding;
288 layout[90] = RuntimePaddingType::kPadding;
289 layout[91] = RuntimePaddingType::kPadding;
290 layout[94] = RuntimePaddingType::kPadding;
291 layout[95] = RuntimePaddingType::kPadding;
292 // uMat3Array[2] is packed as 6 vec4s, with the last 3 bytes of the 3rd
293 // and 6th being padding.
294 layout[105] = RuntimePaddingType::kPadding;
295 layout[106] = RuntimePaddingType::kPadding;
296 layout[107] = RuntimePaddingType::kPadding;
297 layout[117] = RuntimePaddingType::kPadding;
298 layout[118] = RuntimePaddingType::kPadding;
299 layout[119] = RuntimePaddingType::kPadding;
300 // uMat4Array[2] is packed as 8 vec4s with no padding.
301 layout[152] = RuntimePaddingType::kPadding;
302 layout[153] = RuntimePaddingType::kPadding;
303 layout[154] = RuntimePaddingType::kPadding;
304 layout[155] = RuntimePaddingType::kPadding;
305 layout[156] = RuntimePaddingType::kPadding;
306 layout[157] = RuntimePaddingType::kPadding;
307 layout[158] = RuntimePaddingType::kPadding;
308 layout[159] = RuntimePaddingType::kPadding;
309
310 EXPECT_THAT(uni->padding_layout, ::testing::ElementsAreArray(layout));
311
312 std::vector<std::pair<std::string, unsigned int>> expected_uniforms = {
313 {"uFloat", 4}, {"uVec2", 8}, {"uVec3", 12},
314 {"uVec4", 16}, {"uMat2", 16}, {"uMat3", 36},
315 {"uMat4", 64}, {"uFloatArray", 8}, {"uVec2Array", 16},
316 {"uVec3Array", 24}, {"uVec4Array", 32}, {"uMat2Array", 32},
317 {"uMat3Array", 72}, {"uMat4Array", 128}};
318
319 ASSERT_EQ(uni->struct_fields.size(), expected_uniforms.size());
320
321 for (size_t i = 0; i < expected_uniforms.size(); ++i) {
322 const auto& element = uni->struct_fields[i];
323 const auto& expected = expected_uniforms[i];
324
325 EXPECT_EQ(element.name, expected.first) << "index: " << i;
326 EXPECT_EQ(element.byte_size, expected.second) << "index: " << i;
327 }
328 break;
329 }
330 }
331 }
impeller::kPadding
constexpr auto kPadding
Definition: typographer_context_skia.cc:48
impeller::kStruct
@ kStruct
Definition: runtime_types.h:27

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::RuntimeUniformDescription::GetGPUSize(), impeller::kFloat, impeller::kMetal, impeller::kOpenGLES, impeller::kPadding, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, padding, impeller::RuntimeUniformDescription::padding_layout, impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::RuntimeUniformDescription::struct_fields, impeller::RuntimeUniformDescription::struct_float_count, and impeller::RuntimeUniformDescription::type.

## ◆ TEST_P() [572/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerAfterUBO |
| ) |  |

Definition at line 360 of file runtime_stage_unittests.cc.

360 {
361 if (GetBackend() != PlaygroundBackend::kVulkan) {
362 GTEST_SKIP() << "Test only relevant for Vulkan";
363 }
364 const std::shared_ptr<fml::Mapping> fixture =
365 flutter::testing::OpenFixtureAsMapping(
366 "uniforms_and_sampler_2.frag.iplr");
367 ASSERT_TRUE(fixture);
368 ASSERT_GT(fixture->GetSize(), 0u);
369 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
370 ABSL_ASSERT_OK(stages);
371 auto stage =
372 stages.value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
373
374 EXPECT_EQ(stage->GetUniforms().size(), 2u);
375 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
376 ASSERT_TRUE(uni);
377 // Struct must be offset at 45.
378 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
379 EXPECT_EQ(uni->binding, 64u);
380 // Sampler should be offset at 64 but due to current bug
381 // has offset of 0, the correct offset is computed at runtime.
382 auto sampler_uniform = stage->GetUniform("u_texture");
383 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
384 EXPECT_EQ(sampler_uniform->binding, 65u);
385 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [573/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerBeforeUBO |
| ) |  |

Definition at line 333 of file runtime_stage_unittests.cc.

333 {
334 if (GetBackend() != PlaygroundBackend::kVulkan) {
335 GTEST_SKIP() << "Test only relevant for Vulkan";
336 }
337 const std::shared_ptr<fml::Mapping> fixture =
338 flutter::testing::OpenFixtureAsMapping(
339 "uniforms_and_sampler_1.frag.iplr");
340 ASSERT_TRUE(fixture);
341 ASSERT_GT(fixture->GetSize(), 0u);
342 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
343 ABSL_ASSERT_OK(stages);
344 auto stage =
345 stages.value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
346
347 EXPECT_EQ(stage->GetUniforms().size(), 2u);
348 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
349 ASSERT_TRUE(uni);
350 // Struct must be offset at 65.
351 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
352 EXPECT_EQ(uni->binding, 65u);
353 // Sampler should be offset at 64 but due to current bug
354 // has offset of 0, the correct offset is computed at runtime.
355 auto sampler_uniform = stage->GetUniform("u_texture");
356 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
357 EXPECT_EQ(sampler_uniform->binding, 64u);
358 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [574/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadValidBlob |
| ) |  |

Definition at line 33 of file runtime_stage_unittests.cc.

33 {
34 const std::shared_ptr<fml::Mapping> fixture =
35 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
36 ASSERT_TRUE(fixture);
37 ASSERT_GT(fixture->GetSize(), 0u);
38 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
39 ABSL_ASSERT_OK(stages);
40 auto stage =
41 stages.value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
42 ASSERT_TRUE(stage);
43 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
44 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [575/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 387 of file runtime_stage_unittests.cc.

387 {
388 const std::shared_ptr<fml::Mapping> fixture =
389 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
390 ASSERT_TRUE(fixture);
391 ASSERT_GT(fixture->GetSize(), 0u);
392 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
393 ABSL_ASSERT_OK(stages);
394 auto stage =
395 stages.value()[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
396 ASSERT_TRUE(stage);
397 std::promise<bool> registration;
398 auto future = registration.get_future();
399 auto library = GetContext()->GetShaderLibrary();
400 library->RegisterFunction(
401 stage->GetEntrypoint(), //
402 ToShaderStage(stage->GetShaderStage()), //
403 stage->GetCodeMapping(), //
404 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
405 reg.set_value(result);
406 }));
407 ASSERT_TRUE(future.get());
408 {
409 auto function =
410 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
411 ASSERT_NE(function, nullptr);
412 }
413
414 // Check if unregistering works.
415
416 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
417 {
418 auto function =
419 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
420 ASSERT_EQ(function, nullptr);
421 }
422 }
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::ToShaderStage().

## ◆ TEST_P() [576/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRejectInvalidBlob |
| ) |  |

Definition at line 59 of file runtime_stage_unittests.cc.

59 {
60 ScopedValidationDisable disable_validation;
61 const std::shared_ptr<fml::Mapping> fixture =
62 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
63 ASSERT_TRUE(fixture);
64 auto junk_allocation = std::make_shared<Allocation>();
65 ASSERT_TRUE(junk_allocation->Truncate(Bytes{fixture->GetSize()}, false));
66 // Not meant to be secure. Just reject obviously bad blobs using magic
67 // numbers.
68 ::memset(junk_allocation->GetBuffer(), 127,
69 junk_allocation->GetLength().GetByteSize());
70 auto stages = RuntimeStage::DecodeRuntimeStages(
71 CreateMappingFromAllocation(junk_allocation));
72 ASSERT_FALSE(stages.ok());
73 }
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Creates a mapping from allocation.
Definition: allocation.cc:99

References impeller::CreateMappingFromAllocation(), and impeller::RuntimeStage::DecodeRuntimeStages().

## ◆ TEST_P() [577/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 470 of file runtime_stage_unittests.cc.

470 {
471 auto stages_result = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
472 ABSL_ASSERT_OK(stages_result);
473 auto stages = stages_result.value();
474 // Right now, SkSL gets implicitly bundled regardless of what the build rule
475 // for this test requested. After
476 // https://github.com/flutter/flutter/issues/138919, this may require a build
477 // rule change or a new test.
478 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
479
480 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
481 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
482 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
483 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [578/603]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | RejectInvalidFormatVersion |
| ) |  |

Definition at line 46 of file runtime_stage_unittests.cc.

46 {
47 flatbuffers::FlatBufferBuilder builder;
48 fb::RuntimeStagesBuilder stages_builder(builder);
49 stages_builder.add_format_version(0);
50 auto stages = stages_builder.Finish();
51 builder.Finish(stages, fb::RuntimeStagesIdentifier());
52 auto mapping = std::make_shared<fml::NonOwnedMapping>(
53 builder.GetBufferPointer(), builder.GetSize());
54 auto runtime_stages = RuntimeStage::DecodeRuntimeStages(mapping);
55 EXPECT_FALSE(runtime_stages.ok());
56 EXPECT_EQ(runtime_stages.status().code(), absl::StatusCode::kInvalidArgument);
57 }

References impeller::RuntimeStage::DecodeRuntimeStages().

## ◆ TEST_P() [579/603]

impeller::testing::TEST_P | ( | SwapchainTransientsMTLTest | ,
|  | CanAllocateSwapchainTextures |
| ) |  |

Definition at line 27 of file swapchain_transients_mtl_unittests.mm.

27 {
28 const auto& transients = std::make_shared<SwapchainTransientsMTL>(
29 GetContext()->GetResourceAllocator());
30
31 transients->SetSizeAndFormat({1, 1}, PixelFormat::kB8G8R8A8UNormInt);
32
33 auto resolve = transients->GetResolveTexture();
34 EXPECT_NE(resolve, nullptr);
35 EXPECT_NE(transients->GetMSAATexture(), nullptr);
36 EXPECT_NE(transients->GetDepthStencilTexture(), nullptr);
37
38 // Texture properties are correct for resolve.
39 EXPECT_EQ(resolve->GetTextureDescriptor().size, ISize(1, 1));
40 EXPECT_EQ(resolve->GetTextureDescriptor().format,
41 PixelFormat::kB8G8R8A8UNormInt);
42 EXPECT_EQ(resolve->GetTextureDescriptor().sample_count, SampleCount::kCount1);
43 EXPECT_EQ(resolve->GetTextureDescriptor().storage_mode,
44 StorageMode::kDevicePrivate);
45
46 // Texture properties are correct for MSAA.
47 auto msaa = transients->GetMSAATexture();
48 EXPECT_EQ(msaa->GetTextureDescriptor().size, ISize(1, 1));
49 EXPECT_EQ(msaa->GetTextureDescriptor().format,
50 PixelFormat::kB8G8R8A8UNormInt);
51 EXPECT_EQ(msaa->GetTextureDescriptor().sample_count, SampleCount::kCount4);
52 EXPECT_EQ(msaa->GetTextureDescriptor().storage_mode,
53 StorageMode::kDeviceTransient);
54
55 // Texture properties are correct for Depth+Stencil.
56 auto depth_stencil = transients->GetDepthStencilTexture();
57 EXPECT_EQ(depth_stencil->GetTextureDescriptor().size, ISize(1, 1));
58 EXPECT_EQ(depth_stencil->GetTextureDescriptor().format,
59 PixelFormat::kD32FloatS8UInt);
60 EXPECT_EQ(depth_stencil->GetTextureDescriptor().sample_count,
61 SampleCount::kCount4);
62 EXPECT_EQ(depth_stencil->GetTextureDescriptor().storage_mode,
63 StorageMode::kDeviceTransient);
64
65 // Textures are cached.
66 EXPECT_EQ(transients->GetResolveTexture(), resolve);
67
68 // Texture cache is invalidated when size changes.
69 transients->SetSizeAndFormat({2, 2}, PixelFormat::kB8G8R8A8UNormInt);
70 EXPECT_NE(resolve, transients->GetResolveTexture());
71 resolve = transients->GetResolveTexture();
72
73 // Texture cache is invalidated when pixel format changes.
74 transients->SetSizeAndFormat({2, 2}, PixelFormat::kB10G10R10A10XR);
75 EXPECT_NE(resolve, transients->GetResolveTexture());
76 }

References impeller::kB10G10R10A10XR, impeller::kB8G8R8A8UNormInt, impeller::kCount1, impeller::kCount4, impeller::kD32FloatS8UInt, impeller::kDevicePrivate, and impeller::kDeviceTransient.

## ◆ TEST_P() [580/603]

impeller::testing::TEST_P | ( | TessellatorPlaygroundTest | ,
|  | TessellateConvex16or32Bit |
| ) |  |

Definition at line 26 of file tessellator_playground_unittests.cc.

26 {
27 auto tessellator16 = std::make_shared<Tessellator>(false);
28 auto tessellator32 = std::make_shared<Tessellator>(true);
29
30 auto data_host_buffer = HostBuffer::Create(
31 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
32 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
33 auto indexes_host_buffer = HostBuffer::Create(
34 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
35 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
36
37 auto path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
38
39 auto vertex_buffer16 = tessellator16->TessellateConvex(
40 path, *data_host_buffer, *indexes_host_buffer, 1.0, false, false);
41 auto vertex_buffer32 = tessellator32->TessellateConvex(
42 path, *data_host_buffer, *indexes_host_buffer, 1.0, false, false);
43
44 const std::vector<Point> expected = {
45 {0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
46 const std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
47
48 EXPECT_EQ(vertex_buffer16.index_type, IndexType::k16bit);
49 EXPECT_EQ(expected, CopyBufferView<Point>(vertex_buffer16.vertex_buffer));
50 EXPECT_EQ(expected_indices,
51 CopyBufferView<uint16_t>(vertex_buffer16.index_buffer));
52
53 EXPECT_EQ(vertex_buffer32.index_type, IndexType::k32bit);
54 EXPECT_EQ(expected, CopyBufferView<Point>(vertex_buffer32.vertex_buffer));
55 EXPECT_EQ(
56 std::vector<uint32_t>(expected_indices.begin(), expected_indices.end()),
57 CopyBufferView<uint32_t>(vertex_buffer32.index_buffer));
58 }

References impeller::HostBuffer::Create(), impeller::k16bit, impeller::k32bit, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [581/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | MaintainsShape |
| ) |  |

Definition at line 184 of file text_contents_unittests.cc.

184 {
185 std::shared_ptr<TextFrame> text_frame =
186 MakeTextFrame("th", "ahem.ttf", TextOptions{.font_size = 50});
187
188 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
189 std::shared_ptr<GlyphAtlasContext> atlas_context =
190 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
191 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
192 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
193 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
194 ASSERT_TRUE(context && context->IsValid());
195
196 for (int i = 0; i <= 1000; ++i) {
197 Rational font_scale(440 + i, 1000.0);
198 Rect position_rect[2];
199 Rect uv_rect[2];
200
201 {
202 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(12);
203
204 std::shared_ptr<GlyphAtlas> atlas =
205 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
206 GlyphAtlas::Type::kAlphaBitmap, font_scale,
207 atlas_context, text_frame, /*offset=*/{0, 0});
208 ISize texture_size = atlas->GetTexture()->GetSize();
209
210 TextContents::ComputeVertexData(
211 data.data(), text_frame, static_cast<Scalar>(font_scale),
212 /*entity_transform=*/
213 Matrix::MakeScale({static_cast<Scalar>(font_scale),
214 static_cast<Scalar>(font_scale), 1}),
215 /*offset=*/Vector2(0, 0),
216 /*glyph_properties=*/std::nullopt, atlas);
217 position_rect[0] = PerVertexDataPositionToRect(data.begin());
218 uv_rect[0] = PerVertexDataUVToRect(data.begin(), texture_size);
219 position_rect[1] = PerVertexDataPositionToRect(data.begin() + 4);
220 uv_rect[1] = PerVertexDataUVToRect(data.begin() + 4, texture_size);
221 }
222 EXPECT_NEAR(GetAspectRatio(position_rect[1]), GetAspectRatio(uv_rect[1]),
223 0.001)
224 << i;
225 }
226 }
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, HostBuffer &data_host_buffer, GlyphAtlas::Type type, Rational scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::shared_ptr< TextFrame > &frame)
Definition: typographer_unittests.cc:32

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [582/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleComputeVertexData |
| ) |  |

Definition at line 110 of file text_contents_unittests.cc.

110 {
111 #ifndef FML_OS_MACOSX
112 GTEST_SKIP() << "Results aren't stable across linux and macos.";
113 #endif
114
115 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
116
117 std::shared_ptr<TextFrame> text_frame =
118 MakeTextFrame("1", "ahem.ttf", TextOptions{.font_size = 50});
119
120 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
121 std::shared_ptr<GlyphAtlasContext> atlas_context =
122 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
123 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
124 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
125 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
126 ASSERT_TRUE(context && context->IsValid());
127 std::shared_ptr<GlyphAtlas> atlas =
128 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
129 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1, 1),
130 atlas_context, text_frame, /*offset=*/{0, 0});
131
132 ISize texture_size = atlas->GetTexture()->GetSize();
133 TextContents::ComputeVertexData(data.data(), text_frame, /*scale=*/1.0,
134 /*entity_transform=*/Matrix(),
135 /*offset=*/Vector2(0, 0),
136 /*glyph_properties=*/std::nullopt, atlas);
137
138 Rect position_rect = PerVertexDataPositionToRect(data.begin());
139 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
140 // The -1 offset comes from Skia in `ComputeGlyphSize`. So since the font size
141 // is 50, the math appears to be to get back a 50x50 rect and apply 1 pixel
142 // of padding.
143 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
144 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
145 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [583/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleComputeVertexData2x |
| ) |  |

Definition at line 147 of file text_contents_unittests.cc.

147 {
148 #ifndef FML_OS_MACOSX
149 GTEST_SKIP() << "Results aren't stable across linux and macos.";
150 #endif
151
152 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
153 std::shared_ptr<TextFrame> text_frame =
154 MakeTextFrame("1", "ahem.ttf", TextOptions{.font_size = 50});
155
156 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
157 std::shared_ptr<GlyphAtlasContext> atlas_context =
158 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
159 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
160 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
161 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
162 ASSERT_TRUE(context && context->IsValid());
163 Rational font_scale(2, 1);
164 std::shared_ptr<GlyphAtlas> atlas =
165 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
166 GlyphAtlas::Type::kAlphaBitmap, font_scale,
167 atlas_context, text_frame, /*offset=*/{0, 0});
168
169 ISize texture_size = atlas->GetTexture()->GetSize();
170 TextContents::ComputeVertexData(
171 data.data(), text_frame, static_cast<Scalar>(font_scale),
172 /*entity_transform=*/
173 Matrix::MakeScale({static_cast<Scalar>(font_scale),
174 static_cast<Scalar>(font_scale), 1}),
175 /*offset=*/Vector2(0, 0),
176 /*glyph_properties=*/std::nullopt, atlas);
177
178 Rect position_rect = PerVertexDataPositionToRect(data.begin());
179 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
180 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -81, 102, 102));
181 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 102, 102));
182 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [584/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel |
| ) |  |

Definition at line 228 of file text_contents_unittests.cc.

228 {
229 #ifndef FML_OS_MACOSX
230 GTEST_SKIP() << "Results aren't stable across linux and macos.";
231 #endif
232
233 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
234
235 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
236 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
237
238 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
239 std::shared_ptr<GlyphAtlasContext> atlas_context =
240 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
241 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
242 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
243 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
244 ASSERT_TRUE(context && context->IsValid());
245 Point offset = Point(0.5, 0);
246 std::shared_ptr<GlyphAtlas> atlas =
247 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
248 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
249 atlas_context, text_frame, offset);
250
251 ISize texture_size = atlas->GetTexture()->GetSize();
252 TextContents::ComputeVertexData(
253 data.data(), text_frame, /*scale=*/1.0,
254 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
255 /*glyph_properties=*/std::nullopt, atlas);
256
257 Rect position_rect = PerVertexDataPositionToRect(data.begin());
258 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
259 // The values at Point(0, 0).
260 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
261 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
262 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
263 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
264 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [585/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel26 |
| ) |  |

Definition at line 311 of file text_contents_unittests.cc.

311 {
312 #ifndef FML_OS_MACOSX
313 GTEST_SKIP() << "Results aren't stable across linux and macos.";
314 #endif
315
316 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
317
318 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
319 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
320
321 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
322 std::shared_ptr<GlyphAtlasContext> atlas_context =
323 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
324 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
325 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
326 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
327 ASSERT_TRUE(context && context->IsValid());
328 Point offset = Point(0.26, 0);
329 std::shared_ptr<GlyphAtlas> atlas =
330 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
331 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
332 atlas_context, text_frame, offset);
333
334 ISize texture_size = atlas->GetTexture()->GetSize();
335 TextContents::ComputeVertexData(
336 data.data(), text_frame, /*scale=*/1.0,
337 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
338 /*glyph_properties=*/std::nullopt, atlas);
339
340 Rect position_rect = PerVertexDataPositionToRect(data.begin());
341 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
342 // The values without subpixel.
343 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
344 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
345 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
346 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
347 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [586/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel3x |
| ) |  |

Definition at line 266 of file text_contents_unittests.cc.

266 {
267 #ifndef FML_OS_MACOSX
268 GTEST_SKIP() << "Results aren't stable across linux and macos.";
269 #endif
270
271 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
272
273 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
274 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
275
276 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
277 std::shared_ptr<GlyphAtlasContext> atlas_context =
278 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
279 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
280 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
281 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
282 ASSERT_TRUE(context && context->IsValid());
283 Rational font_scale(3, 1);
284 Point offset = {0.16667, 0};
285 std::shared_ptr<GlyphAtlas> atlas =
286 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
287 GlyphAtlas::Type::kAlphaBitmap, font_scale,
288 atlas_context, text_frame, offset);
289
290 ISize texture_size = atlas->GetTexture()->GetSize();
291 TextContents::ComputeVertexData(
292 data.data(), text_frame, static_cast<Scalar>(font_scale),
293 /*entity_transform=*/
294 Matrix::MakeTranslation(offset) *
295 Matrix::MakeScale({static_cast<Scalar>(font_scale),
296 static_cast<Scalar>(font_scale), 1}),
297 offset,
298 /*glyph_properties=*/std::nullopt, atlas);
299
300 Rect position_rect = PerVertexDataPositionToRect(data.begin());
301 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
302 // Values at Point(0, 0)
303 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -121, 152, 152));
304 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 152, 152));
305 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -121, 154, 152))
306 << "position size:" << position_rect.GetSize();
307 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 154, 152))
308 << "position size:" << position_rect.GetSize();
309 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::TRect< T >::GetSize(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [587/603]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel80 |
| ) |  |

Definition at line 349 of file text_contents_unittests.cc.

349 {
350 #ifndef FML_OS_MACOSX
351 GTEST_SKIP() << "Results aren't stable across linux and macos.";
352 #endif
353
354 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
355
356 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
357 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
358
359 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
360 std::shared_ptr<GlyphAtlasContext> atlas_context =
361 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
362 std::shared_ptr<HostBuffer> data_host_buffer = HostBuffer::Create(
363 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
364 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
365 ASSERT_TRUE(context && context->IsValid());
366 Point offset = Point(0.80, 0);
367 std::shared_ptr<GlyphAtlas> atlas =
368 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
369 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
370 atlas_context, text_frame, offset);
371
372 ISize texture_size = atlas->GetTexture()->GetSize();
373 TextContents::ComputeVertexData(
374 data.data(), text_frame, /*scale=*/1.0,
375 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
376 /*glyph_properties=*/std::nullopt, atlas);
377
378 Rect position_rect = PerVertexDataPositionToRect(data.begin());
379 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
380 // The values without subpixel.
381 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
382 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
383 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
384 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
385 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [588/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanConvertTextBlob |
| ) |  |

Definition at line 62 of file typographer_unittests.cc.

62 {
63 SkFont font = flutter::testing::CreateTestFontOfSize(12);
64 auto blob = SkTextBlob::MakeFromString(
65 "the quick brown fox jumped over the lazy dog.", font);
66 ASSERT_TRUE(blob);
67 auto frame = MakeTextFrameFromTextBlobSkia(blob);
68 ASSERT_EQ(frame->GetRunCount(), 1u);
69 for (const auto& run : frame->GetRuns()) {
70 ASSERT_TRUE(run.IsValid());
71 ASSERT_EQ(run.GetGlyphCount(), 45u);
72 }
73 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [589/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateGlyphAtlas |
| ) |  |

Definition at line 80 of file typographer_unittests.cc.

80 {
81 auto context = TypographerContextSkia::Make();
82 auto atlas_context =
83 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
84 auto data_host_buffer = HostBuffer::Create(
85 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
86 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
87 ASSERT_TRUE(context && context->IsValid());
88 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
89 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
90 ASSERT_TRUE(blob);
91 auto atlas =
92 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
93 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
94 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
95
96 ASSERT_NE(atlas, nullptr);
97 ASSERT_NE(atlas->GetTexture(), nullptr);
98 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
99 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
100
101 std::optional<impeller::ScaledFont> first_scaled_font;
102 std::optional<impeller::SubpixelGlyph> first_glyph;
103 Rect first_rect;
104 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
105 const SubpixelGlyph& glyph,
106 const Rect& rect) -> bool {
107 first_scaled_font = scaled_font;
108 first_glyph = glyph;
109 first_rect = rect;
110 return false;
111 });
112
113 ASSERT_TRUE(first_scaled_font.has_value());
114 ASSERT_TRUE(atlas
115 ->FindFontGlyphBounds(
116 {first_scaled_font.value(), first_glyph.value()})
117 .has_value());
118 }
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, HostBuffer &data_host_buffer, GlyphAtlas::Type type, Rational scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< std::shared_ptr< TextFrame >> &frames, const std::vector< std::optional< GlyphProperties >> &properties)
Definition: typographer_unittests.cc:45

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [590/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateRenderContext |
| ) |  |

Definition at line 75 of file typographer_unittests.cc.

75 {
76 auto context = TypographerContextSkia::Make();
77 ASSERT_TRUE(context && context->IsValid());
78 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [591/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 183 of file typographer_unittests.cc.

183 {
184 auto context = TypographerContextSkia::Make();
185 auto atlas_context =
186 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
187 auto data_host_buffer = HostBuffer::Create(
188 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
189 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
190 ASSERT_TRUE(context && context->IsValid());
191 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
192 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
193 ASSERT_TRUE(blob);
194 auto atlas =
195 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
196 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
197 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
198 ASSERT_NE(atlas, nullptr);
199 ASSERT_NE(atlas->GetTexture(), nullptr);
200 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
201
202 // now attempt to re-create an atlas with the same text blob.
203
204 auto next_atlas =
205 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
206 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
207 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
208 ASSERT_EQ(atlas, next_atlas);
209 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
210 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [592/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 262 of file typographer_unittests.cc.

262 {
263 auto data_host_buffer = HostBuffer::Create(
264 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
265 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
266 auto context = TypographerContextSkia::Make();
267 auto atlas_context =
268 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
269 ASSERT_TRUE(context && context->IsValid());
270 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
271 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
272 ASSERT_TRUE(blob);
273 auto atlas =
274 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
275 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
276 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
277 auto old_packer = atlas_context->GetRectPacker();
278
279 ASSERT_NE(atlas, nullptr);
280 ASSERT_NE(atlas->GetTexture(), nullptr);
281 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
282
283 auto* first_texture = atlas->GetTexture().get();
284
285 // Now create a new glyph atlas with a nearly identical blob.
286
287 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
288 auto next_atlas =
289 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
290 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
291 atlas_context, MakeTextFrameFromTextBlobSkia(blob2));
292 ASSERT_EQ(atlas, next_atlas);
293 auto* second_texture = next_atlas->GetTexture().get();
294
295 auto new_packer = atlas_context->GetRectPacker();
296
297 ASSERT_EQ(second_texture, first_texture);
298 ASSERT_EQ(old_packer, new_packer);
299 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [593/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureWillGrowTilMaxTextureSize |
| ) |  |

Definition at line 434 of file typographer_unittests.cc.

434 {
435 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
436 GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
437 }
438
439 auto data_host_buffer = HostBuffer::Create(
440 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
441 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
442 auto context = TypographerContextSkia::Make();
443 auto atlas_context =
444 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
445 ASSERT_TRUE(context && context->IsValid());
446 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
447 auto blob = SkTextBlob::MakeFromString("A", sk_font);
448 ASSERT_TRUE(blob);
449 auto atlas =
450 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
451 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
452 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
453 // Continually append new glyphs until the glyph size grows to the maximum.
454 // Note that the sizes here are more or less experimentally determined, but
455 // the important expectation is that the atlas size will shrink again after
456 // growing to the maximum size.
457 constexpr ISize expected_sizes[13] = {
458 {4096, 4096}, //
459 {4096, 4096}, //
460 {4096, 8192}, //
461 {4096, 8192}, //
462 {4096, 8192}, //
463 {4096, 8192}, //
464 {4096, 16384}, //
465 {4096, 16384}, //
466 {4096, 16384}, //
467 {4096, 16384}, //
468 {4096, 16384}, //
469 {4096, 16384}, //
470 {4096, 4096} // Shrinks!
471 };
472
473 SkFont sk_font_small = flutter::testing::CreateTestFontOfSize(10);
474
475 for (int i = 0; i < 13; i++) {
476 SkTextBlobBuilder builder;
477
478 auto add_char = [&](const SkFont& sk_font, char c) {
479 int count = sk_font.countText(&c, 1, SkTextEncoding::kUTF8);
480 auto buffer = builder.allocRunPos(sk_font, count);
481 sk_font.textToGlyphs(&c, 1, SkTextEncoding::kUTF8,
482 {buffer.glyphs, count});
483 sk_font.getPos({buffer.glyphs, count}, {buffer.points(), count},
484 {0, 0} /*=origin*/);
485 };
486
487 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
488 add_char(sk_font, 'A');
489 add_char(sk_font_small, 'B');
490 auto blob = builder.make();
491
492 atlas =
493 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
494 GlyphAtlas::Type::kAlphaBitmap, Rational(50 + i, 1),
495 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
496 ASSERT_TRUE(!!atlas);
497 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
498 expected_sizes[i]);
499 }
500
501 // The final atlas should contain both the "A" glyph (which was not present
502 // in the previous atlas) and the "B" glyph (which existed in the previous
503 // atlas).
504 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
505 }

References c, impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [594/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 212 of file typographer_unittests.cc.

212 {
213 auto data_host_buffer = HostBuffer::Create(
214 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
215 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
216 auto context = TypographerContextSkia::Make();
217 auto atlas_context =
218 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
219 ASSERT_TRUE(context && context->IsValid());
220
221 const char* test_string =
222 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
223 "2134567890-=!@#$%^&*()_+"
224 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
225 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
226
227 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
228 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
229 ASSERT_TRUE(blob);
230
231 size_t size_count = 8;
232 std::vector<std::shared_ptr<TextFrame>> frames;
233 for (size_t index = 0; index < size_count; index += 1) {
234 frames.push_back(MakeTextFrameFromTextBlobSkia(blob));
235 frames.back()->SetPerFrameData(Rational(6 * index, 10), {0, 0}, Matrix(),
236 {});
237 };
238 auto atlas =
239 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
240 *data_host_buffer, atlas_context, frames);
241 ASSERT_NE(atlas, nullptr);
242 ASSERT_NE(atlas->GetTexture(), nullptr);
243
244 std::set<uint16_t> unique_glyphs;
245 std::vector<uint16_t> total_glyphs;
246 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
247 const SubpixelGlyph& glyph, const Rect& rect) {
248 unique_glyphs.insert(glyph.glyph.index);
249 total_glyphs.push_back(glyph.glyph.index);
250 return true;
251 });
252
253 // These numbers may be different due to subpixel positions.
254 EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
255 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
256
257 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
258 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
259 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
260 }

References impeller::HostBuffer::Create(), impeller::SubpixelGlyph::glyph, impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [595/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithOddUniqueGlyphSize |
| ) |  |

Definition at line 161 of file typographer_unittests.cc.

161 {
162 auto context = TypographerContextSkia::Make();
163 auto atlas_context =
164 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
165 auto data_host_buffer = HostBuffer::Create(
166 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
167 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
168 ASSERT_TRUE(context && context->IsValid());
169 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
170 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
171 ASSERT_TRUE(blob);
172 auto atlas =
173 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
174 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
175 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
176 ASSERT_NE(atlas, nullptr);
177 ASSERT_NE(atlas->GetTexture(), nullptr);
178
179 EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
180 EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
181 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [596/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsIgnoredForNonEmojiFonts |
| ) |  |

Definition at line 337 of file typographer_unittests.cc.

337 {
338 auto data_host_buffer = HostBuffer::Create(
339 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
340 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
341 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
342 sk_sp<SkTypeface> typeface =
343 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
344 SkFont sk_font(typeface, 0.5f);
345
346 auto context = TypographerContextSkia::Make();
347 auto atlas_context =
348 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
349
350 // Create two frames with the same character and a different color, but as a
351 // non-emoji font the text frame constructor will ignore it.
352 auto frame =
353 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
354 auto frame_2 =
355 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
356 std::vector<std::optional<GlyphProperties>> properties = {
357 GlyphProperties{},
358 GlyphProperties{},
359 };
360
361 auto next_atlas =
362 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
363 GlyphAtlas::Type::kColorBitmap, Rational(1),
364 atlas_context, {frame, frame_2}, properties);
365
366 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
367 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [597/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsPartOfCacheKey |
| ) |  |

Definition at line 301 of file typographer_unittests.cc.

301 {
302 auto data_host_buffer = HostBuffer::Create(
303 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
304 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
305 #if FML_OS_MACOSX
306 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
307 #else
308 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
309 #endif
310 ASSERT_TRUE(mapping);
311 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
312 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
313
314 auto context = TypographerContextSkia::Make();
315 auto atlas_context =
316 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
317
318 // Create two frames with the same character and a different color, expect
319 // that it adds a character.
320 auto frame = MakeTextFrameFromTextBlobSkia(
321 SkTextBlob::MakeFromString("😂", emoji_font));
322 auto frame_2 = MakeTextFrameFromTextBlobSkia(
323 SkTextBlob::MakeFromString("😂", emoji_font));
324 std::vector<std::optional<GlyphProperties>> properties = {
325 GlyphProperties{.color = Color::Red()},
326 GlyphProperties{.color = Color::Blue()},
327 };
328
329 auto next_atlas =
330 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
331 GlyphAtlas::Type::kColorBitmap, Rational(1),
332 atlas_context, {frame, frame_2}, properties);
333
334 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
335 }

References impeller::Color::Blue(), impeller::GlyphProperties::color, impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), impeller::MakeTextFrameFromTextBlobSkia(), and impeller::Color::Red().

## ◆ TEST_P() [598/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | InvalidAtlasForcesRepopulation |
| ) |  |

Definition at line 630 of file typographer_unittests.cc.

630 {
631 SkFont font = flutter::testing::CreateTestFontOfSize(12);
632 auto blob = SkTextBlob::MakeFromString(
633 "the quick brown fox jumped over the lazy dog.", font);
634 ASSERT_TRUE(blob);
635 auto frame = MakeTextFrameFromTextBlobSkia(blob);
636
637 EXPECT_FALSE(frame->IsFrameComplete());
638
639 auto context = TypographerContextSkia::Make();
640 auto atlas_context =
641 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
642 auto data_host_buffer = HostBuffer::Create(
643 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
644 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
645
646 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
647 GlyphAtlas::Type::kAlphaBitmap,
648 /*scale=*/Rational(1), atlas_context, frame);
649
650 // The glyph position in the atlas was not known when this value
651 // was recorded. It is marked as a placeholder.
652 EXPECT_TRUE(frame->IsFrameComplete());
653 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
654 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
655 // OpenGLES must always increase the atlas backend if the texture grows.
656 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
657 } else {
658 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
659 }
660
661 auto second_context = TypographerContextSkia::Make();
662 auto second_atlas_context =
663 second_context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
664
665 EXPECT_FALSE(second_atlas_context->GetGlyphAtlas()->IsValid());
666
667 atlas = CreateGlyphAtlas(*GetContext(), second_context.get(),
668 *data_host_buffer, GlyphAtlas::Type::kAlphaBitmap,
669 /*scale=*/Rational(1), second_atlas_context, frame);
670
671 EXPECT_TRUE(second_atlas_context->GetGlyphAtlas()->IsValid());
672 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [599/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 120 of file typographer_unittests.cc.

120 {
121 auto data_host_buffer = HostBuffer::Create(
122 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
123 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
124 #if FML_OS_MACOSX
125 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
126 #else
127 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
128 #endif
129 ASSERT_TRUE(mapping);
130 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
131 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
132 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
133
134 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
135 ASSERT_TRUE(blob);
136 auto frame = MakeTextFrameFromTextBlobSkia(blob);
137
138 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
139
140 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
141
142 lazy_atlas.AddTextFrame(frame, Rational(1), {0, 0}, Matrix(), {});
143
144 frame = MakeTextFrameFromTextBlobSkia(
145 SkTextBlob::MakeFromString("😀 ", emoji_font));
146
147 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
148
149 lazy_atlas.AddTextFrame(frame, Rational(1), {0, 0}, Matrix(), {});
150
151 // Creates different atlases for color and red bitmap.
152 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
153 *GetContext(), *data_host_buffer, GlyphAtlas::Type::kColorBitmap);
154
155 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
156 *GetContext(), *data_host_buffer, GlyphAtlas::Type::kAlphaBitmap);
157
158 ASSERT_FALSE(color_atlas == bitmap_atlas);
159 }

References impeller::LazyGlyphAtlas::AddTextFrame(), impeller::HostBuffer::Create(), impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [600/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 369 of file typographer_unittests.cc.

369 {
370 auto packer = RectanglePacker::Factory(200, 100);
371 ASSERT_NE(packer, nullptr);
372 ASSERT_EQ(packer->PercentFull(), 0);
373
374 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
375
376 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
377 ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
378 // Make sure the rectangle is placed such that it is inside the bounds of
379 // the packer's area.
380 const SkIRect first_rect =
381 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
382 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
383
384 // Initial area was 200 x 100 = 20_000
385 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
386 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.02));
387
388 IPoint16 second_output = {-1, -1};
389 ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
390 const SkIRect second_rect =
391 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
392 // Make sure the rectangle is placed such that it is inside the bounds of
393 // the packer's area but not in the are of the first rectangle.
394 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
395 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
396
397 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
398 // 13_000 / 20_000 == 0.65 == 65%
399 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
400
401 // There's enough area to add this rectangle, but no space big enough for
402 // the 50 units of width.
403 IPoint16 output;
404 ASSERT_FALSE(packer->AddRect(50, 50, &output));
405 // Should be unchanged.
406 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
407
408 packer->Reset();
409 // Should be empty now.
410 ASSERT_EQ(packer->PercentFull(), 0);
411 }
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18

References impeller::RectanglePacker::Factory(), NumberNear(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST_P() [601/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameAtlasGenerationTracksState |
| ) |  |

Definition at line 577 of file typographer_unittests.cc.

577 {
578 SkFont font = flutter::testing::CreateTestFontOfSize(12);
579 auto blob = SkTextBlob::MakeFromString(
580 "the quick brown fox jumped over the lazy dog.", font);
581 ASSERT_TRUE(blob);
582 auto frame = MakeTextFrameFromTextBlobSkia(blob);
583
584 EXPECT_FALSE(frame->IsFrameComplete());
585
586 auto context = TypographerContextSkia::Make();
587 auto atlas_context =
588 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
589 auto data_host_buffer = HostBuffer::Create(
590 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
591 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
592
593 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
594 GlyphAtlas::Type::kAlphaBitmap,
595 /*scale=*/Rational(1), atlas_context, frame);
596
597 // The glyph position in the atlas was not known when this value
598 // was recorded. It is marked as a placeholder.
599 EXPECT_TRUE(frame->IsFrameComplete());
600 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
601 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
602 // OpenGLES must always increase the atlas backend if the texture grows.
603 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
604 } else {
605 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
606 }
607
608 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
609 GlyphAtlas::Type::kAlphaBitmap,
610 /*scale=*/Rational(1), atlas_context, frame);
611
612 // The second time the glyph is rendered, the bounds are correcly known.
613 EXPECT_TRUE(frame->IsFrameComplete());
614 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
615 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
616 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
617 } else {
618 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
619 }
620
621 // Force increase the generation.
622 atlas_context->GetGlyphAtlas()->SetAtlasGeneration(2u);
623 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
624 GlyphAtlas::Type::kAlphaBitmap,
625 /*scale=*/Rational(1), atlas_context, frame);
626
627 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 2u);
628 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [602/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInitialBoundsArePlaceholder |
| ) |  |

Definition at line 507 of file typographer_unittests.cc.

507 {
508 SkFont font = flutter::testing::CreateTestFontOfSize(12);
509 auto blob = SkTextBlob::MakeFromString(
510 "the quick brown fox jumped over the lazy dog.", font);
511 ASSERT_TRUE(blob);
512 auto frame = MakeTextFrameFromTextBlobSkia(blob);
513
514 EXPECT_FALSE(frame->IsFrameComplete());
515
516 auto context = TypographerContextSkia::Make();
517 auto atlas_context =
518 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
519 auto data_host_buffer = HostBuffer::Create(
520 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
521 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
522
523 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
524 GlyphAtlas::Type::kAlphaBitmap,
525 /*scale=*/Rational(1), atlas_context, frame);
526
527 // The glyph position in the atlas was not known when this value
528 // was recorded. It is marked as a placeholder.
529 EXPECT_TRUE(frame->IsFrameComplete());
530 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
531
532 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
533 GlyphAtlas::Type::kAlphaBitmap,
534 /*scale=*/Rational(1), atlas_context, frame);
535
536 // The second time the glyph is rendered, the bounds are correcly known.
537 EXPECT_TRUE(frame->IsFrameComplete());
538 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
539 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [603/603]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInvalidationWithScale |
| ) |  |

Definition at line 541 of file typographer_unittests.cc.

541 {
542 SkFont font = flutter::testing::CreateTestFontOfSize(12);
543 auto blob = SkTextBlob::MakeFromString(
544 "the quick brown fox jumped over the lazy dog.", font);
545 ASSERT_TRUE(blob);
546 auto frame = MakeTextFrameFromTextBlobSkia(blob);
547
548 EXPECT_FALSE(frame->IsFrameComplete());
549
550 auto context = TypographerContextSkia::Make();
551 auto atlas_context =
552 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
553 auto data_host_buffer = HostBuffer::Create(
554 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
555 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
556
557 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
558 GlyphAtlas::Type::kAlphaBitmap,
559 /*scale=*/Rational(1), atlas_context, frame);
560
561 // The glyph position in the atlas was not known when this value
562 // was recorded. It is marked as a placeholder.
563 EXPECT_TRUE(frame->IsFrameComplete());
564 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
565
566 // Change the scale and the glyph data will still be a placeholder, as the
567 // old data is no longer valid.
568 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
569 GlyphAtlas::Type::kAlphaBitmap,
570 /*scale=*/Rational(2), atlas_context, frame);
571
572 // The second time the glyph is rendered, the bounds are correcly known.
573 EXPECT_TRUE(frame->IsFrameComplete());
574 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
575 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ toColor()

flutter::DlColor impeller::testing::toColor | ( | const float * | components | ) |

Definition at line 39 of file dl_unittests.cc.

39 {
40 return flutter::DlColor(Color::ToIColor(
41 Color(components[0], components[1], components[2], components[3])));
42 }

References impeller::Color::ToIColor().

Referenced by TEST_P().

## Variable Documentation

## ◆ golden_cubic_and_quad_points

std::vector<Point> impeller::testing::golden_cubic_and_quad_points

Definition at line 15 of file golden_paths.h.

## ◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
| static constexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 377 of file aiks_dl_text_unittests.cc.

Referenced by TEST_P().

## ◆ kMagicFailingAllocation

constexpr const size_t impeller::testing::kMagicFailingAllocation = 1024000 * 2
| static constexpr

Definition at line 191 of file host_buffer_unittests.cc.

Referenced by impeller::testing::FailingAllocator::OnCreateBuffer(), and TEST_P().

## ◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
| static

Definition at line 679 of file aiks_dl_blur_unittests.cc.