| 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
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 | DlPathReceiverMock = flutter::testing::DlPathReceiverMock
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 | 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, FilledEllipsesRenderCorrectly)
| TEST_P (AiksTest, FilledArcsRenderCorrectly)
| TEST_P (AiksTest, FilledArcsRenderCorrectlyWithCenter)
| TEST_P (AiksTest, NonSquareFilledArcsRenderCorrectly)
| TEST_P (AiksTest, NonSquareFilledArcsRenderCorrectlyWithCenter)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithButtEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithSquareEnds)
| TEST_P (AiksTest, StrokedArcsRenderCorrectlyWithRoundEnds)
| 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)
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, CanRenderClippedBlur)
| 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)
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, 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, CanDrawNinePatchImage)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCornersScaledDown)
| TEST_P (DisplayListTest, NinePatchImagePrecision)
| 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, 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, FailOnValidationError)
| TEST_P (EntityTest, CanComputeGeometryForEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, CanRenderEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, DrawSuperEllipse)
| TEST_P (EntityTest, DrawRoundSuperEllipse)
| 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_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 (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, TransformAndClipBounds)
| 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 (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_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 (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 (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, 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 (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)
| TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
| TEST (TessellatorTest, TessellateConvex)
| TEST (TessellatorTest, TessellateConvexUnclosedPath)
| TEST (TessellatorTest, CircleVertexCounts)
| TEST (TessellatorTest, FilledCircleTessellationVertices)
| TEST (TessellatorTest, StrokedCircleTessellationVertices)
| 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 21 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.

## ◆ DlPathReceiverMock

using impeller::testing::DlPathReceiverMock = typedef flutter::testing::DlPathReceiverMock

Definition at line 19 of file path_source_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 26 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.

## ◆ 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:68

References data.

Referenced by TEST_P().

## ◆ 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 15 of file shader_archive_unittests.cc.

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

Referenced by TEST().

## ◆ CreateStringFromMapping()

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

Definition at line 23 of file shader_archive_unittests.cc.

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

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 26 of file canvas_unittests.cc.

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

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 1658 of file entity_unittests.cc.

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

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

507 {
508 DisplayListBuilder builder;
509 builder.Scale(test_context.GetContentScale().x,
510 test_context.GetContentScale().y);
511 builder.Scale(0.8f, 0.8f);
512 builder.Translate(50.f, 50.f);
513
514 DlPaint draw_paint;
515 draw_paint.setColor(
516 DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
517 Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
518 builder.DrawPaint(draw_paint);
519
520 DlPaint paint;
521 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
522 paint.setInvertColors(config.invert_colors);
523 paint.setImageFilter(config.image_filter);
524 paint.setBlendMode(config.blend_mode);
525
526 const Scalar x = 50;
527 const Scalar radius = 20.0f;
528 const Scalar y_spacing = 100.0f;
529 Scalar alpha = config.alpha * 255;
530
531 Scalar y = 50;
532 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
533 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
534 radius, 60.0f - radius),
535 paint);
536
537 y += y_spacing;
538 paint.setColor(DlColor::kBlue().withAlpha(alpha));
539 builder.DrawCircle(DlPoint{x + 25, y + 25}, radius, paint);
540
541 y += y_spacing;
542 paint.setColor(DlColor::kGreen().withAlpha(alpha));
543 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
544 radius, 60.0f - radius),
545 paint);
546
547 y += y_spacing;
548 paint.setColor(DlColor::kPurple().withAlpha(alpha));
549 DlRoundRect rrect = DlRoundRect::MakeRectXY(
550 DlRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
551 builder.DrawRoundRect(rrect, paint);
552
553 y += y_spacing;
554 paint.setColor(DlColor::kOrange().withAlpha(alpha));
555
556 rrect = DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
557 radius, 5.0);
558 builder.DrawRoundRect(rrect, paint);
559
560 y += y_spacing;
561 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
562
563 {
564 DlPathBuilder path_builder;
565 path_builder.MoveTo(DlPoint(x + 0, y + 60));
566 path_builder.LineTo(DlPoint(x + 30, y + 0));
567 path_builder.LineTo(DlPoint(x + 60, y + 60));
568 path_builder.Close();
569
570 builder.DrawPath(path_builder.TakePath(), paint);
571 }
572
573 y += y_spacing;
574 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
575 {
576 DlPath path = DlPath::MakeArc(Rect::MakeXYWH(x + 5, y, 50, 50), //
577 Degrees(90), Degrees(180), false) +
578 DlPath::MakeArc(Rect::MakeXYWH(x + 25, y, 50, 50), //
579 Degrees(90), Degrees(180), false);
580 builder.DrawPath(path, paint);
581 }
582
583 return builder.Build();
584 }
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 68 of file entity_unittests.cc.

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

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 45 of file aiks_dl_text_unittests.cc.

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

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

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

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/525]

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:76
impeller::MebiBytes
AllocationSize< 1 '024u *1 '024u > MebiBytes
Definition: allocation_size.h:158
impeller::Bytes
AllocationSize< 1u > Bytes
Definition: allocation_size.h:151
impeller::KiloBytes
AllocationSize< 1 '000u > KiloBytes
Definition: allocation_size.h:153

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

## ◆ TEST() [2/525]

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/525]

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/525]

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:159
impeller::GigaBytes
AllocationSize< 1 '000u *1 '000u *1 '000u > GigaBytes
Definition: allocation_size.h:155
impeller::KibiBytes
AllocationSize< 1 '024u > KibiBytes
Definition: allocation_size.h:157
impeller::MegaBytes
AllocationSize< 1 '000u *1 '000u > MegaBytes
Definition: allocation_size.h:154

References e3.

## ◆ TEST() [5/525]

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/525]

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/525]

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/525]

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/525]

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 }

References impeller::saturated::b.

## ◆ TEST() [10/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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

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

## ◆ TEST() [16/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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 = 0}}};
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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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

Definition at line 166 of file driver_info_vk_unittests.cc.

166 {
167 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 620"));
168 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 610"));
169 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 530"));
170 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 512"));
171 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 509"));
172 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 508"));
173 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 506"));
174 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 505"));
175 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 504"));
176 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 630"));
177 EXPECT_FALSE(IsBadVersionTest("Adreno (TM) 640"));
178 EXPECT_FALSE(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/525]

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/525]

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

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

## ◆ TEST() [93/525]

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

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

## ◆ TEST() [94/525]

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

Definition at line 186 of file driver_info_vk_unittests.cc.

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

References IsBadVersionTest().

## ◆ TEST() [95/525]

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/525]

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/525]

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/525]

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/525]

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

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

## ◆ TEST() [100/525]

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

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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(), 80u);
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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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:292
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/525]

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

Definition at line 458 of file gaussian_blur_filter_contents_unittests.cc.

458 {
459 Scalar sigma = 1.0;
460 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
461 GaussianBlurFilterContents::ScaleSigma(sigma));
462 fml::StatusOr<Scalar> derived_sigma =
463 CalculateSigmaForBlurRadius(radius, Matrix());
464 ASSERT_TRUE(derived_sigma.ok());
465 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
466 }

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

## ◆ TEST() [147/525]

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

Definition at line 225 of file gaussian_blur_filter_contents_unittests.cc.

225 {
226 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
227 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
228 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
229 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
230 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
231 // Hang on to 1/8 as long as possible.
232 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
233 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
234 // Downsample clamped to 1/16th.
235 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
236 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [148/525]

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

Definition at line 621 of file gaussian_blur_filter_contents_unittests.cc.

621 {
622 Scalar sigma = 30.5f;
623 int32_t blur_radius = static_cast<int32_t>(
624 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
625 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
626 .blur_sigma = sigma,
627 .blur_radius = blur_radius,
628 .step_size = 1};
629 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
630 GaussianBlurPipeline::FragmentShader::KernelSamples frag_kernel_samples =
631 LerpHackKernelSamples(kernel_samples);
632 EXPECT_TRUE(frag_kernel_samples.sample_count <= kGaussianBlurMaxKernelSize);
633 }
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:84
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:912
impeller::LerpHackKernelSamples
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
Definition: gaussian_blur_filter_contents.cc:959

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

## ◆ TEST() [149/525]

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

Definition at line 468 of file gaussian_blur_filter_contents_unittests.cc.

468 {
469 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
470 .blur_sigma = 1,
471 .blur_radius = 5,
472 .step_size = 1};
473 KernelSamples samples = GenerateBlurInfo(parameters);
474 EXPECT_EQ(samples.sample_count, 11);
475
476 // Coefficients should add up to 1.
477 Scalar tally = 0;
478 for (int i = 0; i < samples.sample_count; ++i) {
479 tally += samples.samples[i].coefficient;
480 }
481 EXPECT_FLOAT_EQ(tally, 1.0f);
482
483 // Verify the shape of the curve.
484 for (int i = 0; i < 4; ++i) {
485 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
486 samples.samples[10 - i].coefficient);
487 EXPECT_TRUE(samples.samples[i + 1].coefficient >
488 samples.samples[i].coefficient);
489 }
490 }

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

## ◆ TEST() [150/525]

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

Definition at line 121 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [151/525]

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

Definition at line 132 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [152/525]

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

Definition at line 145 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [153/525]

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 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
117 EXPECT_EQ(contents.GetSigmaX(), 0.0);
118 EXPECT_EQ(contents.GetSigmaY(), 0.0);
119 }

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

## ◆ TEST() [154/525]

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

Definition at line 208 of file gaussian_blur_filter_contents_unittests.cc.

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

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

## ◆ TEST() [155/525]

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

Definition at line 567 of file gaussian_blur_filter_contents_unittests.cc.

567 {
568 Scalar sigma = 10.0f;
569 int32_t blur_radius = static_cast<int32_t>(
570 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
571 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
572 .blur_sigma = sigma,
573 .blur_radius = blur_radius,
574 .step_size = 1};
575 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
576 EXPECT_EQ(kernel_samples.sample_count, 33);
577 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
578 LerpHackKernelSamples(kernel_samples);
579 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
580 float data[33];
581 srand(0);
582 for (int i = 0; i < 33; i++) {
583 data[i] = 255.0 * static_cast<double>(IMPELLER_RAND()) / RAND_MAX;
584 }
585
586 auto sampler = [data](Point point) -> Scalar {
587 FML_CHECK(point.y == 0.0f);
588 FML_CHECK(point.x >= -16);
589 FML_CHECK(point.x <= 16);
590 Scalar fint_part;
591 Scalar fract = fabsf(modf(point.x, &fint_part));
592 if (fract == 0) {
593 int32_t int_part = static_cast<int32_t>(fint_part) + 16;
594 return data[int_part];
595 } else {
596 int32_t left = static_cast<int32_t>(floor(point.x)) + 16;
597 int32_t right = static_cast<int32_t>(ceil(point.x)) + 16;
598 if (point.x < 0) {
599 return fract * data[left] + (1.0 - fract) * data[right];
600 } else {
601 return (1.0 - fract) * data[left] + fract * data[right];
602 }
603 }
604 };
605
606 Scalar output = 0.0;
607 for (int i = 0; i < kernel_samples.sample_count; ++i) {
608 auto sample = kernel_samples.samples[i];
609 output += sample.coefficient * sampler(sample.uv_offset);
610 }
611
612 Scalar fast_output = 0.0;
613 for (int i = 0; i < fast_kernel_samples.sample_count; i++) {
614 fast_output += GetCoefficient(fast_kernel_samples.sample_data[i]) *
615 sampler(GetUVOffset(fast_kernel_samples.sample_data[i]));
616 }
617
618 EXPECT_NEAR(output, fast_output, 0.1);
619 }
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/525]

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

Definition at line 492 of file gaussian_blur_filter_contents_unittests.cc.

492 {
493 KernelSamples kernel_samples = {
494 .sample_count = 5,
495 .samples =
496 {
497 {
498 .uv_offset = Vector2(-2, 0),
499 .coefficient = 0.1f,
500 },
501 {
502 .uv_offset = Vector2(-1, 0),
503 .coefficient = 0.2f,
504 },
505 {
506 .uv_offset = Vector2(0, 0),
507 .coefficient = 0.4f,
508 },
509 {
510 .uv_offset = Vector2(1, 0),
511 .coefficient = 0.2f,
512 },
513 {
514 .uv_offset = Vector2(2, 0),
515 .coefficient = 0.1f,
516 },
517 },
518 };
519
520 GaussianBlurPipeline::FragmentShader::KernelSamples blur_info =
521 LerpHackKernelSamples(kernel_samples);
522 EXPECT_EQ(blur_info.sample_count, 3);
523
524 KernelSample* samples = kernel_samples.samples;
525
526 //////////////////////////////////////////////////////////////////////////////
527 // Check output kernel.
528
529 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[0]),
530 Point(-1.3333333, 0));
531 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[0]), 0.3);
532
533 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[1]), Point(0, 0));
534 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[1]), 0.4);
535
536 EXPECT_POINT_NEAR(GetUVOffset(blur_info.sample_data[2]), Point(1.333333, 0));
537 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[2]), 0.3);
538
539 //////////////////////////////////////////////////////////////////////////////
540 // Check output of fast kernel versus original kernel.
541
542 Scalar data[5] = {0.25, 0.5, 0.5, 1.0, 0.2};
543 Scalar original_output =
544 samples[0].coefficient * data[0] + samples[1].coefficient * data[1] +
545 samples[2].coefficient * data[2] + samples[3].coefficient * data[3] +
546 samples[4].coefficient * data[4];
547
548 auto lerp = [](const Point& point, Scalar left, Scalar right) {
549 Scalar int_part;
550 Scalar fract = fabsf(modf(point.x, &int_part));
551 if (point.x < 0) {
552 return left * fract + right * (1.0 - fract);
553 } else {
554 return left * (1.0 - fract) + right * fract;
555 }
556 };
557 Scalar fast_output =
558 /*1st*/ lerp(GetUVOffset(blur_info.sample_data[0]), data[0], data[1]) *
559 GetCoefficient(blur_info.sample_data[0]) +
560 /*2nd*/ data[2] * GetCoefficient(blur_info.sample_data[1]) +
561 /*3rd*/ lerp(GetUVOffset(blur_info.sample_data[2]), data[3], data[4]) *
562 GetCoefficient(blur_info.sample_data[2]);
563
564 EXPECT_NEAR(original_output, fast_output, 0.01);
565 }
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/525]

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/525]

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/525]

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

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

## ◆ TEST() [160/525]

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/525]

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 impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [162/525]

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 impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [163/525]

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 impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [164/525]

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 impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [165/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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

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

## ◆ TEST() [200/525]

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/525]

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/525]

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

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

## ◆ TEST() [203/525]

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 impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [204/525]

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

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

## ◆ TEST() [205/525]

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

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

## ◆ TEST() [206/525]

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

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

## ◆ TEST() [207/525]

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/525]

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

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

## ◆ TEST() [209/525]

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/525]

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

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

## ◆ TEST() [211/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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 impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [220/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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:214
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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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/525]

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() [270/525]

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() [271/525]

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() [272/525]

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() [273/525]

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() [274/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSource |
| ) |  |

Definition at line 157 of file path_source_unittests.cc.

157 {
158 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 5);
159
160 EXPECT_FALSE(source.IsConvex());
161 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
162 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
163
164 ::testing::StrictMock<DlPathReceiverMock> receiver;
165
166 {
167 ::testing::Sequence sequence;
168
169 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
170 EXPECT_CALL(receiver, LineTo(Point(15, 10)));
171 EXPECT_CALL(receiver, MoveTo(Point(20, 10), false));
172 EXPECT_CALL(receiver, LineTo(Point(25, 10)));
173 }
174
175 source.Dispatch(receiver);
176 }
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() [275/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceInvalidOffGaps |
| ) |  |

Definition at line 216 of file path_source_unittests.cc.

216 {
217 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, -1);
218
219 EXPECT_FALSE(source.IsConvex());
220 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
221 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
222
223 ::testing::StrictMock<DlPathReceiverMock> receiver;
224
225 {
226 ::testing::Sequence sequence;
227
228 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
229 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
230 }
231
232 source.Dispatch(receiver);
233 }

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() [276/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceInvalidOnRegion |
| ) |  |

Definition at line 235 of file path_source_unittests.cc.

235 {
236 DashedLinePathSource source(Point(10, 10), Point(30, 10), -1, 5);
237
238 EXPECT_FALSE(source.IsConvex());
239 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
240 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
241
242 ::testing::StrictMock<DlPathReceiverMock> receiver;
243
244 {
245 ::testing::Sequence sequence;
246
247 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
248 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
249 }
250
251 source.Dispatch(receiver);
252 }

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/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DashedLinePathSourceZeroOffGaps |
| ) |  |

Definition at line 197 of file path_source_unittests.cc.

197 {
198 DashedLinePathSource source(Point(10, 10), Point(30, 10), 5, 0);
199
200 EXPECT_FALSE(source.IsConvex());
201 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
202 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 30, 10));
203
204 ::testing::StrictMock<DlPathReceiverMock> receiver;
205
206 {
207 ::testing::Sequence sequence;
208
209 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
210 EXPECT_CALL(receiver, LineTo(Point(30, 10)));
211 }
212
213 source.Dispatch(receiver);
214 }

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/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | DiffRoundRectSourceTest |
| ) |  |

Definition at line 104 of file path_source_unittests.cc.

104 {
105 Rect outer_rect = Rect::MakeLTRB(10, 15, 200, 300);
106 Rect inner_rect = Rect::MakeLTRB(50, 60, 100, 200);
107 ASSERT_TRUE(outer_rect.Contains(inner_rect));
108 RoundingRadii radii = {
109 .top_left = Size(1, 11),
110 .top_right = Size(2, 12),
111 .bottom_left = Size(4, 14),
112 .bottom_right = Size(3, 13),
113 };
114 RoundRect outer_rrect = RoundRect::MakeRectRadii(outer_rect, radii);
115 RoundRect inner_rrect = RoundRect::MakeRectRadii(inner_rect, radii);
116 DiffRoundRectPathSource source(outer_rrect, inner_rrect);
117
118 EXPECT_FALSE(source.IsConvex());
119 EXPECT_EQ(source.GetFillType(), FillType::kOdd);
120 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 200, 300));
121
122 ::testing::StrictMock<DlPathReceiverMock> receiver;
123
124 {
125 ::testing::Sequence sequence;
126
127 EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
128 EXPECT_CALL(receiver, LineTo(Point(198, 15)));
129 EXPECT_CALL(receiver, ConicTo(Point(200, 15), Point(200, 27), kSqrt2Over2));
130 EXPECT_CALL(receiver, LineTo(Point(200, 287)));
131 EXPECT_CALL(receiver,
132 ConicTo(Point(200, 300), Point(197, 300), kSqrt2Over2));
133 EXPECT_CALL(receiver, LineTo(Point(14, 300)));
134 EXPECT_CALL(receiver, ConicTo(Point(10, 300), Point(10, 286), kSqrt2Over2));
135 EXPECT_CALL(receiver, LineTo(Point(10, 26)));
136 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
137 // RetiresOnSaturation keeps identical calls from matching each other
138 EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
139
140 EXPECT_CALL(receiver, MoveTo(Point(51, 60), true));
141 EXPECT_CALL(receiver, LineTo(Point(98, 60)));
142 EXPECT_CALL(receiver, ConicTo(Point(100, 60), Point(100, 72), kSqrt2Over2));
143 EXPECT_CALL(receiver, LineTo(Point(100, 187)));
144 EXPECT_CALL(receiver,
145 ConicTo(Point(100, 200), Point(97, 200), kSqrt2Over2));
146 EXPECT_CALL(receiver, LineTo(Point(54, 200)));
147 EXPECT_CALL(receiver, ConicTo(Point(50, 200), Point(50, 186), kSqrt2Over2));
148 EXPECT_CALL(receiver, LineTo(Point(50, 71)));
149 EXPECT_CALL(receiver, ConicTo(Point(50, 60), Point(51, 60), kSqrt2Over2));
150 // RetiresOnSaturation keeps identical calls from matching each other
151 EXPECT_CALL(receiver, Close()).RetiresOnSaturation();
152 }
153
154 source.Dispatch(receiver);
155 }
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() [279/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | EllipseSourceTest |
| ) |  |

Definition at line 45 of file path_source_unittests.cc.

45 {
46 Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
47 EllipsePathSource source(rect);
48
49 EXPECT_TRUE(source.IsConvex());
50 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
51 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
52
53 ::testing::StrictMock<DlPathReceiverMock> receiver;
54
55 {
56 ::testing::Sequence sequence;
57
58 EXPECT_CALL(receiver, MoveTo(Point(10, 22.5), true));
59 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(15, 15), kSqrt2Over2));
60 EXPECT_CALL(receiver, ConicTo(Point(20, 15), Point(20, 22.5), kSqrt2Over2));
61 EXPECT_CALL(receiver, ConicTo(Point(20, 30), Point(15, 30), kSqrt2Over2));
62 EXPECT_CALL(receiver, ConicTo(Point(10, 30), Point(10, 22.5), kSqrt2Over2));
63 EXPECT_CALL(receiver, Close());
64 }
65
66 source.Dispatch(receiver);
67 }

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() [280/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | EmptyDashedLinePathSource |
| ) |  |

Definition at line 178 of file path_source_unittests.cc.

178 {
179 DashedLinePathSource source(Point(10, 10), Point(10, 10), 5, 5);
180
181 EXPECT_FALSE(source.IsConvex());
182 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
183 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 10, 10, 10));
184
185 ::testing::StrictMock<DlPathReceiverMock> receiver;
186
187 {
188 ::testing::Sequence sequence;
189
190 EXPECT_CALL(receiver, MoveTo(Point(10, 10), false));
191 EXPECT_CALL(receiver, LineTo(Point(10, 10)));
192 }
193
194 source.Dispatch(receiver);
195 }

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() [281/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | RectSourceTest |
| ) |  |

Definition at line 21 of file path_source_unittests.cc.

21 {
22 Rect rect = Rect::MakeLTRB(10, 15, 20, 30);
23 RectPathSource source(rect);
24
25 EXPECT_TRUE(source.IsConvex());
26 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
27 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 20, 30));
28
29 ::testing::StrictMock<DlPathReceiverMock> receiver;
30
31 {
32 ::testing::Sequence sequence;
33
34 EXPECT_CALL(receiver, MoveTo(Point(10, 15), true));
35 EXPECT_CALL(receiver, LineTo(Point(20, 15)));
36 EXPECT_CALL(receiver, LineTo(Point(20, 30)));
37 EXPECT_CALL(receiver, LineTo(Point(10, 30)));
38 EXPECT_CALL(receiver, LineTo(Point(10, 15)));
39 EXPECT_CALL(receiver, Close());
40 }
41
42 source.Dispatch(receiver);
43 }

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() [282/525]

impeller::testing::TEST | ( | PathSourceTest | ,
|  | RoundRectSourceTest |
| ) |  |

Definition at line 69 of file path_source_unittests.cc.

69 {
70 Rect rect = Rect::MakeLTRB(10, 15, 40, 60);
71 RoundingRadii radii = {
72 .top_left = Size(1, 11),
73 .top_right = Size(2, 12),
74 .bottom_left = Size(4, 14),
75 .bottom_right = Size(3, 13),
76 };
77 RoundRect round_rect = RoundRect::MakeRectRadii(rect, radii);
78 RoundRectPathSource source(round_rect);
79
80 EXPECT_TRUE(source.IsConvex());
81 EXPECT_EQ(source.GetFillType(), FillType::kNonZero);
82 EXPECT_EQ(source.GetBounds(), Rect::MakeLTRB(10, 15, 40, 60));
83
84 ::testing::StrictMock<DlPathReceiverMock> receiver;
85
86 {
87 ::testing::Sequence sequence;
88
89 EXPECT_CALL(receiver, MoveTo(Point(11, 15), true));
90 EXPECT_CALL(receiver, LineTo(Point(38, 15)));
91 EXPECT_CALL(receiver, ConicTo(Point(40, 15), Point(40, 27), kSqrt2Over2));
92 EXPECT_CALL(receiver, LineTo(Point(40, 47)));
93 EXPECT_CALL(receiver, ConicTo(Point(40, 60), Point(37, 60), kSqrt2Over2));
94 EXPECT_CALL(receiver, LineTo(Point(14, 60)));
95 EXPECT_CALL(receiver, ConicTo(Point(10, 60), Point(10, 46), kSqrt2Over2));
96 EXPECT_CALL(receiver, LineTo(Point(10, 26)));
97 EXPECT_CALL(receiver, ConicTo(Point(10, 15), Point(11, 15), kSqrt2Over2));
98 EXPECT_CALL(receiver, Close());
99 }
100
101 source.Dispatch(receiver);
102 }

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() [283/525]

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:332
contours
std::vector< Contour > contours
Definition: tessellator_libtess.cc:77

References contours, impeller::PathTessellator::CountFillStorage(), impeller::PathTessellator::PathToFilledSegments(), impeller::PathTessellator::PathToFilledVertices(), and points.

## ◆ TEST() [284/525]

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() [285/525]

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() [286/525]

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() [287/525]

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() [288/525]

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() [289/525]

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() [290/525]

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() [291/525]

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() [292/525]

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() [293/525]

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() [294/525]

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() [295/525]

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() [296/525]

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() [297/525]

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() [298/525]

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() [299/525]

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() [300/525]

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() [301/525]

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() [302/525]

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() [303/525]

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() [304/525]

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() [305/525]

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

References impeller::saturated::b, and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [306/525]

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() [307/525]

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() [308/525]

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() [309/525]

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() [310/525]

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() [311/525]

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() [312/525]

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() [313/525]

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() [314/525]

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() [315/525]

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() [316/525]

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() [317/525]

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() [318/525]

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() [319/525]

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() [320/525]

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() [321/525]

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() [322/525]

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() [323/525]

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() [324/525]

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() [325/525]

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() [326/525]

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() [327/525]

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() [328/525]

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() [329/525]

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() [330/525]

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() [331/525]

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() [332/525]

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() [333/525]

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() [334/525]

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() [335/525]

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() [336/525]

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, impeller::TRect< T >::Intersection(), impeller::TRect< T >::MakeLTRB(), and value.

## ◆ TEST() [337/525]

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, impeller::TRect< T >::MakeLTRB(), impeller::TRect< T >::Union(), and value.

## ◆ TEST() [338/525]

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, impeller::TRect< T >::Intersection(), impeller::TRect< Scalar >::Intersection(), impeller::TRect< Scalar >::MakeLTRB(), and value.

## ◆ TEST() [339/525]

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, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::Union(), impeller::TRect< Scalar >::Union(), and value.

## ◆ TEST() [340/525]

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() [341/525]

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() [342/525]

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() [343/525]

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() [344/525]

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() [345/525]

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() [346/525]

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() [347/525]

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() [348/525]

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() [349/525]

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() [350/525]

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() [351/525]

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() [352/525]

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() [353/525]

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() [354/525]

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() [355/525]

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() [356/525]

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() [357/525]

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() [358/525]

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() [359/525]

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() [360/525]

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() [361/525]

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() [362/525]

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() [363/525]

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() [364/525]

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() [365/525]

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() [366/525]

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() [367/525]

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() [368/525]

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() [369/525]

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() [370/525]

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() [371/525]

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() [372/525]

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() [373/525]

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() [374/525]

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() [375/525]

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() [376/525]

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() [377/525]

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() [378/525]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBounds |
| ) |  |

Definition at line 3116 of file rect_unittests.cc.

3116 {
3117 {
3118 // This matrix should clip no corners.
3119 auto matrix = impeller::Matrix::MakeColumn(
3120 // clang-format off
3121 2.0f, 0.0f, 0.0f, 0.0f,
3122 0.0f, 4.0f, 0.0f, 0.0f,
3123 0.0f, 0.0f, 1.0f, 0.0f,
3124 0.0f, 0.0f, 0.0f, 8.0f
3125 // clang-format on
3126 );
3127 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3128 // None of these should have a W<0
3129 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
3130 Vector3(200.0f, 400.0f, 8.0f));
3131 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
3132 Vector3(400.0f, 400.0f, 8.0f));
3133 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
3134 Vector3(200.0f, 800.0f, 8.0f));
3135 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
3136 Vector3(400.0f, 800.0f, 8.0f));
3137
3138 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
3139 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3140 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
3141 }
3142
3143 {
3144 // This matrix should clip one corner.
3145 auto matrix = impeller::Matrix::MakeColumn(
3146 // clang-format off
3147 2.0f, 0.0f, 0.0f, -0.01f,
3148 0.0f, 2.0f, 0.0f, -0.006f,
3149 0.0f, 0.0f, 1.0f, 0.0f,
3150 0.0f, 0.0f, 0.0f, 3.0f
3151 // clang-format on
3152 );
3153 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3154 // Exactly one of these should have a W<0
3155 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3156 Vector3(200.0f, 200.0f, 1.4f));
3157 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3158 Vector3(400.0f, 200.0f, 0.4f));
3159 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3160 Vector3(200.0f, 400.0f, 0.8f));
3161 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3162 Vector3(400.0f, 400.0f, -0.2f));
3163
3164 Rect expect = Rect::MakeLTRB(142.85715f, 142.85715f, 6553600.f, 6553600.f);
3165 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3166 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3167 }
3168
3169 {
3170 // This matrix should clip two corners.
3171 auto matrix = impeller::Matrix::MakeColumn(
3172 // clang-format off
3173 2.0f, 0.0f, 0.0f, -.015f,
3174 0.0f, 2.0f, 0.0f, -.006f,
3175 0.0f, 0.0f, 1.0f, 0.0f,
3176 0.0f, 0.0f, 0.0f, 3.0f
3177 // clang-format on
3178 );
3179 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3180 // Exactly two of these should have a W<0
3181 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3182 Vector3(200.0f, 200.0f, 0.9f));
3183 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3184 Vector3(400.0f, 200.0f, -0.6f));
3185 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3186 Vector3(200.0f, 400.0f, 0.3f));
3187 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3188 Vector3(400.0f, 400.0f, -1.2f));
3189
3190 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5898373.f, 6553600.f);
3191 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3192 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3193 }
3194
3195 {
3196 // This matrix should clip three corners.
3197 auto matrix = impeller::Matrix::MakeColumn(
3198 // clang-format off
3199 2.0f, 0.0f, 0.0f, -.02f,
3200 0.0f, 2.0f, 0.0f, -.006f,
3201 0.0f, 0.0f, 1.0f, 0.0f,
3202 0.0f, 0.0f, 0.0f, 3.0f
3203 // clang-format on
3204 );
3205 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3206 // Exactly three of these should have a W<0
3207 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3208 Vector3(200.0f, 200.0f, 0.4f));
3209 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3210 Vector3(400.0f, 200.0f, -1.6f));
3211 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3212 Vector3(200.0f, 400.0f, -0.2f));
3213 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3214 Vector3(400.0f, 400.0f, -2.2f));
3215
3216 Rect expect = Rect::MakeLTRB(499.99988f, 499.99988f, 5898340.f, 4369400.f);
3217 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3218 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3219 }
3220
3221 {
3222 // This matrix should clip all four corners.
3223 auto matrix = impeller::Matrix::MakeColumn(
3224 // clang-format off
3225 2.0f, 0.0f, 0.0f, -.025f,
3226 0.0f, 2.0f, 0.0f, -.006f,
3227 0.0f, 0.0f, 1.0f, 0.0f,
3228 0.0f, 0.0f, 0.0f, 3.0f
3229 // clang-format on
3230 );
3231 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3232 // All of these should have a W<0
3233 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3234 Vector3(200.0f, 200.0f, -0.1f));
3235 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3236 Vector3(400.0f, 200.0f, -2.6f));
3237 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3238 Vector3(200.0f, 400.0f, -0.7f));
3239 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3240 Vector3(400.0f, 400.0f, -3.2f));
3241
3242 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3243 }
3244 }
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_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() [379/525]

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() [380/525]

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() [381/525]

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() [382/525]

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() [383/525]

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() [384/525]

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() [385/525]

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() [386/525]

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() [387/525]

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() [388/525]

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() [389/525]

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() [390/525]

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() [391/525]

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() [392/525]

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() [393/525]

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() [394/525]

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() [395/525]

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() [396/525]

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() [397/525]

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() [398/525]

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() [399/525]

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() [400/525]

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() [401/525]

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() [402/525]

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() [403/525]

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() [404/525]

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() [405/525]

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() [406/525]

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() [407/525]

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() [408/525]

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() [409/525]

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() [410/525]

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() [411/525]

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() [412/525]

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() [413/525]

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() [414/525]

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() [415/525]

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() [416/525]

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() [417/525]

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() [418/525]

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() [419/525]

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() [420/525]

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() [421/525]

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() [422/525]

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() [423/525]

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() [424/525]

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() [425/525]

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() [426/525]

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() [427/525]

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() [428/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractAndRequireRadiiAdjustment |
| ) |  |

Definition at line 543 of file round_superellipse_unittests.cc.

543 {
544 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
545 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
546 {
547 .top_left = Size(1.0f, 2.0f),
548 .top_right = Size(3.0f, 4.0f),
549 .bottom_left = Size(5.0f, 6.0f),
550 .bottom_right = Size(7.0f, 8.0f),
551 });
552 RoundSuperellipse expanded = rse.Expand(-12.0);
553 // Largest sum of paired radii sizes are the bottom and right edges
554 // both of which sum to 12
555 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
556 // radii are scaled by half to avoid overflowing the contracted rect
557
558 EXPECT_FALSE(expanded.IsEmpty());
559 EXPECT_FALSE(expanded.IsRect());
560 EXPECT_FALSE(expanded.IsOval());
561 EXPECT_TRUE(expanded.IsFinite());
562 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
563 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
564 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
565 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
566 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
567 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
568
569 // In this test, the MakeRectRadii constructor will make the same
570 // adjustment to the radii that the Expand method applied.
571 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
572 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
573 {
574 .top_left = Size(1.0f, 2.0f),
575 .top_right = Size(3.0f, 4.0f),
576 .bottom_left = Size(5.0f, 6.0f),
577 .bottom_right = Size(7.0f, 8.0f),
578 }));
579
580 // In this test, the arguments to the constructor supply the correctly
581 // adjusted radii (though there is no real way to tell other than
582 // the result is the same).
583 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
584 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
585 {
586 .top_left = Size(0.5f, 1.0f),
587 .top_right = Size(1.5f, 2.0f),
588 .bottom_left = Size(2.5f, 3.0f),
589 .bottom_right = Size(3.5f, 4.0f),
590 }));
591 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [429/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractFourScalars |
| ) |  |

Definition at line 511 of file round_superellipse_unittests.cc.

511 {
512 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
513 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
514 {
515 .top_left = Size(1.0f, 2.0f),
516 .top_right = Size(3.0f, 4.0f),
517 .bottom_left = Size(5.0f, 6.0f),
518 .bottom_right = Size(7.0f, 8.0f),
519 });
520 RoundSuperellipse expanded = rse.Expand(-1.0, -1.5, -2.0, -2.5);
521
522 EXPECT_FALSE(expanded.IsEmpty());
523 EXPECT_FALSE(expanded.IsRect());
524 EXPECT_FALSE(expanded.IsOval());
525 EXPECT_TRUE(expanded.IsFinite());
526 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
527 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
528 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
529 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
530 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
531 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
532
533 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
534 Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
535 {
536 .top_left = Size(1.0f, 2.0f),
537 .top_right = Size(3.0f, 4.0f),
538 .bottom_left = Size(5.0f, 6.0f),
539 .bottom_right = Size(7.0f, 8.0f),
540 }));
541 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [430/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractScalar |
| ) |  |

Definition at line 447 of file round_superellipse_unittests.cc.

447 {
448 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
449 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
450 {
451 .top_left = Size(1.0f, 2.0f),
452 .top_right = Size(3.0f, 4.0f),
453 .bottom_left = Size(5.0f, 6.0f),
454 .bottom_right = Size(7.0f, 8.0f),
455 });
456 RoundSuperellipse expanded = rse.Expand(-2.0);
457
458 EXPECT_FALSE(expanded.IsEmpty());
459 EXPECT_FALSE(expanded.IsRect());
460 EXPECT_FALSE(expanded.IsOval());
461 EXPECT_TRUE(expanded.IsFinite());
462 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
463 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
464 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
465 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
466 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
467 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
468
469 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
470 Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
471 {
472 .top_left = Size(1.0f, 2.0f),
473 .top_right = Size(3.0f, 4.0f),
474 .bottom_left = Size(5.0f, 6.0f),
475 .bottom_right = Size(7.0f, 8.0f),
476 }));
477 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [431/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ContractTwoScalars |
| ) |  |

Definition at line 479 of file round_superellipse_unittests.cc.

479 {
480 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
481 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
482 {
483 .top_left = Size(1.0f, 2.0f),
484 .top_right = Size(3.0f, 4.0f),
485 .bottom_left = Size(5.0f, 6.0f),
486 .bottom_right = Size(7.0f, 8.0f),
487 });
488 RoundSuperellipse expanded = rse.Expand(-1.0, -2.0);
489
490 EXPECT_FALSE(expanded.IsEmpty());
491 EXPECT_FALSE(expanded.IsRect());
492 EXPECT_FALSE(expanded.IsOval());
493 EXPECT_TRUE(expanded.IsFinite());
494 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
495 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
496 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
497 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
498 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
499 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
500
501 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
502 Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
503 {
504 .top_left = Size(1.0f, 2.0f),
505 .top_right = Size(3.0f, 4.0f),
506 .bottom_left = Size(5.0f, 6.0f),
507 .bottom_right = Size(7.0f, 8.0f),
508 }));
509 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [432/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | DefaultConstructor |
| ) |  |

Definition at line 88 of file round_superellipse_unittests.cc.

88 {
89 RoundSuperellipse rse = RoundSuperellipse();
90
91 EXPECT_TRUE(rse.IsEmpty());
92 EXPECT_FALSE(rse.IsRect());
93 EXPECT_FALSE(rse.IsOval());
94 EXPECT_TRUE(rse.IsFinite());
95 EXPECT_TRUE(rse.GetBounds().IsEmpty());
96 EXPECT_EQ(rse.GetBounds(), Rect());
97 EXPECT_EQ(rse.GetRadii().top_left, Size());
98 EXPECT_EQ(rse.GetRadii().top_right, Size());
99 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
100 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
101 }

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() [433/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyDeclaration |
| ) |  |

Definition at line 61 of file round_superellipse_unittests.cc.

61 {
62 RoundSuperellipse rse;
63
64 EXPECT_TRUE(rse.IsEmpty());
65 EXPECT_FALSE(rse.IsRect());
66 EXPECT_FALSE(rse.IsOval());
67 EXPECT_TRUE(rse.IsFinite());
68 EXPECT_TRUE(rse.GetBounds().IsEmpty());
69 EXPECT_EQ(rse.GetBounds(), Rect());
70 EXPECT_EQ(rse.GetBounds().GetLeft(), 0.0f);
71 EXPECT_EQ(rse.GetBounds().GetTop(), 0.0f);
72 EXPECT_EQ(rse.GetBounds().GetRight(), 0.0f);
73 EXPECT_EQ(rse.GetBounds().GetBottom(), 0.0f);
74 EXPECT_EQ(rse.GetRadii().top_left, Size());
75 EXPECT_EQ(rse.GetRadii().top_right, Size());
76 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
77 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
78 EXPECT_EQ(rse.GetRadii().top_left.width, 0.0f);
79 EXPECT_EQ(rse.GetRadii().top_left.height, 0.0f);
80 EXPECT_EQ(rse.GetRadii().top_right.width, 0.0f);
81 EXPECT_EQ(rse.GetRadii().top_right.height, 0.0f);
82 EXPECT_EQ(rse.GetRadii().bottom_left.width, 0.0f);
83 EXPECT_EQ(rse.GetRadii().bottom_left.height, 0.0f);
84 EXPECT_EQ(rse.GetRadii().bottom_right.width, 0.0f);
85 EXPECT_EQ(rse.GetRadii().bottom_right.height, 0.0f);
86 }

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() [434/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyOvalConstruction |
| ) |  |

Definition at line 151 of file round_superellipse_unittests.cc.

151 {
152 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
153 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
154
155 EXPECT_TRUE(rse.IsEmpty());
156 EXPECT_FALSE(rse.IsRect());
157 EXPECT_FALSE(rse.IsOval());
158 EXPECT_TRUE(rse.IsFinite());
159 EXPECT_TRUE(rse.GetBounds().IsEmpty());
160 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
161 EXPECT_EQ(rse.GetRadii().top_left, Size());
162 EXPECT_EQ(rse.GetRadii().top_right, Size());
163 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
164 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
165 }

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() [435/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | EmptyRectConstruction |
| ) |  |

Definition at line 103 of file round_superellipse_unittests.cc.

103 {
104 RoundSuperellipse rse =
105 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
106
107 EXPECT_TRUE(rse.IsEmpty());
108 EXPECT_FALSE(rse.IsRect());
109 EXPECT_FALSE(rse.IsOval());
110 EXPECT_TRUE(rse.IsFinite());
111 EXPECT_TRUE(rse.GetBounds().IsEmpty());
112 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
113 EXPECT_EQ(rse.GetRadii().top_left, Size());
114 EXPECT_EQ(rse.GetRadii().top_right, Size());
115 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
116 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
117 }

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() [436/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandFourScalars |
| ) |  |

Definition at line 415 of file round_superellipse_unittests.cc.

415 {
416 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
417 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
418 {
419 .top_left = Size(1.0f, 2.0f),
420 .top_right = Size(3.0f, 4.0f),
421 .bottom_left = Size(5.0f, 6.0f),
422 .bottom_right = Size(7.0f, 8.0f),
423 });
424 RoundSuperellipse expanded = rse.Expand(5.0, 6.0, 7.0, 8.0);
425
426 EXPECT_FALSE(expanded.IsEmpty());
427 EXPECT_FALSE(expanded.IsRect());
428 EXPECT_FALSE(expanded.IsOval());
429 EXPECT_TRUE(expanded.IsFinite());
430 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
431 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
432 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
433 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
434 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
435 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
436
437 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
438 Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
439 {
440 .top_left = Size(1.0f, 2.0f),
441 .top_right = Size(3.0f, 4.0f),
442 .bottom_left = Size(5.0f, 6.0f),
443 .bottom_right = Size(7.0f, 8.0f),
444 }));
445 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [437/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandScalar |
| ) |  |

Definition at line 351 of file round_superellipse_unittests.cc.

351 {
352 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
353 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
354 {
355 .top_left = Size(1.0f, 2.0f),
356 .top_right = Size(3.0f, 4.0f),
357 .bottom_left = Size(5.0f, 6.0f),
358 .bottom_right = Size(7.0f, 8.0f),
359 });
360 RoundSuperellipse expanded = rse.Expand(5.0);
361
362 EXPECT_FALSE(expanded.IsEmpty());
363 EXPECT_FALSE(expanded.IsRect());
364 EXPECT_FALSE(expanded.IsOval());
365 EXPECT_TRUE(expanded.IsFinite());
366 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
367 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
368 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
369 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
370 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
371 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
372
373 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
374 Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
375 {
376 .top_left = Size(1.0f, 2.0f),
377 .top_right = Size(3.0f, 4.0f),
378 .bottom_left = Size(5.0f, 6.0f),
379 .bottom_right = Size(7.0f, 8.0f),
380 }));
381 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [438/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | ExpandTwoScalars |
| ) |  |

Definition at line 383 of file round_superellipse_unittests.cc.

383 {
384 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
385 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
386 {
387 .top_left = Size(1.0f, 2.0f),
388 .top_right = Size(3.0f, 4.0f),
389 .bottom_left = Size(5.0f, 6.0f),
390 .bottom_right = Size(7.0f, 8.0f),
391 });
392 RoundSuperellipse expanded = rse.Expand(5.0, 6.0);
393
394 EXPECT_FALSE(expanded.IsEmpty());
395 EXPECT_FALSE(expanded.IsRect());
396 EXPECT_FALSE(expanded.IsOval());
397 EXPECT_TRUE(expanded.IsFinite());
398 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
399 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
400 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
401 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
402 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
403 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
404
405 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
406 Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
407 {
408 .top_left = Size(1.0f, 2.0f),
409 .top_right = Size(3.0f, 4.0f),
410 .bottom_left = Size(5.0f, 6.0f),
411 .bottom_right = Size(7.0f, 8.0f),
412 }));
413 }

References impeller::RoundSuperellipse::Expand(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [439/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | InvertedOvalConstruction |
| ) |  |

Definition at line 183 of file round_superellipse_unittests.cc.

183 {
184 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
185 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
186
187 EXPECT_FALSE(rse.IsEmpty());
188 EXPECT_FALSE(rse.IsRect());
189 EXPECT_TRUE(rse.IsOval());
190 EXPECT_TRUE(rse.IsFinite());
191 EXPECT_FALSE(rse.GetBounds().IsEmpty());
192 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
193 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
194 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
195 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
196 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
197 }

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() [440/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | InvertedRectConstruction |
| ) |  |

Definition at line 135 of file round_superellipse_unittests.cc.

135 {
136 RoundSuperellipse rse =
137 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
138
139 EXPECT_FALSE(rse.IsEmpty());
140 EXPECT_TRUE(rse.IsRect());
141 EXPECT_FALSE(rse.IsOval());
142 EXPECT_TRUE(rse.IsFinite());
143 EXPECT_FALSE(rse.GetBounds().IsEmpty());
144 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
145 EXPECT_EQ(rse.GetRadii().top_left, Size());
146 EXPECT_EQ(rse.GetRadii().top_right, Size());
147 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
148 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
149 }

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() [441/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | NoCornerRoundSuperellipseContains |
| ) |  |

Definition at line 593 of file round_superellipse_unittests.cc.

593 {
594 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
595 // Rounded superellipses of bounds with no corners contains corners just
596 // barely.
597 auto no_corners = RoundSuperellipse::MakeRectRadii(
598 bounds, RoundingRadii::MakeRadii({0.0f, 0.0f}));
599
600 EXPECT_TRUE(no_corners.Contains({-50, -50}));
601 // Rectangles have half-in, half-out containment so we need
602 // to be careful about testing containment of right/bottom corners.
603 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
604 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
605 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
606 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
607 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
608 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
609 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
610 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
611 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
612 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
613 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
614 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [442/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | OvalConstructor |
| ) |  |

Definition at line 167 of file round_superellipse_unittests.cc.

167 {
168 RoundSuperellipse rse =
169 RoundSuperellipse::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
170
171 EXPECT_FALSE(rse.IsEmpty());
172 EXPECT_FALSE(rse.IsRect());
173 EXPECT_TRUE(rse.IsOval());
174 EXPECT_TRUE(rse.IsFinite());
175 EXPECT_FALSE(rse.GetBounds().IsEmpty());
176 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
177 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
178 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
179 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
180 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
181 }

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() [443/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | PathForRectangularRseWithShapeCornersShouldBeWithinBounds |
| ) |  |

Definition at line 755 of file round_superellipse_unittests.cc.

756 {
757 Rect bounds = Rect::MakeLTRB(34.0f, 242.0f, 766.0f, 358.0f);
758 // Regression test for https://github.com/flutter/flutter/issues/170593.
759 // The issue was caused by incorrect calculation when building paths for
760 // rounded superellipses with sharp corners and unequal width and height.
761 // Since the most obvious symptom of the issue is some points being
762 // incorrectly placed out of bounds, this test case simply verifies that all
763 // points are within the bounds.
764
765 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
766 bounds, {
767 .top_left = Size(14.0, 14.0),
768 .top_right = Size(14.0, 14.0),
769 .bottom_left = Size(0.0, 0.0),
770 .bottom_right = Size(0.0, 0.0),
771 });
772 SpyPathReceiver receiver;
773 receiver.SpyLineTo(
774 [&](const Point& p2) { EXPECT_TRUE(bounds.ContainsInclusive(p2)); });
775 receiver.SpyCubicTo([&](const Point& cp1, const Point& cp2, const Point& p2) {
776 EXPECT_TRUE(bounds.ContainsInclusive(p2));
777 });
778
779 rr.Dispatch(receiver);
780 }

References impeller::TRect< T >::ContainsInclusive(), impeller::RoundSuperellipseParam::Dispatch(), impeller::RoundSuperellipseParam::MakeBoundsRadii(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [444/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | PointsOutsideOfSharpCorner |
| ) |  |

Definition at line 738 of file round_superellipse_unittests.cc.

738 {
739 Rect bounds = Rect::MakeLTRB(196.0f, 0.0f, 294.0f, 28.0f);
740 // Regression test for a case where RoundSuperellipseParam::Contains
741 // previously failed. Although the bounding rect filter of
742 // `RoundSuperellipse::Contains` would reject this point, this test ensures
743 // the internal logic of RoundSuperellipseParam::Contains is now correct.
744 auto rr = RoundSuperellipseParam::MakeBoundsRadii(
745 bounds, {
746 .top_left = Size(0.0, 0.0),
747 .top_right = Size(3.0, 3.0),
748 .bottom_left = Size(0.0, 0.0),
749 .bottom_right = Size(3.0, 3.0),
750 });
751
752 EXPECT_FALSE(rr.Contains(Point{147.0, 14.0}));
753 }

References impeller::RoundSuperellipseParam::MakeBoundsRadii(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [445/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectConstructor |
| ) |  |

Definition at line 119 of file round_superellipse_unittests.cc.

119 {
120 RoundSuperellipse rse =
121 RoundSuperellipse::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
122
123 EXPECT_FALSE(rse.IsEmpty());
124 EXPECT_TRUE(rse.IsRect());
125 EXPECT_FALSE(rse.IsOval());
126 EXPECT_TRUE(rse.IsFinite());
127 EXPECT_FALSE(rse.GetBounds().IsEmpty());
128 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
129 EXPECT_EQ(rse.GetRadii().top_left, Size());
130 EXPECT_EQ(rse.GetRadii().top_right, Size());
131 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
132 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
133 }

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() [446/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiConstructor |
| ) |  |

Definition at line 247 of file round_superellipse_unittests.cc.

247 {
248 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
249 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
250 {
251 .top_left = Size(1.0, 1.5),
252 .top_right = Size(2.0, 2.5f),
253 .bottom_left = Size(3.0, 3.5f),
254 .bottom_right = Size(4.0, 4.5f),
255 });
256
257 EXPECT_FALSE(rse.IsEmpty());
258 EXPECT_FALSE(rse.IsRect());
259 EXPECT_FALSE(rse.IsOval());
260 EXPECT_TRUE(rse.IsFinite());
261 EXPECT_FALSE(rse.GetBounds().IsEmpty());
262 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
263 EXPECT_EQ(rse.GetRadii().top_left, Size(1.0f, 1.5f));
264 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.5f));
265 EXPECT_EQ(rse.GetRadii().bottom_left, Size(3.0f, 3.5f));
266 EXPECT_EQ(rse.GetRadii().bottom_right, Size(4.0f, 4.5f));
267 }

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() [447/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiOverflowHeightConstructor |
| ) |  |

Definition at line 294 of file round_superellipse_unittests.cc.

294 {
295 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
296 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
297 {
298 .top_left = Size(1.0f, 2.0f),
299 .top_right = Size(3.0f, 4.0f),
300 .bottom_left = Size(5.0f, 6.0f),
301 .bottom_right = Size(7.0f, 8.0f),
302 });
303 // Largest sum of paired radii heights is the right edge which sums to 12
304 // Rect is only 6 tall so all radii are scaled by half
305 // Rect is 30 wide so no scaling should happen due to radii widths
306
307 EXPECT_FALSE(rse.IsEmpty());
308 EXPECT_FALSE(rse.IsRect());
309 EXPECT_FALSE(rse.IsOval());
310 EXPECT_TRUE(rse.IsFinite());
311 EXPECT_FALSE(rse.GetBounds().IsEmpty());
312 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
313 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
314 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
315 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
316 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
317 }

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() [448/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiiOverflowWidthConstructor |
| ) |  |

Definition at line 269 of file round_superellipse_unittests.cc.

269 {
270 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
271 Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
272 {
273 .top_left = Size(1.0f, 2.0f),
274 .top_right = Size(3.0f, 4.0f),
275 .bottom_left = Size(5.0f, 6.0f),
276 .bottom_right = Size(7.0f, 8.0f),
277 });
278 // Largest sum of paired radii widths is the bottom edge which sums to 12
279 // Rect is only 6 wide so all radii are scaled by half
280 // Rect is 30 tall so no scaling should happen due to radii heights
281
282 EXPECT_FALSE(rse.IsEmpty());
283 EXPECT_FALSE(rse.IsRect());
284 EXPECT_FALSE(rse.IsOval());
285 EXPECT_TRUE(rse.IsFinite());
286 EXPECT_FALSE(rse.GetBounds().IsEmpty());
287 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
288 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
289 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
290 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
291 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
292 }

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() [449/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectRadiusConstructor |
| ) |  |

Definition at line 199 of file round_superellipse_unittests.cc.

199 {
200 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadius(
201 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
202
203 EXPECT_FALSE(rse.IsEmpty());
204 EXPECT_FALSE(rse.IsRect());
205 EXPECT_FALSE(rse.IsOval());
206 EXPECT_TRUE(rse.IsFinite());
207 EXPECT_FALSE(rse.GetBounds().IsEmpty());
208 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
209 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 2.0f));
210 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.0f));
211 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 2.0f));
212 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 2.0f));
213 }

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() [450/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectSizeConstructor |
| ) |  |

Definition at line 231 of file round_superellipse_unittests.cc.

231 {
232 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
233 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
234
235 EXPECT_FALSE(rse.IsEmpty());
236 EXPECT_FALSE(rse.IsRect());
237 EXPECT_FALSE(rse.IsOval());
238 EXPECT_TRUE(rse.IsFinite());
239 EXPECT_FALSE(rse.GetBounds().IsEmpty());
240 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
241 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
242 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
243 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
244 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
245 }

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() [451/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | RectXYConstructor |
| ) |  |

Definition at line 215 of file round_superellipse_unittests.cc.

215 {
216 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
217 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
218
219 EXPECT_FALSE(rse.IsEmpty());
220 EXPECT_FALSE(rse.IsRect());
221 EXPECT_FALSE(rse.IsOval());
222 EXPECT_TRUE(rse.IsFinite());
223 EXPECT_FALSE(rse.GetBounds().IsEmpty());
224 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
225 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
226 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
227 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
228 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
229 }

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() [452/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | Shift |
| ) |  |

Definition at line 319 of file round_superellipse_unittests.cc.

319 {
320 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
321 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
322 {
323 .top_left = Size(1.0f, 2.0f),
324 .top_right = Size(3.0f, 4.0f),
325 .bottom_left = Size(5.0f, 6.0f),
326 .bottom_right = Size(7.0f, 8.0f),
327 });
328 RoundSuperellipse shifted = rse.Shift(5.0, 6.0);
329
330 EXPECT_FALSE(shifted.IsEmpty());
331 EXPECT_FALSE(shifted.IsRect());
332 EXPECT_FALSE(shifted.IsOval());
333 EXPECT_TRUE(shifted.IsFinite());
334 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
335 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
336 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
337 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
338 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
339 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
340
341 EXPECT_EQ(shifted, RoundSuperellipse::MakeRectRadii(
342 Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
343 {
344 .top_left = Size(1.0f, 2.0f),
345 .top_right = Size(3.0f, 4.0f),
346 .bottom_left = Size(5.0f, 6.0f),
347 .bottom_right = Size(7.0f, 8.0f),
348 }));
349 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundSuperellipse::MakeRectRadii(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::RoundSuperellipse::Shift().

## ◆ TEST() [453/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | SlimDiagonalContains |
| ) |  |

Definition at line 701 of file round_superellipse_unittests.cc.

701 {
702 // This shape has large radii on one diagonal and tiny radii on the other,
703 // resulting in a almond-like shape placed diagonally (NW to SE).
704 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
705 auto rr = RoundSuperellipse::MakeRectRadii(
706 bounds, {
707 .top_left = Size(1.0, 1.0),
708 .top_right = Size(99.0, 99.0),
709 .bottom_left = Size(99.0, 99.0),
710 .bottom_right = Size(1.0, 1.0),
711 });
712
713 EXPECT_TRUE(rr.Contains(Point{0, 0}));
714 EXPECT_FALSE(rr.Contains(Point{-49.999, -49.999}));
715 EXPECT_FALSE(rr.Contains(Point{-49.999, 49.999}));
716 EXPECT_FALSE(rr.Contains(Point{49.999, 49.999}));
717 EXPECT_FALSE(rr.Contains(Point{49.999, -49.999}));
718
719 // The pointy ends at the NE and SW corners
720 CHECK_POINT_WITH_OFFSET(rr, Point(-49.70, -49.70), Point(-0.02, -0.02));
721 CHECK_POINT_WITH_OFFSET(rr, Point(49.70, 49.70), Point(0.02, 0.02));
722
723 // Checks two points symmetrical to the origin.
724 #define CHECK_DIAGONAL_POINTS(p) \
725 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, -0.02)); \
726 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, 0.02));
727
728 // A few other points along the edge
729 CHECK_DIAGONAL_POINTS(Point(-40.0, -49.59));
730 CHECK_DIAGONAL_POINTS(Point(-20.0, -45.64));
731 CHECK_DIAGONAL_POINTS(Point(0.0, -37.01));
732 CHECK_DIAGONAL_POINTS(Point(20.0, -21.96));
733 CHECK_DIAGONAL_POINTS(Point(21.05, -20.92));
734 CHECK_DIAGONAL_POINTS(Point(40.0, 5.68));
735 #undef CHECK_POINT_AND_MIRRORS
736 }
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() [454/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | TinyCornerContains |
| ) |  |

Definition at line 616 of file round_superellipse_unittests.cc.

616 {
617 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
618 // Rounded superellipses of bounds with even the tiniest corners does not
619 // contain corners.
620 auto tiny_corners = RoundSuperellipse::MakeRectRadii(
621 bounds, RoundingRadii::MakeRadii({0.01f, 0.01f}));
622
623 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
624 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
625 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
626 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
627 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [455/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformEllipticalContains |
| ) |  |

Definition at line 650 of file round_superellipse_unittests.cc.

650 {
651 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
652 auto rr = RoundSuperellipse::MakeRectRadii(
653 bounds, RoundingRadii::MakeRadii({5.0f, 10.0f}));
654
655 #define CHECK_POINT_AND_MIRRORS(p) \
656 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
657 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
658 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
659 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
660
661 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
662 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.911)); // Top curve start
663 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.75)); // Top joint
664 CHECK_POINT_AND_MIRRORS(Point(48.51, 47.07)); // Circular arc mid
665 CHECK_POINT_AND_MIRRORS(Point(49.87, 41.44)); // Right joint
666 CHECK_POINT_AND_MIRRORS(Point(49.95, 38.49)); // Right curve start
667 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
668 #undef CHECK_POINT_AND_MIRRORS
669 }
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() [456/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformRectangularContains |
| ) |  |

Definition at line 671 of file round_superellipse_unittests.cc.

671 {
672 // The bounds is not centered at the origin and has unequal height and width.
673 Rect bounds = Rect::MakeLTRB(0.0f, 0.0f, 50.0f, 100.0f);
674 auto rr = RoundSuperellipse::MakeRectRadii(
675 bounds, RoundingRadii::MakeRadii({23.0f, 30.0f}));
676
677 Point center = bounds.GetCenter();
678 #define CHECK_POINT_AND_MIRRORS(p) \
679 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, 1) + center, \
680 Point(0.02, 0.02)); \
681 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, -1) + center, \
682 Point(0.02, -0.02)); \
683 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, 1) + center, \
684 Point(-0.02, 0.02)); \
685 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, -1) + center, \
686 Point(-0.02, -0.02));
687
688 CHECK_POINT_AND_MIRRORS(Point(24.99, 99.99)); // Bottom mid edge
689 CHECK_POINT_AND_MIRRORS(Point(29.99, 99.64));
690 CHECK_POINT_AND_MIRRORS(Point(34.99, 98.06));
691 CHECK_POINT_AND_MIRRORS(Point(39.99, 94.73));
692 CHECK_POINT_AND_MIRRORS(Point(44.13, 89.99));
693 CHECK_POINT_AND_MIRRORS(Point(48.46, 79.99));
694 CHECK_POINT_AND_MIRRORS(Point(49.70, 69.99));
695 CHECK_POINT_AND_MIRRORS(Point(49.97, 59.99));
696 CHECK_POINT_AND_MIRRORS(Point(49.99, 49.99)); // Right mid edge
697
698 #undef CHECK_POINT_AND_MIRRORS
699 }

References CHECK_POINT_AND_MIRRORS, impeller::TRect< T >::GetCenter(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [457/525]

impeller::testing::TEST | ( | RoundSuperellipseTest | ,
|  | UniformSquareContains |
| ) |  |

Definition at line 629 of file round_superellipse_unittests.cc.

629 {
630 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
631 auto rr = RoundSuperellipse::MakeRectRadii(
632 bounds, RoundingRadii::MakeRadii({5.0f, 5.0f}));
633
634 #define CHECK_POINT_AND_MIRRORS(p) \
635 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
636 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
637 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
638 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
639
640 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
641 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.95)); // Top curve start
642 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.87)); // Top joint
643 CHECK_POINT_AND_MIRRORS(Point(48.53, 48.53)); // Circular arc mid
644 CHECK_POINT_AND_MIRRORS(Point(49.87, 45.72)); // Right joint
645 CHECK_POINT_AND_MIRRORS(Point(49.95, 44.245)); // Right curve start
646 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
647 #undef CHECK_POINT_AND_MIRRORS
648 }

References CHECK_POINT_AND_MIRRORS, impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundingRadii::MakeRadii(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [458/525]

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() [459/525]

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() [460/525]

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() [461/525]

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() [462/525]

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() [463/525]

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() [464/525]

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() [465/525]

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() [466/525]

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() [467/525]

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() [468/525]

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() [469/525]

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() [470/525]

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() [471/525]

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() [472/525]

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() [473/525]

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() [474/525]

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() [475/525]

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() [476/525]

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() [477/525]

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() [478/525]

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() [479/525]

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() [480/525]

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() [481/525]

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() [482/525]

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() [483/525]

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() [484/525]

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() [485/525]

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() [486/525]

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() [487/525]

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() [488/525]

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() [489/525]

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() [490/525]

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() [491/525]

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() [492/525]

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() [493/525]

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() [494/525]

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() [495/525]

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() [496/525]

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() [497/525]

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() [498/525]

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() [499/525]

impeller::testing::TEST | ( | ShaderArchiveTest | ,
|  | CanReadAndWriteBlobs |
| ) |  |

Definition at line 28 of file shader_archive_unittests.cc.

28 {
29 ShaderArchiveWriter writer;
30 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Hello",
31 CreateMappingFromString("World")));
32 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Foo",
33 CreateMappingFromString("Bar")));
34 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Baz",
35 CreateMappingFromString("Bang")));
36 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kVertex, "Ping",
37 CreateMappingFromString("Pong")));
38 ASSERT_TRUE(writer.AddShader(ArchiveShaderType::kFragment, "Pang",
39 CreateMappingFromString("World")));
40
41 auto mapping = writer.CreateMapping();
42 ASSERT_NE(mapping, nullptr);
43
44 ShaderArchive library(mapping);
45 ASSERT_TRUE(library.IsValid());
46 ASSERT_EQ(library.GetShaderCount(), 5u);
47
48 // Wrong type.
49 ASSERT_EQ(library.GetMapping(ArchiveShaderType::kFragment, "Hello"), nullptr);
50
51 auto hello_vtx = library.GetMapping(ArchiveShaderType::kVertex, "Hello");
52 ASSERT_NE(hello_vtx, nullptr);
53 ASSERT_EQ(CreateStringFromMapping(*hello_vtx), "World");
54 }
impeller::testing::CreateStringFromMapping
const std::string CreateStringFromMapping(const fml::Mapping &mapping)
Definition: shader_archive_unittests.cc:23
impeller::testing::CreateMappingFromString
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)
Definition: shader_archive_unittests.cc:15

References impeller::ShaderArchiveWriter::AddShader(), impeller::ShaderArchiveWriter::CreateMapping(), CreateMappingFromString(), CreateStringFromMapping(), impeller::ShaderArchive::GetMapping(), impeller::ShaderArchive::GetShaderCount(), impeller::ShaderArchive::IsValid(), impeller::kFragment, and impeller::kVertex.

## ◆ TEST() [500/525]

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() [501/525]

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() [502/525]

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() [503/525]

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() [504/525]

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() [505/525]

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() [506/525]

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() [507/525]

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() [508/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | CircleVertexCounts |
| ) |  |

Definition at line 153 of file tessellator_unittests.cc.

153 {
154 auto tessellator = std::make_shared<Tessellator>();
155
156 auto test = [&tessellator](const Matrix& transform, Scalar radius) {
157 auto generator = tessellator->FilledCircle(transform, {}, radius);
158 size_t quadrant_divisions = generator.GetVertexCount() / 4;
159
160 // Confirm the approximation error is within the currently accepted
161 // |kCircleTolerance| value advertised by |CircleTessellator|.
162 // (With an additional 1% tolerance for floating point rounding.)
163 double angle = kPiOver2 / quadrant_divisions;
164 Point first = {radius, 0};
165 Point next = {static_cast<Scalar>(cos(angle) * radius),
166 static_cast<Scalar>(sin(angle) * radius)};
167 Point midpoint = (first + next) * 0.5;
168 EXPECT_GE(midpoint.GetLength(),
169 radius - Tessellator::kCircleTolerance * 1.01)
170 << ", transform = " << transform << ", radius = " << radius
171 << ", divisions = " << quadrant_divisions;
172 };
173
174 test({}, 0.0);
175 test({}, 0.9);
176 test({}, 1.0);
177 test({}, 1.9);
178 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
179 test({}, 2.0);
180 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
181 test({}, 11.9);
182 test({}, 12.0);
183 test({}, 35.9);
184 for (int i = 36; i < 10000; i += 4) {
185 test({}, i);
186 }
187 }

References impeller::TPoint< T >::GetLength(), impeller::Tessellator::kCircleTolerance, impeller::kPiOver2, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [509/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | EarlyReturnEmptyConvexShape |
| ) |  |

Definition at line 513 of file tessellator_unittests.cc.

513 {
514 // This path is not technically empty (it has a size in one dimension), but
515 // it contains only move commands and no actual path segment definitions.
516 flutter::DlPathBuilder builder;
517 builder.MoveTo({0, 0});
518 builder.MoveTo({10, 10});
519
520 std::vector<Point> points;
521 std::vector<uint16_t> indices;
522 Tessellator::TessellateConvexInternal(builder.TakePath(), points, indices,
523 3.0f);
524
525 EXPECT_TRUE(points.empty());
526 EXPECT_TRUE(indices.empty());
527 }

References points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [510/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledCircleTessellationVertices |
| ) |  |

Definition at line 189 of file tessellator_unittests.cc.

189 {
190 auto tessellator = std::make_shared<Tessellator>();
191
192 auto test = [&tessellator](const Matrix& transform, const Point& center,
193 Scalar radius) {
194 auto generator = tessellator->FilledCircle(transform, center, radius);
195 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
196
197 auto vertex_count = generator.GetVertexCount();
198 auto vertices = std::vector<Point>();
199 generator.GenerateVertices([&vertices](const Point& p) { //
200 vertices.push_back(p);
201 });
202 EXPECT_EQ(vertices.size(), vertex_count);
203 ASSERT_EQ(vertex_count % 4, 0u);
204
205 auto quadrant_count = vertex_count / 4;
206 for (size_t i = 0; i < quadrant_count; i++) {
207 double angle = kPiOver2 * i / (quadrant_count - 1);
208 double degrees = angle * 180.0 / kPi;
209 double rsin = sin(angle) * radius;
210 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
211 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
212 EXPECT_POINT_NEAR(vertices[i * 2],
213 Point(center.x - rcos, center.y + rsin))
214 << "vertex " << i << ", angle = " << degrees << std::endl;
215 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
216 Point(center.x - rcos, center.y - rsin))
217 << "vertex " << i << ", angle = " << degrees << std::endl;
218 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
219 Point(center.x + rcos, center.y - rsin))
220 << "vertex " << i << ", angle = " << degrees << std::endl;
221 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
222 Point(center.x + rcos, center.y + rsin))
223 << "vertex " << i << ", angle = " << degrees << std::endl;
224 }
225 };
226
227 test({}, {}, 2.0);
228 test({}, {10, 10}, 2.0);
229 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0);
230 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0);
231 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [511/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledEllipseTessellationVertices |
| ) |  |

Definition at line 378 of file tessellator_unittests.cc.

378 {
379 auto tessellator = std::make_shared<Tessellator>();
380
381 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
382 auto center = bounds.GetCenter();
383 auto half_size = bounds.GetSize() * 0.5f;
384
385 auto generator = tessellator->FilledEllipse(transform, bounds);
386 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
387
388 auto vertex_count = generator.GetVertexCount();
389 auto vertices = std::vector<Point>();
390 generator.GenerateVertices([&vertices](const Point& p) { //
391 vertices.push_back(p);
392 });
393 EXPECT_EQ(vertices.size(), vertex_count);
394 ASSERT_EQ(vertex_count % 4, 0u);
395
396 auto quadrant_count = vertex_count / 4;
397 for (size_t i = 0; i < quadrant_count; i++) {
398 double angle = kPiOver2 * i / (quadrant_count - 1);
399 double degrees = angle * 180.0 / kPi;
400 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
401 double rcos =
402 (i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
403 double rsin = sin(angle) * half_size.height;
404 EXPECT_POINT_NEAR(vertices[i * 2],
405 Point(center.x - rcos, center.y + rsin))
406 << "vertex " << i << ", angle = " << degrees << ", " //
407 << "bounds = " << bounds << std::endl;
408 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
409 Point(center.x - rcos, center.y - rsin))
410 << "vertex " << i << ", angle = " << degrees << ", " //
411 << "bounds = " << bounds << std::endl;
412 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
413 Point(center.x + rcos, center.y - rsin))
414 << "vertex " << i << ", angle = " << degrees << ", " //
415 << "bounds = " << bounds << std::endl;
416 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
417 Point(center.x + rcos, center.y + rsin))
418 << "vertex " << i << ", angle = " << degrees << ", " //
419 << "bounds = " << bounds << std::endl;
420 }
421 };
422
423 // Square bounds should actually use the circle generator, but its
424 // results should match the same math as the ellipse generator.
425 test({}, Rect::MakeXYWH(0, 0, 2, 2));
426
427 test({}, Rect::MakeXYWH(0, 0, 2, 3));
428 test({}, Rect::MakeXYWH(0, 0, 3, 2));
429 test({}, Rect::MakeXYWH(5, 10, 2, 3));
430 test({}, Rect::MakeXYWH(16, 7, 3, 2));
431 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
432 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
433 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
434 Rect::MakeXYWH(5000, 10000, 3000, 2000));
435 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
436 Rect::MakeXYWH(5000, 10000, 2000, 3000));
437 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [512/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | FilledRoundRectTessellationVertices |
| ) |  |

Definition at line 439 of file tessellator_unittests.cc.

439 {
440 auto tessellator = std::make_shared<Tessellator>();
441
442 auto test = [&tessellator](const Matrix& transform, const Rect& bounds,
443 const Size& radii) {
444 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
445 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
446
447 Scalar middle_left = bounds.GetX() + radii.width;
448 Scalar middle_top = bounds.GetY() + radii.height;
449 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
450 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
451
452 auto generator = tessellator->FilledRoundRect(transform, bounds, radii);
453 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
454
455 auto vertex_count = generator.GetVertexCount();
456 auto vertices = std::vector<Point>();
457 generator.GenerateVertices([&vertices](const Point& p) { //
458 vertices.push_back(p);
459 });
460 EXPECT_EQ(vertices.size(), vertex_count);
461 ASSERT_EQ(vertex_count % 4, 0u);
462
463 auto quadrant_count = vertex_count / 4;
464 for (size_t i = 0; i < quadrant_count; i++) {
465 double angle = kPiOver2 * i / (quadrant_count - 1);
466 double degrees = angle * 180.0 / kPi;
467 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
468 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
469 double rsin = sin(angle) * radii.height;
470 EXPECT_POINT_NEAR(vertices[i * 2],
471 Point(middle_left - rcos, middle_bottom + rsin))
472 << "vertex " << i << ", angle = " << degrees << ", " //
473 << "bounds = " << bounds << std::endl;
474 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
475 Point(middle_left - rcos, middle_top - rsin))
476 << "vertex " << i << ", angle = " << degrees << ", " //
477 << "bounds = " << bounds << std::endl;
478 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
479 Point(middle_right + rcos, middle_top - rsin))
480 << "vertex " << i << ", angle = " << degrees << ", " //
481 << "bounds = " << bounds << std::endl;
482 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
483 Point(middle_right + rcos, middle_bottom + rsin))
484 << "vertex " << i << ", angle = " << degrees << ", " //
485 << "bounds = " << bounds << std::endl;
486 }
487 };
488
489 // Both radii spanning the bounds should actually use the circle/ellipse
490 // generator, but their results should match the same math as the round
491 // rect generator.
492 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 10});
493
494 // One radius spanning the bounds, but not the other will not match the
495 // round rect math if the generator transfers to circle/ellipse
496 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 5});
497 test({}, Rect::MakeXYWH(0, 0, 20, 20), {5, 10});
498
499 test({}, Rect::MakeXYWH(0, 0, 20, 30), {2, 2});
500 test({}, Rect::MakeXYWH(0, 0, 30, 20), {2, 2});
501 test({}, Rect::MakeXYWH(5, 10, 20, 30), {2, 3});
502 test({}, Rect::MakeXYWH(16, 7, 30, 20), {2, 3});
503 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 30, 20),
504 {2, 3});
505 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 20, 30),
506 {2, 3});
507 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
508 Rect::MakeXYWH(5000, 10000, 3000, 2000), {50, 70});
509 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
510 Rect::MakeXYWH(5000, 10000, 2000, 3000), {50, 70});
511 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [513/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | RoundCapLineTessellationVertices |
| ) |  |

Definition at line 305 of file tessellator_unittests.cc.

305 {
306 auto tessellator = std::make_shared<Tessellator>();
307
308 auto test = [&tessellator](const Matrix& transform, const Point& p0,
309 const Point& p1, Scalar radius) {
310 auto generator = tessellator->RoundCapLine(transform, p0, p1, radius);
311 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
312
313 auto vertex_count = generator.GetVertexCount();
314 auto vertices = std::vector<Point>();
315 generator.GenerateVertices([&vertices](const Point& p) { //
316 vertices.push_back(p);
317 });
318 EXPECT_EQ(vertices.size(), vertex_count);
319 ASSERT_EQ(vertex_count % 4, 0u);
320
321 Point along = p1 - p0;
322 Scalar length = along.GetLength();
323 if (length > 0) {
324 along *= radius / length;
325 } else {
326 along = {radius, 0};
327 }
328 Point across = {-along.y, along.x};
329
330 auto quadrant_count = vertex_count / 4;
331 for (size_t i = 0; i < quadrant_count; i++) {
332 double angle = kPiOver2 * i / (quadrant_count - 1);
333 double degrees = angle * 180.0 / kPi;
334 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
335 Point relative_along =
336 along * ((i == quadrant_count - 1) ? 0.0f : cos(angle));
337 Point relative_across = across * sin(angle);
338 EXPECT_POINT_NEAR(vertices[i * 2], //
339 p0 - relative_along + relative_across)
340 << "vertex " << i << ", angle = " << degrees << ", " //
341 << "line = " << p0 << " => " << p1 << ", " //
342 << "radius = " << radius << std::endl;
343 EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
344 p0 - relative_along - relative_across)
345 << "vertex " << i << ", angle = " << degrees << ", " //
346 << "line = " << p0 << " => " << p1 << ", " //
347 << "radius = " << radius << std::endl;
348 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
349 p1 + relative_along - relative_across)
350 << "vertex " << i << ", angle = " << degrees << ", " //
351 << "line = " << p0 << " => " << p1 << ", " //
352 << "radius = " << radius << std::endl;
353 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
354 p1 + relative_along + relative_across)
355 << "vertex " << i << ", angle = " << degrees << ", " //
356 << "line = " << p0 << " => " << p1 << ", " //
357 << "radius = " << radius << std::endl;
358 }
359 };
360
361 // Empty line should actually use the circle generator, but its
362 // results should match the same math as the round cap generator.
363 test({}, {0, 0}, {0, 0}, 10);
364
365 test({}, {0, 0}, {10, 0}, 2);
366 test({}, {10, 0}, {0, 0}, 2);
367 test({}, {0, 0}, {10, 10}, 2);
368
369 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
370 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
371 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
372
373 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
374 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
375 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
376 }
impeller::TPoint::y
Type y
Definition: point.h:31

References EXPECT_POINT_NEAR, impeller::TPoint< T >::GetLength(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), transform, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [514/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | StrokedCircleTessellationVertices |
| ) |  |

Definition at line 233 of file tessellator_unittests.cc.

233 {
234 auto tessellator = std::make_shared<Tessellator>();
235
236 auto test = [&tessellator](const Matrix& transform, const Point& center,
237 Scalar radius, Scalar half_width) {
238 ASSERT_GT(radius, half_width);
239 auto generator =
240 tessellator->StrokedCircle(transform, center, radius, half_width);
241 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
242
243 auto vertex_count = generator.GetVertexCount();
244 auto vertices = std::vector<Point>();
245 generator.GenerateVertices([&vertices](const Point& p) { //
246 vertices.push_back(p);
247 });
248 EXPECT_EQ(vertices.size(), vertex_count);
249 ASSERT_EQ(vertex_count % 4, 0u);
250
251 auto quadrant_count = vertex_count / 8;
252
253 // Test outer points first
254 for (size_t i = 0; i < quadrant_count; i++) {
255 double angle = kPiOver2 * i / (quadrant_count - 1);
256 double degrees = angle * 180.0 / kPi;
257 double rsin = sin(angle) * (radius + half_width);
258 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
259 double rcos =
260 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
261 EXPECT_POINT_NEAR(vertices[i * 2],
262 Point(center.x - rcos, center.y - rsin))
263 << "vertex " << i << ", angle = " << degrees << std::endl;
264 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2],
265 Point(center.x + rsin, center.y - rcos))
266 << "vertex " << i << ", angle = " << degrees << std::endl;
267 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2],
268 Point(center.x + rcos, center.y + rsin))
269 << "vertex " << i << ", angle = " << degrees << std::endl;
270 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2],
271 Point(center.x - rsin, center.y + rcos))
272 << "vertex " << i << ", angle = " << degrees << std::endl;
273 }
274
275 // Then test innerer points
276 for (size_t i = 0; i < quadrant_count; i++) {
277 double angle = kPiOver2 * i / (quadrant_count - 1);
278 double degrees = angle * 180.0 / kPi;
279 double rsin = sin(angle) * (radius - half_width);
280 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
281 double rcos =
282 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
283 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
284 Point(center.x - rcos, center.y - rsin))
285 << "vertex " << i << ", angle = " << degrees << std::endl;
286 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2 + 1],
287 Point(center.x + rsin, center.y - rcos))
288 << "vertex " << i << ", angle = " << degrees << std::endl;
289 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2 + 1],
290 Point(center.x + rcos, center.y + rsin))
291 << "vertex " << i << ", angle = " << degrees << std::endl;
292 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2 + 1],
293 Point(center.x - rsin, center.y + rcos))
294 << "vertex " << i << ", angle = " << degrees << std::endl;
295 }
296 };
297
298 test({}, {}, 2.0, 1.0);
299 test({}, {}, 2.0, 0.5);
300 test({}, {10, 10}, 2.0, 1.0);
301 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0, 1.0);
302 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0, 10.0);
303 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [515/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellateConvex |
| ) |  |

Definition at line 96 of file tessellator_unittests.cc.

96 {
97 {
98 std::vector<Point> points;
99 std::vector<uint16_t> indices;
100 // Sanity check simple rectangle.
101 Tessellator::TessellateConvexInternal(
102 flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 10, 10)), points,
103 indices, 1.0);
104
105 // Note: the origin point is repeated but not referenced in the indices
106 // below
107 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
108 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
109 EXPECT_EQ(points, expected);
110 EXPECT_EQ(indices, expected_indices);
111 }
112
113 {
114 std::vector<Point> points;
115 std::vector<uint16_t> indices;
116 Tessellator::TessellateConvexInternal(
117 flutter::DlPath(flutter::DlPathBuilder{}
118 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
119 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
120 .TakePath()),
121 points, indices, 1.0);
122
123 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
124 {0, 0}, {20, 20}, {30, 20}, {30, 30},
125 {20, 30}, {20, 20}};
126 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
127 EXPECT_EQ(points, expected);
128 EXPECT_EQ(indices, expected_indices);
129 }
130 }

References impeller::TRect< Scalar >::MakeLTRB(), points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [516/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellateConvexUnclosedPath |
| ) |  |

Definition at line 133 of file tessellator_unittests.cc.

133 {
134 std::vector<Point> points;
135 std::vector<uint16_t> indices;
136
137 // Create a rectangle that lacks an explicit close.
138 flutter::DlPath path = flutter::DlPathBuilder{}
139 .LineTo({100, 0})
140 .LineTo({100, 100})
141 .LineTo({0, 100})
142 .TakePath();
143 Tessellator::TessellateConvexInternal(flutter::DlPath(path), points, indices,
144 1.0);
145
146 std::vector<Point> expected = {
147 {0, 0}, {100, 0}, {100, 100}, {0, 100}, {0, 0}};
148 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
149 EXPECT_EQ(points, expected);
150 EXPECT_EQ(indices, expected_indices);
151 }

References impeller::LineTo(), points, and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [517/525]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellatorBuilderReturnsCorrectResultStatus |
| ) |  |

Definition at line 16 of file tessellator_unittests.cc.

16 {
17 // Zero points.
18 {
19 TessellatorLibtess t;
20 auto path = flutter::DlPathBuilder{} //
21 .SetFillType(FillType::kOdd)
22 .TakePath();
23 TessellatorLibtess::Result result = t.Tessellate(
24 path, 1.0f,
25 [](const float* vertices, size_t vertices_count,
26 const uint16_t* indices, size_t indices_count) { return true; });
27
28 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
29 }
30
31 // One point.
32 {
33 TessellatorLibtess t;
34 auto path = flutter::DlPathBuilder{}
35 .LineTo({0, 0})
36 .SetFillType(FillType::kOdd)
37 .TakePath();
38 TessellatorLibtess::Result result = t.Tessellate(
39 path, 1.0f,
40 [](const float* vertices, size_t vertices_count,
41 const uint16_t* indices, size_t indices_count) { return true; });
42
43 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
44 }
45
46 // Two points.
47 {
48 TessellatorLibtess t;
49 auto path = flutter::DlPathBuilder{}
50 .MoveTo({0, 0})
51 .LineTo({0, 1})
52 .SetFillType(FillType::kOdd)
53 .TakePath();
54 TessellatorLibtess::Result result = t.Tessellate(
55 path, 1.0f,
56 [](const float* vertices, size_t vertices_count,
57 const uint16_t* indices, size_t indices_count) { return true; });
58
59 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
60 }
61
62 // Many points.
63 {
64 TessellatorLibtess t;
65 flutter::DlPathBuilder builder;
66 for (int i = 0; i < 1000; i++) {
67 auto coord = i * 1.0f;
68 builder.MoveTo({coord, coord}).LineTo({coord + 1, coord + 1});
69 }
70 auto path = builder.SetFillType(FillType::kOdd).TakePath();
71 TessellatorLibtess::Result result = t.Tessellate(
72 path, 1.0f,
73 [](const float* vertices, size_t vertices_count,
74 const uint16_t* indices, size_t indices_count) { return true; });
75
76 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
77 }
78
79 // Closure fails.
80 {
81 TessellatorLibtess t;
82 auto path = flutter::DlPathBuilder{}
83 .MoveTo({0, 0})
84 .LineTo({0, 1})
85 .SetFillType(FillType::kOdd)
86 .TakePath();
87 TessellatorLibtess::Result result = t.Tessellate(
88 path, 1.0f,
89 [](const float* vertices, size_t vertices_count,
90 const uint16_t* indices, size_t indices_count) { return false; });
91
92 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
93 }
94 }

References impeller::TessellatorLibtess::kInputError, impeller::kOdd, impeller::TessellatorLibtess::kSuccess, impeller::LineTo(), and impeller::TessellatorLibtess::Tessellate().

## ◆ TEST() [518/525]

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() [519/525]

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() [520/525]

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() [521/525]

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() [522/525]

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() [523/525]

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() [524/525]

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() [525/525]

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_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)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1214

References impeller::DisplayListToTexture(), and impeller::testing::Screenshotter::MakeScreenshot().

## ◆ TEST_P() [1/549]

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/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownBackdropId |
| ) |  |

Definition at line 176 of file canvas_unittests.cc.

176 {
177 ContentContext context(GetContext(), nullptr);
178 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
179 GTEST_SKIP() << "Test requires device with framebuffer fetch";
180 }
181 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
182 /*requires_readback=*/true);
183 // 3 backdrop filters all with same id.
184 std::unordered_map<int64_t, BackdropData> data;
185 data[1] = BackdropData{.backdrop_count = 3};
186 canvas->SetBackdropData(data, 3);
187
188 auto blur =
189 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
190
191 EXPECT_TRUE(canvas->RequiresReadback());
192 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
193 {.color = Color::Azure()});
194 canvas->SaveLayer({}, std::nullopt, blur.get(),
195 ContentBoundsPromise::kContainsContents,
196 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
197 /*backdrop_id=*/1);
198 canvas->Restore();
199 EXPECT_FALSE(canvas->RequiresReadback());
200
201 canvas->SaveLayer({}, std::nullopt, blur.get(),
202 ContentBoundsPromise::kContainsContents,
203 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
204 /*backdrop_id=*/1);
205 canvas->Restore();
206 EXPECT_FALSE(canvas->RequiresReadback());
207
208 canvas->SaveLayer({}, std::nullopt, blur.get(),
209 ContentBoundsPromise::kContainsContents,
210 /*total_content_depth=*/1, /*can_distribute_opacity=*/false,
211 /*backdrop_id=*/1);
212 canvas->Restore();
213 EXPECT_FALSE(canvas->RequiresReadback());
214 }
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:26

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownBackdropIdMixed |
| ) |  |

Definition at line 216 of file canvas_unittests.cc.

216 {
217 ContentContext context(GetContext(), nullptr);
218 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
219 GTEST_SKIP() << "Test requires device with framebuffer fetch";
220 }
221 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
222 /*requires_readback=*/true);
223 // 3 backdrop filters, 2 with same id.
224 std::unordered_map<int64_t, BackdropData> data;
225 data[1] = BackdropData{.backdrop_count = 2};
226 canvas->SetBackdropData(data, 3);
227
228 auto blur =
229 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
230
231 EXPECT_TRUE(canvas->RequiresReadback());
232 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
233 {.color = Color::Azure()});
234 canvas->SaveLayer({}, std::nullopt, blur.get(),
235 ContentBoundsPromise::kContainsContents, 1, false);
236 canvas->Restore();
237 EXPECT_TRUE(canvas->RequiresReadback());
238
239 canvas->SaveLayer({}, std::nullopt, blur.get(),
240 ContentBoundsPromise::kContainsContents, 1, false, 1);
241 canvas->Restore();
242 EXPECT_FALSE(canvas->RequiresReadback());
243
244 canvas->SaveLayer({}, std::nullopt, blur.get(),
245 ContentBoundsPromise::kContainsContents, 1, false, 1);
246 canvas->Restore();
247 EXPECT_FALSE(canvas->RequiresReadback());
248 }

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownNormal |
| ) |  |

Definition at line 141 of file canvas_unittests.cc.

141 {
142 ContentContext context(GetContext(), nullptr);
143 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
144 GTEST_SKIP() << "Test requires device with framebuffer fetch";
145 }
146 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
147 /*requires_readback=*/true);
148 // 3 backdrop filters
149 canvas->SetBackdropData({}, 3);
150
151 auto blur =
152 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
153 flutter::DlRect rect = flutter::DlRect::MakeLTRB(0, 0, 50, 50);
154
155 EXPECT_TRUE(canvas->RequiresReadback());
156 canvas->DrawRect(rect, {.color = Color::Azure()});
157 canvas->SaveLayer({}, rect, blur.get(),
158 ContentBoundsPromise::kContainsContents,
159 /*total_content_depth=*/1);
160 canvas->Restore();
161 EXPECT_TRUE(canvas->RequiresReadback());
162
163 canvas->SaveLayer({}, rect, blur.get(),
164 ContentBoundsPromise::kContainsContents,
165 /*total_content_depth=*/1);
166 canvas->Restore();
167 EXPECT_TRUE(canvas->RequiresReadback());
168
169 canvas->SaveLayer({}, rect, blur.get(),
170 ContentBoundsPromise::kContainsContents,
171 /*total_content_depth=*/1);
172 canvas->Restore();
173 EXPECT_FALSE(canvas->RequiresReadback());
174 }
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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropCountDownWithNestedSaveLayers |
| ) |  |

Definition at line 253 of file canvas_unittests.cc.

253 {
254 ContentContext context(GetContext(), nullptr);
255 if (!context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
256 GTEST_SKIP() << "Test requires device with framebuffer fetch";
257 }
258 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
259 /*requires_readback=*/true);
260
261 canvas->SetBackdropData({}, 2);
262
263 auto blur =
264 flutter::DlImageFilter::MakeBlur(4, 4, flutter::DlTileMode::kClamp);
265
266 EXPECT_TRUE(canvas->RequiresReadback());
267 canvas->DrawRect(flutter::DlRect::MakeLTRB(0, 0, 50, 50),
268 {.color = Color::Azure()});
269 canvas->SaveLayer({}, std::nullopt, blur.get(),
270 ContentBoundsPromise::kContainsContents,
271 /*total_content_depth=*/3);
272
273 // This filter is nested in the first saveLayer. We cannot restore to onscreen
274 // here.
275 canvas->SaveLayer({}, std::nullopt, blur.get(),
276 ContentBoundsPromise::kContainsContents,
277 /*total_content_depth=*/1);
278 canvas->Restore();
279 EXPECT_TRUE(canvas->RequiresReadback());
280
281 canvas->Restore();
282 EXPECT_TRUE(canvas->RequiresReadback());
283 }

References impeller::Color::Azure(), CreateTestCanvas(), impeller::ContentContext::GetDeviceCapabilities(), impeller::kContainsContents, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Capabilities::SupportsFramebufferFetch().

## ◆ TEST_P() [7/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BackdropFilterOverUnclosedClip |
| ) |  |

Definition at line 2146 of file aiks_dl_basic_unittests.cc.

2146 {
2147 DisplayListBuilder builder;
2148
2149 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
2150 builder.Save();
2151 {
2152 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
2153
2154 builder.Save();
2155 {
2156 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
2157 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
2158 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
2159 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
2160 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
2161 }
2162 builder.Restore();
2163
2164 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
2165 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
2166 }
2167 builder.Restore();
2168 builder.DrawCircle(DlPoint(100, 100), 100,
2169 DlPaint().setColor(DlColor::kAqua()));
2170
2171 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2172 }

## ◆ TEST_P() [8/549]

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/549]

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/549]

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/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurGradientWithOpacity |
| ) |  |

Definition at line 1343 of file aiks_dl_blur_unittests.cc.

1343 {
1344 DisplayListBuilder builder;
1345 builder.Scale(GetContentScale().x, GetContentScale().y);
1346
1347 std::vector<DlColor> colors = {DlColor(0xFFFF0000), DlColor(0xFF00FF00)};
1348 std::vector<Scalar> stops = {0.0, 1.0};
1349
1350 auto gradient = DlColorSource::MakeLinear(
1351 {0, 0}, {400, 400}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
1352
1353 DlPaint save_paint;
1354 save_paint.setOpacity(0.5);
1355 builder.SaveLayer(std::nullopt, &save_paint);
1356
1357 DlPaint paint;
1358 paint.setColorSource(gradient);
1359 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1360 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
1361
1362 builder.Restore();
1363
1364 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1365 }

References x.

## ◆ TEST_P() [13/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurHasNoEdge |
| ) |  |

Definition at line 438 of file aiks_dl_blur_unittests.cc.

438 {
439 Scalar sigma = 47.6;
440 auto callback = [&]() -> sk_sp<DisplayList> {
441 if (AiksTest::ImGuiBegin("Controls", nullptr,
442 ImGuiWindowFlags_AlwaysAutoResize)) {
443 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
444 ImGui::End();
445 }
446 DisplayListBuilder builder;
447 builder.Scale(GetContentScale().x, GetContentScale().y);
448 builder.DrawPaint({});
449
450 DlPaint paint;
451 paint.setColor(DlColor::kGreen());
452 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
453
454 builder.DrawRect(DlRect::MakeXYWH(300, 300, 200, 200), paint);
455 return builder.Build();
456 };
457
458 ASSERT_TRUE(OpenPlaygroundHere(callback));
459 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [14/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlurredRectangleWithShader |
| ) |  |

Definition at line 1196 of file aiks_dl_blur_unittests.cc.

1196 {
1197 DisplayListBuilder builder;
1198 builder.Scale(GetContentScale().x, GetContentScale().y);
1199
1200 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1201 auto draw_line = [&builder, &paint](DlPoint a, DlPoint b) {
1202 DlPath line = DlPath::MakeLine(a, b);
1203 builder.DrawPath(line, paint);
1204 };
1205 paint.setStrokeWidth(5);
1206 paint.setDrawStyle(DlDrawStyle::kStroke);
1207 draw_line(DlPoint(dx + 100, dy + 100), DlPoint(dx + 200, dy + 200));
1208 draw_line(DlPoint(dx + 100, dy + 200), DlPoint(dx + 200, dy + 100));
1209 draw_line(DlPoint(dx + 150, dy + 100), DlPoint(dx + 200, dy + 150));
1210 draw_line(DlPoint(dx + 100, dy + 150), DlPoint(dx + 150, dy + 200));
1211 };
1212
1213 AiksContext renderer(GetContext(), nullptr);
1214 DisplayListBuilder recorder_builder;
1215 for (int x = 0; x < 5; ++x) {
1216 for (int y = 0; y < 5; ++y) {
1217 DlRect rect = DlRect::MakeXYWH(x * 20, y * 20, 20, 20);
1218 DlPaint paint;
1219 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1220 : DlColor::kBlue());
1221
1222 recorder_builder.DrawRect(rect, paint);
1223 }
1224 }
1225 auto texture =
1226 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1227
1228 auto image_source = DlColorSource::MakeImage(
1229 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1230 auto blur_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kDecal);
1231
1232 DlPaint paint;
1233 paint.setColor(DlColor::kDarkGreen());
1234 builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 600), paint);
1235
1236 paint.setColorSource(image_source);
1237 builder.DrawRect(DlRect::MakeLTRB(100, 100, 200, 200), paint);
1238
1239 paint.setColorSource(nullptr);
1240 paint.setColor(DlColor::kRed());
1241 builder.DrawRect(DlRect::MakeLTRB(300, 0, 600, 600), paint);
1242
1243 paint.setColorSource(image_source);
1244 paint.setImageFilter(blur_filter);
1245 builder.DrawRect(DlRect::MakeLTRB(400, 100, 500, 200), paint);
1246
1247 paint.setImageFilter(nullptr);
1248 paint_lines(0, 300, paint);
1249
1250 paint.setImageFilter(blur_filter);
1251 paint_lines(300, 300, paint);
1252
1253 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1254 }

References impeller::saturated::b, impeller::DisplayListToTexture(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [16/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanConvertTriangleFanToTriangles |
| ) |  |

Definition at line 158 of file aiks_dl_vertices_unittests.cc.

158 {
159 constexpr Scalar hexagon_radius = 125;
160 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
161 auto center_to_flat = 1.73 / 2 * hexagon_radius;
162
163 // clang-format off
164 std::vector<DlPoint> vertices = {
165 DlPoint(hex_start.x, hex_start.y),
166 DlPoint(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
167 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
168 DlPoint(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
169 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
170 DlPoint(hex_start.x, hex_start.y + 2 * hexagon_radius),
171 DlPoint(hex_start.x - center_to_flat, hex_start.y + 1.5 * 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 + 0.5 * hexagon_radius)
174 };
175 // clang-format on
176 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
177 auto dl_vertices = flutter::DlVertices::Make(
178 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
179 nullptr, nullptr);
180 flutter::DisplayListBuilder builder;
181 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
182 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
183 }

## ◆ TEST_P() [17/549]

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/549]

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/549]

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/549]

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/549]

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/549]

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/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPerspectiveTransformWithClips |
| ) |  |

Definition at line 1373 of file aiks_dl_basic_unittests.cc.

1373 {
1374 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
1375 int time = 0;
1376 auto callback = [&]() -> sk_sp<DisplayList> {
1377 DisplayListBuilder builder;
1378
1379 builder.Save();
1380 {
1381 builder.Translate(300, 300);
1382
1383 // 1. Draw/restore a clip before drawing the image, which will get drawn
1384 // to the depth buffer behind the image.
1385 builder.Save();
1386 {
1387 DlPaint paint;
1388 paint.setColor(DlColor::kGreen());
1389 builder.DrawPaint(paint);
1390 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
1391 DlClipOp::kDifference);
1392
1393 paint.setColor(DlColor::kBlack());
1394 builder.DrawPaint(paint);
1395 }
1396 builder.Restore(); // Restore rectangle difference clip.
1397
1398 builder.Save();
1399 {
1400 // 2. Draw an oval clip that applies to the image, which will get drawn
1401 // in front of the image on the depth buffer.
1402 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
1403
1404 Matrix result =
1405 Matrix(1.0, 0.0, 0.0, 0.0, //
1406 0.0, 1.0, 0.0, 0.0, //
1407 0.0, 0.0, 1.0, 0.003, //
1408 0.0, 0.0, 0.0, 1.0) *
1409 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
1410
1411 // 3. Draw the rotating image with a perspective transform.
1412 builder.Transform(result);
1413
1414 auto image =
1415 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1416 auto position =
1417 -DlPoint(image->GetSize().width, image->GetSize().height) * 0.5;
1418 builder.DrawImage(image, position, {});
1419 }
1420 builder.Restore(); // Restore oval intersect clip.
1421
1422 // 4. Draw a semi-translucent blue circle atop all previous draws.
1423 DlPaint paint;
1424 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
1425 builder.DrawCircle(DlPoint(), 230, paint);
1426 }
1427 builder.Restore(); // Restore translation.
1428
1429 return builder.Build();
1430 };
1431 ASSERT_TRUE(OpenPlaygroundHere(callback));
1432 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::Transform().

## ◆ TEST_P() [25/549]

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/549]

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/549]

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/549]

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/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformFullScreenMSAA |
| ) |  |

Definition at line 1714 of file aiks_dl_basic_unittests.cc.

1714 {
1715 DisplayListBuilder builder;
1716
1717 DlPaint paint;
1718 paint.setColor(DlColor::kRed());
1719 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1720
1721 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1722 }

## ◆ TEST_P() [31/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBounds |
| ) |  |

Definition at line 1735 of file aiks_dl_basic_unittests.cc.

1735 {
1736 DisplayListBuilder builder;
1737
1738 DlPaint save;
1739 save.setColor(DlColor::kBlack());
1740
1741 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1742 builder.SaveLayer(save_bounds, &save);
1743
1744 DlPaint paint;
1745 paint.setColor(DlColor::kRed());
1746 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1747 paint.setColor(DlColor::kGreen());
1748 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1749 paint.setColor(DlColor::kBlue());
1750 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1751
1752 builder.Restore();
1753
1754 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1755 }

## ◆ TEST_P() [32/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated |
| ) |  |

Definition at line 1636 of file aiks_dl_basic_unittests.cc.

1637 {
1638 DisplayListBuilder builder;
1639
1640 DlPaint red;
1641 red.setColor(DlColor::kRed());
1642
1643 DlPaint green;
1644 green.setColor(DlColor::kGreen());
1645
1646 DlPaint blue;
1647 blue.setColor(DlColor::kBlue());
1648
1649 DlPaint save;
1650 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1651
1652 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1653 builder.SaveLayer(huge_bounds, &save);
1654
1655 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1656 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1657 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1658
1659 builder.Restore();
1660
1661 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1662 }

## ◆ TEST_P() [33/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSkew |
| ) |  |

Definition at line 1724 of file aiks_dl_basic_unittests.cc.

1724 {
1725 DisplayListBuilder builder;
1726
1727 DlPaint red;
1728 red.setColor(DlColor::kRed());
1729 builder.Skew(2, 5);
1730 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1731
1732 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1733 }

## ◆ TEST_P() [34/549]

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/549]

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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlur |
| ) |  |

Definition at line 241 of file aiks_dl_blur_unittests.cc.

241 {
242 DisplayListBuilder builder;
243
244 DlPaint paint;
245 paint.setColor(DlColor::kCornflowerBlue());
246 builder.DrawCircle(DlPoint(100, 100), 50, paint);
247
248 paint.setColor(DlColor::kGreenYellow());
249 builder.DrawCircle(DlPoint(300, 200), 100, paint);
250
251 paint.setColor(DlColor::kDarkMagenta());
252 builder.DrawCircle(DlPoint(140, 170), 75, paint);
253
254 paint.setColor(DlColor::kOrangeRed());
255 builder.DrawCircle(DlPoint(180, 120), 100, paint);
256
257 DlRoundRect rrect =
258 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(75, 50, 375, 275), 20, 20);
259 builder.ClipRoundRect(rrect);
260
261 DlPaint save_paint;
262 save_paint.setBlendMode(DlBlendMode::kSrc);
263 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
264 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
265 builder.Restore();
266
267 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
268 }

## ◆ TEST_P() [37/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurHugeSigma |
| ) |  |

Definition at line 351 of file aiks_dl_blur_unittests.cc.

351 {
352 DisplayListBuilder builder;
353
354 DlPaint paint;
355 paint.setColor(DlColor::kGreen());
356 builder.DrawCircle(DlPoint(400, 400), 300, paint);
357
358 DlPaint save_paint;
359 save_paint.setBlendMode(DlBlendMode::kSrc);
360
361 auto backdrop_filter =
362 DlImageFilter::MakeBlur(999999, 999999, DlTileMode::kClamp);
363 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
364 builder.Restore();
365
366 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
367 }

## ◆ TEST_P() [38/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurInteractive |
| ) |  |

Definition at line 204 of file aiks_dl_blur_unittests.cc.

204 {
205 auto callback = [&]() -> sk_sp<DisplayList> {
206 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
207 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
208 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
209
210 DisplayListBuilder builder;
211 DlPaint paint;
212 paint.setColor(DlColor::kCornflowerBlue());
213 builder.DrawCircle(DlPoint(100, 100), 50, paint);
214
215 paint.setColor(DlColor::kGreenYellow());
216 builder.DrawCircle(DlPoint(300, 200), 100, paint);
217
218 paint.setColor(DlColor::kDarkMagenta());
219 builder.DrawCircle(DlPoint(140, 170), 75, paint);
220
221 paint.setColor(DlColor::kOrangeRed());
222 builder.DrawCircle(DlPoint(180, 120), 100, paint);
223
224 DlRoundRect rrect =
225 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(a.x, a.y, b.x, b.y), 20, 20);
226 builder.ClipRoundRect(rrect);
227
228 DlPaint save_paint;
229 save_paint.setBlendMode(DlBlendMode::kSrc);
230
231 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
232 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
233 builder.Restore();
234
235 return builder.Build();
236 };
237
238 ASSERT_TRUE(OpenPlaygroundHere(callback));
239 }
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/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurWithSingleBackdropId |
| ) |  |

Definition at line 270 of file aiks_dl_blur_unittests.cc.

270 {
271 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
272
273 DisplayListBuilder builder;
274
275 DlPaint paint;
276 builder.DrawImage(image, DlPoint(50.0, 50.0),
277 DlImageSampling::kNearestNeighbor, &paint);
278
279 DlRoundRect rrect =
280 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(50, 250, 100, 100), 20, 20);
281 builder.Save();
282 builder.ClipRoundRect(rrect);
283
284 DlPaint save_paint;
285 save_paint.setBlendMode(DlBlendMode::kSrc);
286 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
287 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
288 /*backdrop_id=*/1);
289 builder.Restore();
290 builder.Restore();
291
292 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
293 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [40/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedBackdropFilter |
| ) |  |

Definition at line 1334 of file aiks_dl_basic_unittests.cc.

1334 {
1335 DisplayListBuilder builder;
1336
1337 builder.Scale(GetContentScale().x, GetContentScale().y);
1338
1339 // Draw something interesting in the background.
1340 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1341 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
1342 std::vector<Scalar> stops = {
1343 0.0,
1344 1.0,
1345 };
1346 DlPaint paint;
1347 paint.setColorSource(DlColorSource::MakeLinear(
1348 /*start_point=*/DlPoint(0, 0), //
1349 /*end_point=*/DlPoint(100, 100), //
1350 /*stop_count=*/2, //
1351 /*colors=*/colors.data(), //
1352 /*stops=*/stops.data(), //
1353 /*tile_mode=*/DlTileMode::kRepeat //
1354 ));
1355
1356 builder.DrawPaint(paint);
1357
1358 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
1359 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
1360
1361 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
1362 // the same.
1363 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
1364
1365 DlPaint save_paint;
1366 auto backdrop_filter = DlImageFilter::MakeColorFilter(
1367 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
1368 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
1369
1370 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1371 }

References x.

## ◆ TEST_P() [41/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedBlur |
| ) |  |

Definition at line 369 of file aiks_dl_blur_unittests.cc.

369 {
370 DisplayListBuilder builder;
371 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
372
373 DlPaint paint;
374 paint.setColor(DlColor::kGreen());
375 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
376 builder.DrawCircle(DlPoint(400, 400), 200, paint);
377 builder.Restore();
378
379 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
380 }

## ◆ TEST_P() [42/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedLayers |
| ) |  |

Definition at line 1969 of file aiks_dl_basic_unittests.cc.

1969 {
1970 DisplayListBuilder builder;
1971
1972 DlPaint paint;
1973 paint.setColor(DlColor::kWhite());
1974 builder.DrawPaint(paint);
1975
1976 // Draw a green circle on the screen.
1977 {
1978 // Increase the clip depth for the savelayer to contend with.
1979 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
1980 builder.ClipPath(path);
1981
1982 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
1983 DlPaint save_paint;
1984 builder.SaveLayer(bounds, &save_paint);
1985
1986 // Fill the layer with white.
1987 paint.setColor(DlColor::kWhite());
1988 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1989 // Fill the layer with green, but do so with a color blend that can't be
1990 // collapsed into the parent pass.
1991 paint.setColor(DlColor::kGreen());
1992 paint.setBlendMode(DlBlendMode::kHardLight);
1993 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1994 }
1995
1996 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1997 }

## ◆ TEST_P() [43/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedRuntimeEffects |
| ) |  |

Definition at line 40 of file aiks_dl_runtime_effect_unittests.cc.

40 {
41 struct FragUniforms {
42 Vector2 iResolution;
43 Scalar iTime;
44 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
45 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
46 uniform_data->resize(sizeof(FragUniforms));
47 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
48
49 DlPaint paint;
50 paint.setColorSource(
51 MakeRuntimeEffect(this, "runtime_stage_example.frag.iplr", uniform_data));
52
53 DisplayListBuilder builder;
54 builder.Save();
55 builder.ClipRoundRect(
56 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 400, 400), 10.0, 10.0),
57 DlClipOp::kIntersect);
58 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
59 builder.Restore();
60
61 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
62 }

## ◆ TEST_P() [44/549]

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() [45/549]

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() [46/549]

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() [47/549]

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() [48/549]

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() [49/549]

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() [50/549]

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() [51/549]

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() [52/549]

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() [53/549]

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() [54/549]

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() [55/549]

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() [56/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrame |
| ) |  |

Definition at line 383 of file aiks_dl_text_unittests.cc.

383 {
384 DisplayListBuilder builder;
385
386 DlPaint paint;
387 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
388 builder.DrawPaint(paint);
389
390 ASSERT_TRUE(RenderTextInCanvasSkia(
391 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
392 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
393 }
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:45
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_dl_text_unittests.cc:376

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [57/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrameWithAlpha |
| ) |  |

Definition at line 411 of file aiks_dl_text_unittests.cc.

411 {
412 DisplayListBuilder builder;
413
414 DlPaint paint;
415 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
416 builder.DrawPaint(paint);
417
418 ASSERT_TRUE(RenderTextInCanvasSkia(
419 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
420 {.color = DlColor::kBlack().modulateOpacity(0.5)}));
421 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
422 }

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [58/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrameWithBlur |
| ) |  |

Definition at line 395 of file aiks_dl_text_unittests.cc.

395 {
396 DisplayListBuilder builder;
397
398 builder.Scale(GetContentScale().x, GetContentScale().y);
399 DlPaint paint;
400 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
401 builder.DrawPaint(paint);
402
403 ASSERT_TRUE(RenderTextInCanvasSkia(
404 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
405 TextRenderOptions{
406 .color = DlColor::kBlue(),
407 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
408 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
409 }

References impeller::testing::TextRenderOptions::color, kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [59/549]

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() [60/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundAdvancedBlendWithMaskBlur |
| ) |  |

Definition at line 183 of file aiks_dl_blur_unittests.cc.

183 {
184 // This case triggers the ForegroundAdvancedBlend path. The color filter
185 // should apply to the color only, and respect the alpha mask.
186 DisplayListBuilder builder;
187 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
188
189 DlPaint paint;
190 paint.setColor(
191 DlColor::RGBA(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1.0f));
192
193 Sigma sigma = Radius(20);
194 paint.setMaskFilter(
195 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
196 paint.setColorFilter(
197 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kColor));
198 builder.DrawCircle(DlPoint(400, 400), 200, paint);
199 builder.Restore();
200
201 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
202 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [61/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundBlendWithMaskBlur |
| ) |  |

Definition at line 164 of file aiks_dl_blur_unittests.cc.

164 {
165 // This case triggers the ForegroundPorterDuffBlend path. The color filter
166 // should apply to the color only, and respect the alpha mask.
167 DisplayListBuilder builder;
168 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
169
170 DlPaint paint;
171 paint.setColor(DlColor::kWhite());
172
173 Sigma sigma = Radius(20);
174 paint.setMaskFilter(
175 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
176 paint.setColorFilter(
177 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kSrc));
178 builder.DrawCircle(DlPoint(400, 400), 200, paint);
179
180 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
181 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [62/549]

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() [63/549]

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() [64/549]

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() [65/549]

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() [66/549]

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() [67/549]

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() [68/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderItalicizedText |
| ) |  |

Definition at line 363 of file aiks_dl_text_unittests.cc.

363 {
364 DisplayListBuilder builder;
365
366 DlPaint paint;
367 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
368 builder.DrawPaint(paint);
369
370 ASSERT_TRUE(RenderTextInCanvasSkia(
371 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
372 "HomemadeApple.ttf"));
373 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
374 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [69/549]

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() [70/549]

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() [71/549]

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() [72/549]

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() [73/549]

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() [74/549]

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() [75/549]

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() [76/549]

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() [77/549]

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() [78/549]

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() [79/549]

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() [80/549]

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() [81/549]

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() [82/549]

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() [83/549]

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() [84/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMaskBlurHugeSigma |
| ) |  |

Definition at line 152 of file aiks_dl_blur_unittests.cc.

152 {
153 DisplayListBuilder builder;
154
155 DlPaint paint;
156 paint.setColor(DlColor::kGreen());
157 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 99999));
158 builder.DrawCircle(DlPoint(400, 400), 300, paint);
159 builder.Restore();
160
161 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
162 }

## ◆ TEST_P() [85/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropId |
| ) |  |

Definition at line 295 of file aiks_dl_blur_unittests.cc.

295 {
296 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
297
298 DisplayListBuilder builder;
299
300 DlPaint paint;
301 builder.DrawImage(image, DlPoint(50.0, 50.0),
302 DlImageSampling::kNearestNeighbor, &paint);
303
304 for (int i = 0; i < 6; i++) {
305 DlRoundRect rrect = DlRoundRect::MakeRectXY(
306 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
307 builder.Save();
308 builder.ClipRoundRect(rrect);
309
310 DlPaint save_paint;
311 save_paint.setBlendMode(DlBlendMode::kSrc);
312 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
313 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
314 /*backdrop_id=*/1);
315 builder.Restore();
316 builder.Restore();
317 }
318
319 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
320 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [86/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters |
| ) |  |

Definition at line 322 of file aiks_dl_blur_unittests.cc.

323 {
324 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
325
326 DisplayListBuilder builder;
327
328 DlPaint paint;
329 builder.DrawImage(image, DlPoint(50.0, 50.0),
330 DlImageSampling::kNearestNeighbor, &paint);
331
332 for (int i = 0; i < 6; i++) {
333 DlRoundRect rrect = DlRoundRect::MakeRectXY(
334 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
335 builder.Save();
336 builder.ClipRoundRect(rrect);
337
338 DlPaint save_paint;
339 save_paint.setBlendMode(DlBlendMode::kSrc);
340 auto backdrop_filter =
341 DlImageFilter::MakeBlur(30 + i, 30, DlTileMode::kClamp);
342 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
343 /*backdrop_id=*/1);
344 builder.Restore();
345 builder.Restore();
346 }
347
348 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
349 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [87/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers |
| ) |  |

Definition at line 1307 of file aiks_dl_blur_unittests.cc.

1308 {
1309 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1310
1311 DisplayListBuilder builder;
1312
1313 DlPaint paint;
1314 builder.DrawImage(image, DlPoint(50.0, 50.0),
1315 DlImageSampling::kNearestNeighbor, &paint);
1316
1317 for (int i = 0; i < 6; i++) {
1318 if (i != 0) {
1319 DlPaint paint;
1320 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1321 builder.SaveLayer(std::nullopt, &paint);
1322 }
1323 DlRoundRect rrect = DlRoundRect::MakeRectXY(
1324 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1325 builder.Save();
1326 builder.ClipRoundRect(rrect);
1327
1328 DlPaint save_paint;
1329 save_paint.setBlendMode(DlBlendMode::kSrc);
1330 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1331 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
1332 /*backdrop_id=*/1);
1333 builder.Restore();
1334 builder.Restore();
1335 if (i != 0) {
1336 builder.Restore();
1337 }
1338 }
1339
1340 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1341 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [88/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderNestedBackdropBlur |
| ) |  |

Definition at line 1371 of file aiks_dl_blur_unittests.cc.

1371 {
1372 int64_t count = 0;
1373 auto callback = [&]() -> sk_sp<DisplayList> {
1374 DisplayListBuilder builder;
1375
1376 Scalar freq = 1.0;
1377 Scalar amp = 50.0;
1378 Scalar offset = amp * sin(freq * 2.0 * M_PI * count / 60.0);
1379
1380 // Draw some background content to be blurred.
1381 DlPaint paint;
1382 paint.setColor(DlColor::kCornflowerBlue());
1383 builder.DrawCircle(DlPoint(100 + offset, 100), 50, paint);
1384 paint.setColor(DlColor::kGreenYellow());
1385 builder.DrawCircle(DlPoint(300, 200 + offset), 100, paint);
1386 paint.setColor(DlColor::kDarkMagenta());
1387 builder.DrawCircle(DlPoint(140, 170), 75, paint);
1388 paint.setColor(DlColor::kOrangeRed());
1389 builder.DrawCircle(DlPoint(180 + offset, 120 + offset), 100, paint);
1390
1391 // This is the first backdrop blur, simulating the navigation transition.
1392 auto backdrop_filter1 = DlImageFilter::MakeBlur(15, 15, DlTileMode::kClamp);
1393 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter1.get());
1394
1395 // Draw the semi-transparent container from the second screen.
1396 DlPaint transparent_paint;
1397 transparent_paint.setColor(DlColor::kWhite().withAlpha(0.1 * 255));
1398 builder.DrawPaint(transparent_paint);
1399
1400 {
1401 // This is the second, nested backdrop blur.
1402 auto backdrop_filter2 =
1403 DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
1404 builder.Save();
1405 builder.ClipRect(DlRect::MakeXYWH(150, 150, 300, 300));
1406 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter2.get());
1407 builder.Restore(); // Restore from SaveLayer
1408 builder.Restore(); // Restore from ClipRect
1409 }
1410
1411 builder.Restore(); // Restore from the first SaveLayer
1412
1413 count++;
1414 return builder.Build();
1415 };
1416 ASSERT_TRUE(OpenPlaygroundHere(callback));
1417 }

## ◆ TEST_P() [89/549]

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() [90/549]

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() [91/549]

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() [92/549]

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() [93/549]

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() [94/549]

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() [95/549]

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() [96/549]

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() [97/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRuntimeEffectFilter |
| ) |  |

Definition at line 85 of file aiks_dl_runtime_effect_unittests.cc.

85 {
86 auto runtime_stages =
87 OpenAssetAsRuntimeStage("runtime_stage_filter_example.frag.iplr");
88
89 std::shared_ptr<RuntimeStage> runtime_stage =
90 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
91 ASSERT_TRUE(runtime_stage);
92 ASSERT_TRUE(runtime_stage->IsDirty());
93
94 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
95 nullptr,
96 };
97 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
98 uniform_data->resize(sizeof(Vector2));
99
100 DlPaint paint;
101 paint.setColor(DlColor::kAqua());
102 paint.setImageFilter(DlImageFilter::MakeRuntimeEffect(
103 DlRuntimeEffectImpeller::Make(runtime_stage), sampler_inputs,
104 uniform_data));
105
106 DisplayListBuilder builder;
107 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
108
109 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
110 }
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:33

References flutter::DlRuntimeEffectImpeller::Make(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [98/549]

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() [99/549]

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() [100/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokedTextFrame |
| ) |  |

Definition at line 127 of file aiks_dl_text_unittests.cc.

127 {
128 DisplayListBuilder builder;
129
130 DlPaint paint;
131 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
132 builder.DrawPaint(paint);
133
134 ASSERT_TRUE(RenderTextInCanvasSkia(
135 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
136 "Roboto-Regular.ttf",
137 {
138 .stroke = true,
139 }));
140 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
141 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [101/549]

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() [102/549]

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() [103/549]

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() [104/549]

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() [105/549]

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() [106/549]

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() [107/549]

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() [108/549]

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() [109/549]

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() [110/549]

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() [111/549]

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() [112/549]

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() [113/549]

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() [114/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrame |
| ) |  |

Definition at line 98 of file aiks_dl_text_unittests.cc.

98 {
99 DisplayListBuilder builder;
100
101 DlPaint paint;
102 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
103 builder.DrawPaint(paint);
104 ASSERT_TRUE(RenderTextInCanvasSkia(
105 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
106 "Roboto-Regular.ttf"));
107
108 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
109 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [115/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithFractionScaling |
| ) |  |

Definition at line 252 of file aiks_dl_text_unittests.cc.

252 {
253 Scalar fine_scale = 0.f;
254 bool is_subpixel = false;
255 auto callback = [&]() -> sk_sp<DisplayList> {
256 if (AiksTest::ImGuiBegin("Controls", nullptr,
257 ImGuiWindowFlags_AlwaysAutoResize)) {
258 ImGui::SliderFloat("Fine Scale", &fine_scale, -1, 1);
259 ImGui::Checkbox("subpixel", &is_subpixel);
260 ImGui::End();
261 }
262
263 DisplayListBuilder builder;
264 DlPaint paint;
265 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
266 builder.DrawPaint(paint);
267 Scalar scale = 2.625 + fine_scale;
268 builder.Scale(scale, scale);
269 RenderTextInCanvasSkia(GetContext(), builder,
270 "the quick brown fox jumped over the lazy dog!.?",
271 "Roboto-Regular.ttf",
272 TextRenderOptions{.is_subpixel = is_subpixel});
273 return builder.Build();
274 };
275
276 ASSERT_TRUE(OpenPlaygroundHere(callback));
277 }
is_subpixel
bool is_subpixel
Definition: text_contents_unittests.cc:28

References impeller::testing::TextRenderOptions::is_subpixel, is_subpixel, and RenderTextInCanvasSkia().

## ◆ TEST_P() [116/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithHalfScaling |
| ) |  |

Definition at line 159 of file aiks_dl_text_unittests.cc.

159 {
160 DisplayListBuilder builder;
161
162 DlPaint paint;
163 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
164 builder.DrawPaint(paint);
165 builder.Scale(0.5, 0.5);
166
167 ASSERT_TRUE(RenderTextInCanvasSkia(
168 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
169 "Roboto-Regular.ttf"));
170 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
171 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [117/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithInvertedTransform |
| ) |  |

Definition at line 111 of file aiks_dl_text_unittests.cc.

111 {
112 DisplayListBuilder builder;
113
114 DlPaint paint;
115 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
116 builder.DrawPaint(paint);
117 builder.Translate(1000, 0);
118 builder.Scale(-1, 1);
119
120 ASSERT_TRUE(RenderTextInCanvasSkia(
121 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
122 "Roboto-Regular.ttf"));
123
124 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
125 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [118/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameWithScalingOverflow |
| ) |  |

Definition at line 223 of file aiks_dl_text_unittests.cc.

223 {
224 Scalar scale = 60.0;
225 Scalar offsetx = -500.0;
226 Scalar offsety = 700.0;
227 auto callback = [&]() -> sk_sp<DisplayList> {
228 if (AiksTest::ImGuiBegin("Controls", nullptr,
229 ImGuiWindowFlags_AlwaysAutoResize)) {
230 ImGui::SliderFloat("scale", &scale, 1.f, 300.f);
231 ImGui::SliderFloat("offsetx", &offsetx, -600.f, 100.f);
232 ImGui::SliderFloat("offsety", &offsety, 600.f, 2048.f);
233 ImGui::End();
234 }
235 DisplayListBuilder builder;
236 builder.Scale(GetContentScale().x, GetContentScale().y);
237 DlPaint paint;
238 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
239 builder.DrawPaint(paint);
240 builder.Scale(scale, scale);
241
242 RenderTextInCanvasSkia(
243 GetContext(), builder, "test", "Roboto-Regular.ttf",
244 TextRenderOptions{
245 .position = DlPoint(offsetx / scale, offsety / scale),
246 });
247 return builder.Build();
248 };
249 ASSERT_TRUE(OpenPlaygroundHere(callback));
250 }

References impeller::testing::TextRenderOptions::position, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [119/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextInSaveLayer |
| ) |  |

Definition at line 424 of file aiks_dl_text_unittests.cc.

424 {
425 DisplayListBuilder builder;
426
427 DlPaint paint;
428 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
429 builder.DrawPaint(paint);
430
431 builder.Translate(100, 100);
432 builder.Scale(0.5, 0.5);
433
434 // Blend the layer with the parent pass using kClear to expose the coverage.
435 paint.setBlendMode(DlBlendMode::kClear);
436 builder.SaveLayer(std::nullopt, &paint);
437 ASSERT_TRUE(RenderTextInCanvasSkia(
438 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
439 "Roboto-Regular.ttf"));
440 builder.Restore();
441
442 // Render the text again over the cleared coverage rect.
443 ASSERT_TRUE(RenderTextInCanvasSkia(
444 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
445 "Roboto-Regular.ttf"));
446
447 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
448 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [120/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextOutsideBoundaries |
| ) |  |

Definition at line 450 of file aiks_dl_text_unittests.cc.

450 {
451 DisplayListBuilder builder;
452 builder.Translate(200, 150);
453
454 // Construct the text blob.
455 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
456 ASSERT_NE(mapping, nullptr);
457
458 Scalar font_size = 80;
459 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
460 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
461
462 DlPaint text_paint;
463 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
464
465 struct {
466 DlPoint position;
467 const char* text;
468 } text[] = {{DlPoint(0, 0), "0F0F0F0"},
469 {DlPoint(1, 2), "789"},
470 {DlPoint(1, 3), "456"},
471 {DlPoint(1, 4), "123"},
472 {DlPoint(0, 6), "0F0F0F0"}};
473 for (auto& t : text) {
474 builder.Save();
475 builder.Translate(t.position.x * font_size * 2,
476 t.position.y * font_size * 1.1);
477 {
478 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
479 ASSERT_NE(blob, nullptr);
480 auto frame = MakeTextFrameFromTextBlobSkia(blob);
481 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
482 }
483 builder.Restore();
484 }
485
486 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
487 }
font_size
Scalar font_size
Definition: text_contents_unittests.cc:27

References font_size, flutter::DlTextImpeller::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [121/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextStrokeWidth |
| ) |  |

Definition at line 143 of file aiks_dl_text_unittests.cc.

143 {
144 DisplayListBuilder builder;
145
146 DlPaint paint;
147 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
148 builder.DrawPaint(paint);
149
150 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
151 "Roboto-Medium.ttf",
152 {
153 .stroke = true,
154 .stroke_width = 4,
155 }));
156 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
157 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [122/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextWithLargePerspectiveTransform |
| ) |  |

Definition at line 547 of file aiks_dl_text_unittests.cc.

547 {
548 // Verifies that text scales are clamped to work around
549 // https://github.com/flutter/flutter/issues/136112 .
550
551 DisplayListBuilder builder;
552
553 DlPaint save_paint;
554 builder.SaveLayer(std::nullopt, &save_paint);
555 builder.Transform(Matrix(2000, 0, 0, 0, //
556 0, 2000, 0, 0, //
557 0, 0, -1, 9000, //
558 0, 0, -1, 7000 //
559 ));
560
561 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
562 "Roboto-Regular.ttf"));
563 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
564 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [123/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextWithPerspectiveTransformInSublist |
| ) |  |

Definition at line 566 of file aiks_dl_text_unittests.cc.

566 {
567 DisplayListBuilder text_builder;
568 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
569 "Roboto-Regular.ttf"));
570 auto text_display_list = text_builder.Build();
571
572 DisplayListBuilder builder;
573
574 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
575 0.0, 2.0, 0.0, 0.0, //
576 0.0, 0.0, 1.0, 0.0, //
577 0.0, 0.002, 0.0, 1.0);
578
579 DlPaint save_paint;
580 DlRect window_bounds =
581 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
582 builder.SaveLayer(window_bounds, &save_paint);
583 builder.Transform(matrix);
584 builder.DrawDisplayList(text_display_list, 1.0f);
585 builder.Restore();
586
587 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
588 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [124/549]

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() [125/549]

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() [126/549]

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() [127/549]

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() [128/549]

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() [129/549]

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() [130/549]

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() [131/549]

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() [132/549]

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() [133/549]

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() [134/549]

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() [135/549]

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() [136/549]

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() [137/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCanPushPopCTM |
| ) |  |

Definition at line 112 of file canvas_unittests.cc.

112 {
113 ContentContext context(GetContext(), nullptr);
114 auto canvas = CreateTestCanvas(context);
115
116 ASSERT_EQ(canvas->GetSaveCount(), 1u);
117 ASSERT_EQ(canvas->Restore(), false);
118
119 canvas->Translate(Size{100, 100});
120 canvas->Save(10);
121 ASSERT_EQ(canvas->GetSaveCount(), 2u);
122 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
123 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
124 ASSERT_TRUE(canvas->Restore());
125 ASSERT_EQ(canvas->GetSaveCount(), 1u);
126 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
127 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
128 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [138/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCTMCanBeUpdated |
| ) |  |

Definition at line 130 of file canvas_unittests.cc.

130 {
131 ContentContext context(GetContext(), nullptr);
132 auto canvas = CreateTestCanvas(context);
133
134 Matrix identity;
135 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
136 canvas->Translate(Size{100, 100});
137 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
138 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
139 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [139/549]

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() [140/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearBlendWithBlur |
| ) |  |

Definition at line 423 of file aiks_dl_blur_unittests.cc.

423 {
424 DisplayListBuilder builder;
425 DlPaint paint;
426 paint.setColor(DlColor::kBlue());
427 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
428
429 DlPaint clear;
430 clear.setBlendMode(DlBlendMode::kClear);
431 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
432
433 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
434
435 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
436 }

## ◆ TEST_P() [141/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearColorOptimizationWhenSubpassIsBiggerThanParentPass |
| ) |  |

Definition at line 1580 of file aiks_dl_basic_unittests.cc.

1580 {
1581 SetWindowSize({400, 400});
1582 DisplayListBuilder builder;
1583
1584 builder.Scale(GetContentScale().x, GetContentScale().y);
1585
1586 DlPaint paint;
1587 paint.setColor(DlColor::kRed());
1588 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1589
1590 paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1591 DlImageSampling::kLinear));
1592 builder.SaveLayer(std::nullopt, &paint);
1593 // Draw a rectangle that would fully cover the parent pass size, but not
1594 // the subpass that it is rendered in.
1595 paint.setColor(DlColor::kGreen());
1596 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1597 // Draw a bigger rectangle to force the subpass to be bigger.
1598
1599 paint.setColor(DlColor::kRed());
1600 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1601 builder.Restore();
1602
1603 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1604 }

References x.

## ◆ TEST_P() [142/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectly |
| ) |  |

Definition at line 406 of file aiks_dl_blur_unittests.cc.

406 {
407 DisplayListBuilder builder;
408 builder.Translate(0, -400);
409 DlPaint paint;
410
411 Sigma sigma = Radius{120 * 3};
412 paint.setMaskFilter(
413 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
414 paint.setColor(DlColor::kRed());
415
416 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
417 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
418 builder.DrawPath(path, paint);
419
420 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
421 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [143/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectlyInteractive |
| ) |  |

Definition at line 382 of file aiks_dl_blur_unittests.cc.

382 {
383 auto callback = [&]() -> sk_sp<DisplayList> {
384 static PlaygroundPoint playground_point(Point(400, 400), 20,
385 Color::Green());
386 auto point = DrawPlaygroundPoint(playground_point);
387
388 DisplayListBuilder builder;
389 auto location = point - Point(400, 400);
390 builder.Translate(location.x, location.y);
391
392 DlPaint paint;
393 Sigma sigma = Radius{120 * 3};
394 paint.setMaskFilter(
395 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
396 paint.setColor(DlColor::kRed());
397
398 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
399 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
400 builder.DrawPath(path, paint);
401 return builder.Build();
402 };
403 ASSERT_TRUE(OpenPlaygroundHere(callback));
404 }
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:11

References impeller::DrawPlaygroundPoint(), impeller::Color::Green(), and impeller::Sigma::sigma.

## ◆ TEST_P() [144/549]

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() [145/549]

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() [146/549]

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() [147/549]

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() [148/549]

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() [149/549]

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() [150/549]

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() [151/549]

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() [152/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoordinateConversionsAreCorrect |
| ) |  |

Definition at line 1678 of file aiks_dl_basic_unittests.cc.

1678 {
1679 DisplayListBuilder builder;
1680
1681 // Render a texture directly.
1682 {
1683 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1684
1685 builder.Save();
1686 builder.Translate(100, 200);
1687 builder.Scale(0.5, 0.5);
1688 builder.DrawImage(image, DlPoint(100.0, 100.0),
1689 DlImageSampling::kNearestNeighbor);
1690 builder.Restore();
1691 }
1692
1693 // Render an offscreen rendered texture.
1694 {
1695 DlPaint alpha;
1696 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1697
1698 builder.SaveLayer(std::nullopt, &alpha);
1699
1700 DlPaint paint;
1701 paint.setColor(DlColor::kRed());
1702 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1703 paint.setColor(DlColor::kGreen());
1704 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1705 paint.setColor(DlColor::kBlue());
1706 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1707
1708 builder.Restore();
1709 }
1710
1711 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1712 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [153/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoverageOriginShouldBeAccountedForInSubpasses |
| ) |  |

Definition at line 1859 of file aiks_dl_basic_unittests.cc.

1859 {
1860 auto callback = [&]() -> sk_sp<DisplayList> {
1861 DisplayListBuilder builder;
1862 builder.Scale(GetContentScale().x, GetContentScale().y);
1863
1864 DlPaint alpha;
1865 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1866
1867 auto current = Point{25, 25};
1868 const auto offset = Point{25, 25};
1869 const auto size = Size(100, 100);
1870
1871 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1872 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1873 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1874 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1875
1876 DlPaint stroke_paint;
1877 stroke_paint.setColor(DlColor::kYellow());
1878 stroke_paint.setStrokeWidth(5);
1879 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1880 builder.DrawRect(bounds, stroke_paint);
1881
1882 builder.SaveLayer(bounds, &alpha);
1883
1884 DlPaint paint;
1885 paint.setColor(DlColor::kRed());
1886 builder.DrawRect(
1887 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1888
1889 paint.setColor(DlColor::kGreen());
1890 current += offset;
1891 builder.DrawRect(
1892 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1893
1894 paint.setColor(DlColor::kBlue());
1895 current += offset;
1896 builder.DrawRect(
1897 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1898
1899 builder.Restore();
1900
1901 return builder.Build();
1902 };
1903
1904 ASSERT_TRUE(OpenPlaygroundHere(callback));
1905 }

References impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [154/549]

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() [155/549]

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() [156/549]

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() [157/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DifferenceClipsMustRenderIdenticallyAcrossBackends |
| ) |  |

Definition at line 632 of file aiks_dl_text_unittests.cc.

632 {
633 DisplayListBuilder builder;
634
635 DlPaint paint;
636 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
637 paint.setColor(clear_color);
638 builder.DrawPaint(paint);
639
640 DlMatrix identity = {
641 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
642 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
643 };
644 builder.Save();
645 builder.Transform(identity);
646
647 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
648 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
649 paint.setColor(white);
650 builder.DrawRect(frame, paint);
651
652 builder.Save();
653 builder.ClipRect(frame, DlClipOp::kIntersect);
654
655 DlMatrix rect_xform = {
656 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
657 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
658 };
659 builder.Save();
660 builder.Transform(rect_xform);
661
662 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
663 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
664 paint.setColor(bluish);
665 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
666 builder.DrawRoundRect(rrect, paint);
667
668 builder.Save();
669 builder.ClipRect(rect, DlClipOp::kIntersect);
670 builder.Restore();
671
672 builder.Restore();
673
674 DlMatrix path_xform = {
675 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
676 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
677 };
678 builder.Save();
679 builder.Transform(path_xform);
680
681 DlPathBuilder path_builder;
682 path_builder.MoveTo(DlPoint(87.5, 349.5));
683 path_builder.LineTo(DlPoint(25.0, 29.5));
684 path_builder.LineTo(DlPoint(150.0, 118.0));
685 path_builder.LineTo(DlPoint(25.0, 118.0));
686 path_builder.LineTo(DlPoint(150.0, 29.5));
687 path_builder.Close();
688 DlPath path = path_builder.TakePath();
689
690 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
691 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
692 paint.setColor(fill_color);
693 paint.setDrawStyle(DlDrawStyle::kFill);
694 builder.DrawPath(path, paint);
695
696 paint.setColor(stroke_color);
697 paint.setStrokeWidth(2.0);
698 paint.setDrawStyle(DlDrawStyle::kStroke);
699 builder.DrawPath(path, paint);
700
701 builder.Restore();
702 builder.Restore();
703 builder.Restore();
704
705 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
706 }

## ◆ TEST_P() [158/549]

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() [159/549]

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() [160/549]

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() [161/549]

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() [162/549]

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() [163/549]

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() [164/549]

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() [165/549]

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() [166/549]

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() [167/549]

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() [168/549]

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() [169/549]

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() [170/549]

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() [171/549]

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() [172/549]

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() [173/549]

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() [174/549]

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() [175/549]

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() [176/549]

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() [177/549]

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() [178/549]

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(), and x.

## ◆ TEST_P() [179/549]

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() [180/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintTransformsBounds |
| ) |  |

Definition at line 64 of file aiks_dl_runtime_effect_unittests.cc.

64 {
65 struct FragUniforms {
66 Size size;
67 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
68 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
69 uniform_data->resize(sizeof(FragUniforms));
70 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
71
72 DlPaint paint;
73 paint.setColorSource(
74 MakeRuntimeEffect(this, "gradient.frag.iplr", uniform_data));
75
76 DisplayListBuilder builder;
77 builder.Save();
78 builder.Scale(GetContentScale().x, GetContentScale().y);
79 builder.DrawPaint(paint);
80 builder.Restore();
81
82 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
83 }

References impeller::TSize< Scalar >::MakeWH(), and x.

## ◆ TEST_P() [181/549]

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() [182/549]

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() [183/549]

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() [184/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveNoSaveLayer |
| ) |  |

Definition at line 508 of file aiks_dl_text_unittests.cc.

508 {
509 DisplayListBuilder builder;
510
511 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
512 0.0, 1.0, 0.0, 0.0, //
513 0.0, 0.0, 1.0, 0.01, //
514 0.0, 0.0, 0.0, 1.0) * //
515 Matrix::MakeRotationY({Degrees{10}});
516
517 builder.Transform(matrix);
518
519 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
520 "Roboto-Regular.ttf"));
521 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
522 }

References RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [185/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveSaveLayer |
| ) |  |

Definition at line 524 of file aiks_dl_text_unittests.cc.

524 {
525 DisplayListBuilder builder;
526
527 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
528 0.0, 1.0, 0.0, 0.0, //
529 0.0, 0.0, 1.0, 0.01, //
530 0.0, 0.0, 0.0, 1.0) * //
531 Matrix::MakeRotationY({Degrees{10}});
532
533 DlPaint save_paint;
534 DlRect window_bounds =
535 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
536 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
537 builder.SaveLayer(window_bounds, &save_paint);
538 builder.Transform(matrix);
539
540 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
541 "Roboto-Regular.ttf"));
542
543 builder.Restore();
544 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
545 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [186/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinates |
| ) |  |

Definition at line 272 of file aiks_dl_vertices_unittests.cc.

272 {
273 auto texture = CreateTextureForFixture("embarcadero.jpg");
274 auto dl_image = DlImageImpeller::Make(texture);
275 std::vector<DlPoint> positions = {
276 DlPoint(100, 300),
277 DlPoint(200, 100),
278 DlPoint(300, 300),
279 };
280 std::vector<DlPoint> texture_coordinates = {
281 DlPoint(0, 0),
282 DlPoint(100, 200),
283 DlPoint(200, 100),
284 };
285
286 auto vertices = flutter::DlVertices::Make(
287 flutter::DlVertexMode::kTriangles, 3, positions.data(),
288 texture_coordinates.data(), /*colors=*/nullptr);
289
290 flutter::DisplayListBuilder builder;
291 flutter::DlPaint paint;
292
293 auto image_source = flutter::DlColorSource::MakeImage(
294 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
295
296 paint.setColorSource(image_source);
297 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
298
299 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
300 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [187/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending |
| ) |  |

Definition at line 302 of file aiks_dl_vertices_unittests.cc.

303 {
304 auto texture = CreateTextureForFixture("embarcadero.jpg");
305 auto dl_image = DlImageImpeller::Make(texture);
306 std::vector<DlPoint> positions = {
307 DlPoint(100, 300),
308 DlPoint(200, 100),
309 DlPoint(300, 300),
310 };
311 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
312 flutter::DlColor::kGreen(),
313 flutter::DlColor::kWhite()};
314 std::vector<DlPoint> texture_coordinates = {
315 DlPoint(0, 0),
316 DlPoint(100, 200),
317 DlPoint(200, 100),
318 };
319
320 auto vertices = flutter::DlVertices::Make(
321 flutter::DlVertexMode::kTriangles, 3, positions.data(),
322 texture_coordinates.data(), colors.data());
323
324 flutter::DisplayListBuilder builder;
325 flutter::DlPaint paint;
326
327 auto image_source = flutter::DlColorSource::MakeImage(
328 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
329
330 paint.setColorSource(image_source);
331 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
332
333 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
334 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [188/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithEmptySize |
| ) |  |

Definition at line 285 of file canvas_unittests.cc.

285 {
286 RenderCallback callback = [&](RenderTarget& render_target) {
287 ContentContext context(GetContext(), nullptr);
288 Canvas canvas(context, render_target, true, false);
289
290 std::vector<flutter::DlPoint> vertex_coordinates = {
291 flutter::DlPoint(0, 0),
292 flutter::DlPoint(600, 0),
293 flutter::DlPoint(0, 600),
294 };
295 std::vector<flutter::DlPoint> texture_coordinates = {
296 flutter::DlPoint(0, 0),
297 flutter::DlPoint(500, 0),
298 flutter::DlPoint(0, 500),
299 };
300 std::vector<uint16_t> indices = {0, 1, 2};
301 flutter::DlVertices::Builder vertices_builder(
302 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
303 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
304 vertices_builder.store_vertices(vertex_coordinates.data());
305 vertices_builder.store_indices(indices.data());
306 vertices_builder.store_texture_coordinates(texture_coordinates.data());
307 auto vertices = vertices_builder.build();
308
309 // The start and end points of the gradient form an empty rectangle.
310 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
311 flutter::DlColor::kRed()};
312 std::vector<Scalar> stops = {0.0, 1.0};
313 auto gradient = flutter::DlColorSource::MakeLinear(
314 {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
315 flutter::DlTileMode::kClamp);
316
317 Paint paint;
318 paint.color_source = gradient.get();
319 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
320 BlendMode::kSrcOver, paint);
321
322 canvas.EndReplay();
323 return true;
324 };
325
326 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
327 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, and impeller::Playground::OpenPlaygroundHere().

## ◆ TEST_P() [189/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithoutIndices |
| ) |  |

Definition at line 211 of file aiks_dl_vertices_unittests.cc.

211 {
212 std::vector<DlPoint> positions = {
213 DlPoint(100, 300),
214 DlPoint(200, 100),
215 DlPoint(300, 300),
216 };
217
218 auto vertices = flutter::DlVertices::Make(
219 flutter::DlVertexMode::kTriangles, 3, positions.data(),
220 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
221
222 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
223 flutter::DlColor::kRed()};
224 const float stops[2] = {0.0, 1.0};
225
226 auto linear = flutter::DlColorSource::MakeLinear(
227 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
228 flutter::DlTileMode::kRepeat);
229
230 flutter::DisplayListBuilder builder;
231 flutter::DlPaint paint;
232
233 paint.setColorSource(linear);
234 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
235
236 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
237 }

## ◆ TEST_P() [190/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesLinearGradientWithTextureCoordinates |
| ) |  |

Definition at line 239 of file aiks_dl_vertices_unittests.cc.

239 {
240 std::vector<DlPoint> positions = {
241 DlPoint(100, 300),
242 DlPoint(200, 100),
243 DlPoint(300, 300),
244 };
245 std::vector<DlPoint> texture_coordinates = {
246 DlPoint(300, 100),
247 DlPoint(100, 200),
248 DlPoint(300, 300),
249 };
250
251 auto vertices = flutter::DlVertices::Make(
252 flutter::DlVertexMode::kTriangles, 3, positions.data(),
253 texture_coordinates.data(), /*colors=*/nullptr);
254
255 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
256 flutter::DlColor::kRed()};
257 const float stops[2] = {0.0, 1.0};
258
259 auto linear = flutter::DlColorSource::MakeLinear(
260 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
261 flutter::DlTileMode::kRepeat);
262
263 flutter::DisplayListBuilder builder;
264 flutter::DlPaint paint;
265
266 paint.setColorSource(linear);
267 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
268
269 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
270 }

## ◆ TEST_P() [191/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesPremultipliesColors |
| ) |  |

Definition at line 359 of file aiks_dl_vertices_unittests.cc.

359 {
360 std::vector<DlPoint> positions = {
361 DlPoint(100, 300),
362 DlPoint(200, 100),
363 DlPoint(300, 300),
364 DlPoint(200, 500),
365 };
366 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
367 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
368 std::vector<flutter::DlColor> colors = {color, color, color, color};
369
370 auto vertices = flutter::DlVertices::Make(
371 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
372 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
373 indices.data());
374
375 flutter::DisplayListBuilder builder;
376 flutter::DlPaint paint;
377 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
378 paint.setColor(flutter::DlColor::kRed());
379
380 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
381 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
382
383 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
384 }

## ◆ TEST_P() [192/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesSolidColorTrianglesWithIndices |
| ) |  |

Definition at line 336 of file aiks_dl_vertices_unittests.cc.

336 {
337 std::vector<DlPoint> positions = {
338 DlPoint(100, 300),
339 DlPoint(200, 100),
340 DlPoint(300, 300),
341 DlPoint(200, 500),
342 };
343 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
344
345 auto vertices = flutter::DlVertices::Make(
346 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
347 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
348 indices.data());
349
350 flutter::DisplayListBuilder builder;
351 flutter::DlPaint paint;
352
353 paint.setColor(flutter::DlColor::kRed());
354 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
355
356 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
357 }

## ◆ TEST_P() [193/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesSolidColorTrianglesWithoutIndices |
| ) |  |

Definition at line 185 of file aiks_dl_vertices_unittests.cc.

185 {
186 // Use negative coordinates and then scale the transform by -1, -1 to make
187 // sure coverage is taking the transform into account.
188 std::vector<DlPoint> positions = {
189 DlPoint(-100, -300),
190 DlPoint(-200, -100),
191 DlPoint(-300, -300),
192 };
193 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
194 flutter::DlColor::kGreen(),
195 flutter::DlColor::kWhite()};
196
197 auto vertices = flutter::DlVertices::Make(
198 flutter::DlVertexMode::kTriangles, 3, positions.data(),
199 /*texture_coordinates=*/nullptr, colors.data());
200
201 flutter::DisplayListBuilder builder;
202 flutter::DlPaint paint;
203
204 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
205 builder.Scale(-1, -1);
206 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
207
208 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
209 }

## ◆ TEST_P() [194/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesTextureCoordinatesWithFragmentShader |
| ) |  |

Definition at line 418 of file aiks_dl_vertices_unittests.cc.

418 {
419 std::vector<DlPoint> positions_lt = {
420 DlPoint(0, 0), //
421 DlPoint(50, 0), //
422 DlPoint(0, 50), //
423 DlPoint(50, 50), //
424 };
425
426 auto vertices_lt = flutter::DlVertices::Make(
427 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
428 positions_lt.data(),
429 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
430 /*index_count=*/0,
431 /*indices=*/nullptr);
432
433 std::vector<DlPoint> positions_rt = {
434 DlPoint(50, 0), //
435 DlPoint(100, 0), //
436 DlPoint(50, 50), //
437 DlPoint(100, 50), //
438 };
439
440 auto vertices_rt = flutter::DlVertices::Make(
441 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
442 positions_rt.data(),
443 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
444 /*index_count=*/0,
445 /*indices=*/nullptr);
446
447 std::vector<DlPoint> positions_lb = {
448 DlPoint(0, 50), //
449 DlPoint(50, 50), //
450 DlPoint(0, 100), //
451 DlPoint(50, 100), //
452 };
453
454 auto vertices_lb = flutter::DlVertices::Make(
455 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
456 positions_lb.data(),
457 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
458 /*index_count=*/0,
459 /*indices=*/nullptr);
460
461 std::vector<DlPoint> positions_rb = {
462 DlPoint(50, 50), //
463 DlPoint(100, 50), //
464 DlPoint(50, 100), //
465 DlPoint(100, 100), //
466 };
467
468 auto vertices_rb = flutter::DlVertices::Make(
469 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
470 positions_rb.data(),
471 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
472 /*index_count=*/0,
473 /*indices=*/nullptr);
474
475 flutter::DisplayListBuilder builder;
476 flutter::DlPaint paint;
477 flutter::DlPaint rect_paint;
478 rect_paint.setColor(DlColor::kBlue());
479
480 auto runtime_stages =
481 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
482
483 auto runtime_stage =
484 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
485 ASSERT_TRUE(runtime_stage);
486
487 auto runtime_effect = DlRuntimeEffectImpeller::Make(runtime_stage);
488 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
489 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
490 runtime_effect, {}, uniform_data);
491
492 paint.setColorSource(color_source);
493
494 builder.Scale(GetContentScale().x, GetContentScale().y);
495 builder.Save();
496 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), rect_paint);
497 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
498 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
499 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
500 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
501 builder.Restore();
502
503 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
504 }

References flutter::DlRuntimeEffectImpeller::Make(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [195/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesTextureCoordinatesWithFragmentShaderNonZeroOrigin |
| ) |  |

Definition at line 508 of file aiks_dl_vertices_unittests.cc.

509 {
510 std::vector<DlPoint> positions_lt = {
511 DlPoint(200, 200), //
512 DlPoint(250, 200), //
513 DlPoint(200, 250), //
514 DlPoint(250, 250), //
515 };
516
517 auto vertices = flutter::DlVertices::Make(
518 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
519 positions_lt.data(),
520 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
521 /*index_count=*/0,
522 /*indices=*/nullptr);
523
524 flutter::DisplayListBuilder builder;
525 flutter::DlPaint paint;
526 flutter::DlPaint rect_paint;
527 rect_paint.setColor(DlColor::kBlue());
528
529 auto runtime_stages =
530 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
531
532 auto runtime_stage =
533 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
534 ASSERT_TRUE(runtime_stage);
535
536 auto runtime_effect = DlRuntimeEffectImpeller::Make(runtime_stage);
537 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
538
539 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
540 uniform_data->resize(rect_data.size() * sizeof(Rect));
541 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
542
543 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
544 runtime_effect, {}, uniform_data);
545
546 paint.setColorSource(color_source);
547
548 builder.Scale(GetContentScale().x, GetContentScale().y);
549 builder.DrawRect(DlRect::MakeLTRB(200, 200, 250, 250), rect_paint);
550 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
551
552 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
553 }

References flutter::DlRuntimeEffectImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [196/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesWithEmptyTextureCoordinates |
| ) |  |

Definition at line 329 of file canvas_unittests.cc.

329 {
330 auto runtime_stages =
331 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
332
333 auto runtime_stage =
334 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
335 ASSERT_TRUE(runtime_stage);
336
337 auto runtime_effect = flutter::DlRuntimeEffectImpeller::Make(runtime_stage);
338 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
339 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
340 runtime_effect, {}, uniform_data);
341
342 RenderCallback callback = [&](RenderTarget& render_target) {
343 ContentContext context(GetContext(), nullptr);
344 Canvas canvas(context, render_target, true, false);
345
346 std::vector<flutter::DlPoint> vertex_coordinates = {
347 flutter::DlPoint(100, 100),
348 flutter::DlPoint(300, 100),
349 flutter::DlPoint(100, 300),
350 };
351 // The bounding box of the texture coordinates is empty.
352 std::vector<flutter::DlPoint> texture_coordinates = {
353 flutter::DlPoint(0, 0),
354 flutter::DlPoint(0, 100),
355 flutter::DlPoint(0, 0),
356 };
357 std::vector<uint16_t> indices = {0, 1, 2};
358 flutter::DlVertices::Builder vertices_builder(
359 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
360 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
361 vertices_builder.store_vertices(vertex_coordinates.data());
362 vertices_builder.store_indices(indices.data());
363 vertices_builder.store_texture_coordinates(texture_coordinates.data());
364 auto vertices = vertices_builder.build();
365
366 Paint paint;
367 paint.color_source = color_source.get();
368 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
369 BlendMode::kSrcOver, paint);
370
371 canvas.EndReplay();
372 return true;
373 };
374
375 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
376 }
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() [197/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawVerticesWithInvalidIndices |
| ) |  |

Definition at line 386 of file aiks_dl_vertices_unittests.cc.

386 {
387 std::vector<DlPoint> positions = {
388 DlPoint(100, 300),
389 DlPoint(200, 100),
390 DlPoint(300, 300),
391 DlPoint(200, 500),
392 };
393 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
394
395 auto vertices = flutter::DlVertices::Make(
396 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
397 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
398 indices.data());
399
400 EXPECT_EQ(vertices->GetBounds(), DlRect::MakeLTRB(100, 100, 300, 500));
401
402 flutter::DisplayListBuilder builder;
403 flutter::DlPaint paint;
404 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
405 paint.setColor(flutter::DlColor::kRed());
406
407 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
408 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
409
410 AiksContext renderer(GetContext(), nullptr);
411 std::shared_ptr<Texture> image =
412 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
413 EXPECT_TRUE(image);
414 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [198/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | EmptySaveLayerIgnoresPaint |
| ) |  |

Definition at line 1606 of file aiks_dl_basic_unittests.cc.

1606 {
1607 DisplayListBuilder builder;
1608 builder.Scale(GetContentScale().x, GetContentScale().y);
1609
1610 DlPaint paint;
1611 paint.setColor(DlColor::kRed());
1612 builder.DrawPaint(paint);
1613 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1614 paint.setColor(DlColor::kBlue());
1615 builder.SaveLayer(std::nullopt, &paint);
1616 builder.Restore();
1617
1618 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1619 }

References x.

## ◆ TEST_P() [199/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | EmptySaveLayerRendersWithClear |
| ) |  |

Definition at line 1621 of file aiks_dl_basic_unittests.cc.

1621 {
1622 DisplayListBuilder builder;
1623 builder.Scale(GetContentScale().x, GetContentScale().y);
1624 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1625 builder.DrawImage(image, DlPoint(10, 10), {});
1626 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1627
1628 DlPaint paint;
1629 paint.setBlendMode(DlBlendMode::kClear);
1630 builder.SaveLayer(std::nullopt, &paint);
1631 builder.Restore();
1632
1633 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1634 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [200/549]

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() [201/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FastEllipticalRRectMaskBlursRenderCorrectly |
| ) |  |

Definition at line 2023 of file aiks_dl_basic_unittests.cc.

2023 {
2024 DisplayListBuilder builder;
2025
2026 builder.Scale(GetContentScale().x, GetContentScale().y);
2027 DlPaint paint;
2028 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
2029
2030 DlPaint save_paint;
2031 save_paint.setColor(DlColor::kWhite());
2032 builder.DrawPaint(save_paint);
2033
2034 paint.setColor(DlColor::kBlue());
2035 for (int i = 0; i < 5; i++) {
2036 Scalar y = i * 125;
2037 Scalar y_radius = i * 15;
2038 for (int j = 0; j < 5; j++) {
2039 Scalar x = j * 125;
2040 Scalar x_radius = j * 15;
2041 builder.DrawRoundRect(
2042 DlRoundRect::MakeRectXY(
2043 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
2044 x_radius, y_radius),
2045 paint);
2046 }
2047 }
2048
2049 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2050 }

References x.

## ◆ TEST_P() [202/549]

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() [203/549]

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() [204/549]

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() [205/549]

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() [206/549]

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() [207/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledArcsRenderCorrectly |
| ) |  |

Definition at line 857 of file aiks_dl_basic_unittests.cc.

857 {
858 DisplayListBuilder builder;
859 builder.Scale(GetContentScale().x, GetContentScale().y);
860 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
861
862 DlPaint paint;
863 paint.setColor(DlColor::kBlue());
864
865 RenderArcFarm(builder, paint,
866 {
867 .use_center = false,
868 .full_circles = false,
869 });
870
871 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
872 }

References x.

## ◆ TEST_P() [208/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledArcsRenderCorrectlyWithCenter |
| ) |  |

Definition at line 874 of file aiks_dl_basic_unittests.cc.

874 {
875 DisplayListBuilder builder;
876 builder.Scale(GetContentScale().x, GetContentScale().y);
877 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
878
879 DlPaint paint;
880 paint.setColor(DlColor::kBlue());
881
882 RenderArcFarm(builder, paint,
883 {
884 .use_center = true,
885 .full_circles = false,
886 });
887
888 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
889 }

References x.

## ◆ TEST_P() [209/549]

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() [210/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledEllipsesRenderCorrectly |
| ) |  |

Definition at line 755 of file aiks_dl_basic_unittests.cc.

755 {
756 DisplayListBuilder builder;
757 builder.Scale(GetContentScale().x, GetContentScale().y);
758 DlPaint paint;
759 const int color_count = 3;
760 DlColor colors[color_count] = {
761 DlColor::kBlue(),
762 DlColor::kGreen(),
763 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
764 };
765
766 paint.setColor(DlColor::kWhite());
767 builder.DrawPaint(paint);
768
769 int c_index = 0;
770 int long_radius = 600;
771 int short_radius = 600;
772 while (long_radius > 0 && short_radius > 0) {
773 paint.setColor(colors[(c_index++) % color_count]);
774 builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
775 long_radius * 2, short_radius * 2),
776 paint);
777 builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
778 short_radius * 2, long_radius * 2),
779 paint);
780 if (short_radius > 30) {
781 short_radius -= 10;
782 long_radius -= 5;
783 } else {
784 short_radius -= 2;
785 long_radius -= 1;
786 }
787 }
788
789 DlColor gradient_colors[7] = {
790 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
791 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
792 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
793 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
794 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
795 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
796 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
797 };
798 DlScalar stops[7] = {
799 0.0,
800 (1.0 / 6.0) * 1,
801 (1.0 / 6.0) * 2,
802 (1.0 / 6.0) * 3,
803 (1.0 / 6.0) * 4,
804 (1.0 / 6.0) * 5,
805 1.0,
806 };
807 auto texture = CreateTextureForFixture("airplane.jpg",
808 /*enable_mipmapping=*/true);
809 auto image = DlImageImpeller::Make(texture);
810
811 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
812
813 paint.setColorSource(DlColorSource::MakeRadial(
814 DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
815 builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
816 builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
817
818 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
819 paint.setColorSource(DlColorSource::MakeImage(
820 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
821 DlImageSampling::kNearestNeighbor, &local_matrix));
822 builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
823 builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
824
825 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
826 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [211/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledRoundRectPathsRenderCorrectly |
| ) |  |

Definition at line 1757 of file aiks_dl_basic_unittests.cc.

1757 {
1758 DisplayListBuilder builder;
1759 builder.Scale(GetContentScale().x, GetContentScale().y);
1760
1761 DlPaint paint;
1762 const int color_count = 3;
1763 DlColor colors[color_count] = {
1764 DlColor::kBlue(),
1765 DlColor::kGreen(),
1766 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1767 };
1768
1769 paint.setColor(DlColor::kWhite());
1770 builder.DrawPaint(paint);
1771
1772 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1773 const DlPaint& paint) {
1774 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1775 };
1776
1777 int c_index = 0;
1778 for (int i = 0; i < 4; i++) {
1779 for (int j = 0; j < 4; j++) {
1780 paint.setColor(colors[(c_index++) % color_count]);
1781 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1782 i * 5 + 10, j * 5 + 10, paint);
1783 }
1784 }
1785 paint.setColor(colors[(c_index++) % color_count]);
1786 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1787 paint.setColor(colors[(c_index++) % color_count]);
1788 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1789
1790 std::vector<DlColor> gradient_colors = {
1791 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1792 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1793 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1794 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1795 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1796 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1797 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1798 std::vector<Scalar> stops = {
1799 0.0,
1800 (1.0 / 6.0) * 1,
1801 (1.0 / 6.0) * 2,
1802 (1.0 / 6.0) * 3,
1803 (1.0 / 6.0) * 4,
1804 (1.0 / 6.0) * 5,
1805 1.0,
1806 };
1807 auto texture = DlImageImpeller::Make(
1808 CreateTextureForFixture("airplane.jpg",
1809 /*enable_mipmapping=*/true));
1810
1811 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1812 paint.setColorSource(DlColorSource::MakeRadial(
1813 /*center=*/DlPoint(550, 550),
1814 /*radius=*/75,
1815 /*stop_count=*/gradient_colors.size(),
1816 /*colors=*/gradient_colors.data(),
1817 /*stops=*/stops.data(),
1818 /*tile_mode=*/DlTileMode::kMirror));
1819 for (int i = 1; i <= 10; i++) {
1820 int j = 11 - i;
1821 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1822 550 + i * 20, 550 + j * 20),
1823 i * 10, j * 10, paint);
1824 }
1825 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1826 paint.setColorSource(DlColorSource::MakeRadial(
1827 /*center=*/DlPoint(200, 650),
1828 /*radius=*/75,
1829 /*stop_count=*/gradient_colors.size(),
1830 /*colors=*/gradient_colors.data(),
1831 /*stops=*/stops.data(),
1832 /*tile_mode=*/DlTileMode::kMirror));
1833 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1834 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1835
1836 auto matrix = DlMatrix::MakeTranslation({520, 20});
1837 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1838 paint.setColorSource(DlColorSource::MakeImage(
1839 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1840 DlImageSampling::kMipmapLinear, &matrix));
1841 for (int i = 1; i <= 10; i++) {
1842 int j = 11 - i;
1843 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1844 720 + i * 20, 220 + j * 20),
1845 i * 10, j * 10, paint);
1846 }
1847 matrix = DlMatrix::MakeTranslation({800, 300});
1848 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1849 paint.setColorSource(DlColorSource::MakeImage(
1850 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1851 DlImageSampling::kMipmapLinear, &matrix));
1852
1853 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1854 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1855
1856 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1857 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [212/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FilledRoundRectsRenderCorrectly |
| ) |  |

Definition at line 1161 of file aiks_dl_basic_unittests.cc.

1161 {
1162 DisplayListBuilder builder;
1163 builder.Scale(GetContentScale().x, GetContentScale().y);
1164 DlPaint paint;
1165 const int color_count = 3;
1166 DlColor colors[color_count] = {
1167 DlColor::kBlue(),
1168 DlColor::kGreen(),
1169 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
1170 };
1171
1172 paint.setColor(DlColor::kWhite());
1173 builder.DrawPaint(paint);
1174
1175 int c_index = 0;
1176 for (int i = 0; i < 4; i++) {
1177 for (int j = 0; j < 4; j++) {
1178 paint.setColor(colors[(c_index++) % color_count]);
1179 builder.DrawRoundRect(
1180 DlRoundRect::MakeRectXY(
1181 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
1182 i * 5 + 10, j * 5 + 10),
1183 paint);
1184 }
1185 }
1186 paint.setColor(colors[(c_index++) % color_count]);
1187 builder.DrawRoundRect(
1188 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
1189 paint);
1190 paint.setColor(colors[(c_index++) % color_count]);
1191 builder.DrawRoundRect(
1192 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
1193 paint);
1194
1195 DlColor gradient_colors[7] = {
1196 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1197 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1198 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1199 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1200 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1201 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1202 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
1203 };
1204 DlScalar stops[7] = {
1205 0.0,
1206 (1.0 / 6.0) * 1,
1207 (1.0 / 6.0) * 2,
1208 (1.0 / 6.0) * 3,
1209 (1.0 / 6.0) * 4,
1210 (1.0 / 6.0) * 5,
1211 1.0,
1212 };
1213 auto texture = CreateTextureForFixture("airplane.jpg",
1214 /*enable_mipmapping=*/true);
1215 auto image = DlImageImpeller::Make(texture);
1216
1217 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1218 paint.setColorSource(DlColorSource::MakeRadial(
1219 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1220 for (int i = 1; i <= 10; i++) {
1221 int j = 11 - i;
1222 builder.DrawRoundRect(
1223 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1224 550 + i * 20, 550 + j * 20),
1225 i * 10, j * 10),
1226 paint);
1227 }
1228
1229 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1230 paint.setColorSource(DlColorSource::MakeRadial(
1231 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1232 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1233 builder.DrawRoundRect(
1234 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
1235 paint);
1236 builder.DrawRoundRect(
1237 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
1238 paint);
1239
1240 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1241 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
1242 paint.setColorSource(DlColorSource::MakeImage(
1243 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1244 DlImageSampling::kNearestNeighbor, &local_matrix));
1245 for (int i = 1; i <= 10; i++) {
1246 int j = 11 - i;
1247 builder.DrawRoundRect(
1248 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1249 720 + i * 20, 220 + j * 20),
1250 i * 10, j * 10),
1251 paint);
1252 }
1253
1254 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1255 local_matrix = DlMatrix::MakeTranslation({800, 300});
1256 paint.setColorSource(DlColorSource::MakeImage(
1257 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1258 DlImageSampling::kNearestNeighbor, &local_matrix));
1259 builder.DrawRoundRect(
1260 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
1261 paint);
1262 builder.DrawRoundRect(
1263 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
1264 paint);
1265
1266 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1267 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [213/549]

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() [214/549]

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() [215/549]

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() [216/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FormatSRGB |
| ) |  |

Definition at line 1670 of file aiks_dl_basic_unittests.cc.

1670 {
1671 PixelFormat pixel_format =
1672 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1673 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1674 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1675 << "pixel format: " << PixelFormatToString(pixel_format);
1676 }
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:140

References impeller::kB8G8R8A8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::PixelFormatToString().

## ◆ TEST_P() [217/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | FormatWideGamut |
| ) |  |

Definition at line 1665 of file aiks_dl_basic_unittests.cc.

1665 {
1666 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1667 PixelFormat::kB10G10R10A10XR);
1668 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [218/549]

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() [219/549]

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() [220/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAnimatedBackdrop |
| ) |  |

Definition at line 850 of file aiks_dl_blur_unittests.cc.

850 {
851 // This test is for checking out how stable rendering is when content is
852 // translated underneath a blur. Animating under a blur can cause
853 // *shimmering* to happen as a result of pixel alignment.
854 // See also: https://github.com/flutter/flutter/issues/140193
855 auto boston =
856 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
857 ASSERT_TRUE(boston);
858 int64_t count = 0;
859 Scalar sigma = 20.0;
860 Scalar freq = 0.1;
861 Scalar amp = 50.0;
862 auto callback = [&]() -> sk_sp<DisplayList> {
863 if (AiksTest::ImGuiBegin("Controls", nullptr,
864 ImGuiWindowFlags_AlwaysAutoResize)) {
865 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
866 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
867 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
868 ImGui::End();
869 }
870
871 DisplayListBuilder builder;
872 builder.Scale(GetContentScale().x, GetContentScale().y);
873 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
874 builder.DrawImage(DlImageImpeller::Make(boston),
875 DlPoint(1024 / 2 - boston->GetSize().width / 2,
876 (768 / 2 - boston->GetSize().height / 2) + y),
877 DlImageSampling::kMipmapLinear);
878 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
879 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
880 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
881
882 builder.ClipRect(
883 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
884 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
885
886 DlPaint paint;
887 paint.setBlendMode(DlBlendMode::kSrc);
888
889 auto backdrop_filter =
890 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
891 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
892 count += 1;
893 return builder.Build();
894 };
895 ASSERT_TRUE(OpenPlaygroundHere(callback));
896 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), and x.

## ◆ TEST_P() [221/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryHorizontal |
| ) |  |

Definition at line 821 of file aiks_dl_blur_unittests.cc.

821 {
822 DisplayListBuilder builder;
823
824 builder.Scale(GetContentScale().x, GetContentScale().y);
825 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
826 builder.DrawImageRect(
827 DlImageImpeller::Make(boston),
828 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
829 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
830 DlImageSampling::kNearestNeighbor);
831
832 DlPaint paint;
833 paint.setColor(DlColor::kMagenta());
834
835 DlRoundRect rrect = DlRoundRect::MakeRectXY(
836 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
837 builder.DrawRoundRect(rrect, paint);
838 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
839
840 DlPaint save_paint;
841 save_paint.setBlendMode(DlBlendMode::kSrc);
842
843 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
844 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
845
846 builder.Restore();
847 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
848 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [222/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryVertical |
| ) |  |

Definition at line 793 of file aiks_dl_blur_unittests.cc.

793 {
794 DisplayListBuilder builder;
795
796 DlPaint paint;
797 builder.Scale(GetContentScale().x, GetContentScale().y);
798
799 paint.setColor(DlColor::kLimeGreen());
800 DlRoundRect rrect = DlRoundRect::MakeRectXY(
801 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
802 builder.DrawRoundRect(rrect, paint);
803
804 paint.setColor(DlColor::kMagenta());
805 rrect = DlRoundRect::MakeRectXY(
806 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
807 builder.DrawRoundRect(rrect, paint);
808 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
809
810 DlPaint save_paint;
811 save_paint.setBlendMode(DlBlendMode::kSrc);
812
813 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
814
815 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
816 builder.Restore();
817
818 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
819 }

References x.

## ◆ TEST_P() [223/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurBackdropTinyMipMap |
| ) |  |

Definition at line 1284 of file aiks_dl_blur_unittests.cc.

1284 {
1285 AiksContext renderer(GetContext(), nullptr);
1286 for (int32_t i = 1; i < 5; ++i) {
1287 DisplayListBuilder builder;
1288
1289 ISize clip_size = ISize(i, i);
1290 builder.Save();
1291 builder.ClipRect(
1292 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1293
1294 DlPaint paint;
1295 paint.setColor(DlColor::kGreen());
1296 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1297 paint.setImageFilter(blur_filter);
1298
1299 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1300 builder.Restore();
1301
1302 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1303 EXPECT_TRUE(image) << " length " << i;
1304 }
1305 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [224/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurOneDimension |
| ) |  |

Definition at line 1096 of file aiks_dl_blur_unittests.cc.

1096 {
1097 DisplayListBuilder builder;
1098
1099 builder.Scale(GetContentScale().x, GetContentScale().y);
1100 builder.Scale(0.5, 0.5);
1101
1102 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1103 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1104
1105 DlPaint paint;
1106 paint.setBlendMode(DlBlendMode::kSrc);
1107
1108 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1109 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1110 builder.Restore();
1111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1112 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [225/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClipped |
| ) |  |

Definition at line 1118 of file aiks_dl_blur_unittests.cc.

1118 {
1119 DisplayListBuilder builder;
1120
1121 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1122 Rect bounds =
1123 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1124
1125 DlPaint paint;
1126 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1127
1128 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1129 Vector2 clip_size = {150, 75};
1130 Vector2 center = Vector2(1024, 768) / 2;
1131 builder.Scale(GetContentScale().x, GetContentScale().y);
1132
1133 auto clip_bounds =
1134 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1135 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1136 clip_bounds.GetRight(),
1137 clip_bounds.GetBottom()));
1138 builder.Translate(center.x, center.y);
1139 builder.Scale(0.6, 0.6);
1140 builder.Rotate(25);
1141
1142 auto dst_rect = bounds.Shift(-image_center);
1143 builder.DrawImageRect(
1144 DlImageImpeller::Make(boston), /*src=*/
1145 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1146 bounds.GetBottom()),
1147 /*dst=*/
1148 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1149 dst_rect.GetRight(), dst_rect.GetBottom()),
1150 DlImageSampling::kMipmapLinear, &paint);
1151
1152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1153 }
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:226

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() [226/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClippedInteractive |
| ) |  |

Definition at line 1041 of file aiks_dl_blur_unittests.cc.

1041 {
1042 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1043
1044 auto callback = [&]() -> sk_sp<DisplayList> {
1045 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1046 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1047 DlTileMode::kMirror, DlTileMode::kDecal};
1048
1049 static float rotation = 0;
1050 static float scale = 0.6;
1051 static int selected_tile_mode = 3;
1052
1053 if (AiksTest::ImGuiBegin("Controls", nullptr,
1054 ImGuiWindowFlags_AlwaysAutoResize)) {
1055 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1056 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1057 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1058 sizeof(tile_mode_names) / sizeof(char*));
1059 ImGui::End();
1060 }
1061
1062 DisplayListBuilder builder;
1063 Rect bounds =
1064 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1065 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1066 DlPaint paint;
1067 paint.setImageFilter(
1068 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1069
1070 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1071 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1072 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1073 Vector2 center = Vector2(1024, 768) / 2;
1074
1075 builder.Scale(GetContentScale().x, GetContentScale().y);
1076 builder.ClipRect(
1077 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1078 builder.Translate(center.x, center.y);
1079 builder.Scale(scale, scale);
1080 builder.Rotate(rotation);
1081
1082 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1083 bounds.GetRight(), bounds.GetBottom());
1084 Rect dest = bounds.Shift(-image_center);
1085 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1086 dest.GetRight(), dest.GetBottom());
1087 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1088 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1089 &paint);
1090 return builder.Build();
1091 };
1092
1093 ASSERT_TRUE(OpenPlaygroundHere(callback));
1094 }
impeller::TRect::Shift
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:606

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() [227/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedNonUniform |
| ) |  |

Definition at line 1155 of file aiks_dl_blur_unittests.cc.

1155 {
1156 auto callback = [&]() -> sk_sp<DisplayList> {
1157 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1158 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1159 DlTileMode::kMirror, DlTileMode::kDecal};
1160
1161 static float rotation = 45;
1162 static float scale = 0.6;
1163 static int selected_tile_mode = 3;
1164
1165 if (AiksTest::ImGuiBegin("Controls", nullptr,
1166 ImGuiWindowFlags_AlwaysAutoResize)) {
1167 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1168 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1169 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1170 sizeof(tile_mode_names) / sizeof(char*));
1171 ImGui::End();
1172 }
1173
1174 DisplayListBuilder builder;
1175
1176 DlPaint paint;
1177 paint.setColor(DlColor::kGreen());
1178 paint.setImageFilter(
1179 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1180
1181 Vector2 center = Vector2(1024, 768) / 2;
1182 builder.Scale(GetContentScale().x, GetContentScale().y);
1183 builder.Translate(center.x, center.y);
1184 builder.Scale(scale, scale);
1185 builder.Rotate(rotation);
1186
1187 DlRoundRect rrect =
1188 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1189 builder.DrawRoundRect(rrect, paint);
1190 return builder.Build();
1191 };
1192
1193 ASSERT_TRUE(OpenPlaygroundHere(callback));
1194 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [228/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurScaledAndClipped |
| ) |  |

Definition at line 1008 of file aiks_dl_blur_unittests.cc.

1008 {
1009 DisplayListBuilder builder;
1010 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1011 Rect bounds =
1012 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1013 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1014
1015 DlPaint paint;
1016 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1017
1018 Vector2 clip_size = {150, 75};
1019 Vector2 center = Vector2(1024, 768) / 2;
1020 builder.Scale(GetContentScale().x, GetContentScale().y);
1021
1022 auto rect =
1023 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1024 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1025 rect.GetRight(), rect.GetBottom()));
1026 builder.Translate(center.x, center.y);
1027 builder.Scale(0.6, 0.6);
1028
1029 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1030 bounds.GetRight(), bounds.GetBottom());
1031 Rect dest = bounds.Shift(-image_center);
1032 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1033 dest.GetRight(), dest.GetBottom());
1034 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1035 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1036 &paint);
1037
1038 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1039 }

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() [229/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurSolidColorTinyMipMap |
| ) |  |

Definition at line 1259 of file aiks_dl_blur_unittests.cc.

1259 {
1260 AiksContext renderer(GetContext(), nullptr);
1261
1262 for (int32_t i = 1; i < 5; ++i) {
1263 DisplayListBuilder builder;
1264 Scalar fi = i;
1265 DlPathBuilder path_builder;
1266 path_builder.MoveTo(DlPoint(100, 100));
1267 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1268
1269 DlPaint paint;
1270 paint.setColor(DlColor::kChartreuse());
1271 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1272 paint.setImageFilter(blur_filter);
1273
1274 builder.DrawPath(path_builder.TakePath(), paint);
1275
1276 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1277 EXPECT_TRUE(image) << " length " << i;
1278 }
1279 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [230/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInner |
| ) |  |

Definition at line 648 of file aiks_dl_blur_unittests.cc.

648 {
649 DisplayListBuilder builder;
650 builder.Scale(GetContentScale().x, GetContentScale().y);
651
652 DlPaint paint;
653 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
654 builder.DrawPaint(paint);
655
656 paint.setColor(DlColor::kGreen());
657 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
658
659 DlPathBuilder path_builder;
660 path_builder.MoveTo(DlPoint(200, 200));
661 path_builder.LineTo(DlPoint(300, 400));
662 path_builder.LineTo(DlPoint(100, 400));
663 path_builder.Close();
664
665 builder.DrawPath(path_builder.TakePath(), paint);
666
667 // Draw another thing to make sure the clip area is reset.
668 DlPaint red;
669 red.setColor(DlColor::kRed());
670 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
671
672 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
673 }

References x.

## ◆ TEST_P() [231/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInnerGradient |
| ) |  |

Definition at line 898 of file aiks_dl_blur_unittests.cc.

898 {
899 DisplayListBuilder builder;
900
901 builder.Scale(GetContentScale().x, GetContentScale().y);
902
903 DlPaint paint;
904 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
905 builder.DrawPaint(paint);
906
907 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
908 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
909 std::vector<Scalar> stops = {0.0, 1.0};
910
911 paint = DlPaint{};
912 paint.setColorSource(DlColorSource::MakeLinear(
913 /*start_point=*/{0, 0},
914 /*end_point=*/{200, 200},
915 /*stop_count=*/colors.size(),
916 /*colors=*/colors.data(),
917 /*stops=*/stops.data(),
918 /*tile_mode=*/DlTileMode::kMirror));
919 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
920
921 DlPathBuilder path_builder;
922 path_builder.MoveTo(DlPoint(200, 200));
923 path_builder.LineTo(DlPoint(300, 400));
924 path_builder.LineTo(DlPoint(100, 400));
925 path_builder.Close();
926 builder.DrawPath(path_builder.TakePath(), paint);
927
928 // Draw another thing to make sure the clip area is reset.
929 DlPaint red;
930 red.setColor(DlColor::kRed());
931 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
932
933 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
934 }

References x.

## ◆ TEST_P() [232/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuter |
| ) |  |

Definition at line 675 of file aiks_dl_blur_unittests.cc.

675 {
676 DisplayListBuilder builder;
677 builder.Scale(GetContentScale().x, GetContentScale().y);
678
679 DlPaint paint;
680 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
681 builder.DrawPaint(paint);
682
683 paint.setColor(DlColor::kGreen());
684 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
685
686 DlPathBuilder path_builder;
687 path_builder.MoveTo(DlPoint(200, 200));
688 path_builder.LineTo(DlPoint(300, 400));
689 path_builder.LineTo(DlPoint(100, 400));
690 path_builder.Close();
691
692 builder.DrawPath(path_builder.TakePath(), paint);
693
694 // Draw another thing to make sure the clip area is reset.
695 DlPaint red;
696 red.setColor(DlColor::kRed());
697 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
698
699 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
700 }

References x.

## ◆ TEST_P() [233/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuterGradient |
| ) |  |

Definition at line 972 of file aiks_dl_blur_unittests.cc.

972 {
973 DisplayListBuilder builder;
974 builder.Scale(GetContentScale().x, GetContentScale().y);
975
976 DlPaint paint;
977 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
978 builder.DrawPaint(paint);
979
980 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
981 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
982 std::vector<Scalar> stops = {0.0, 1.0};
983
984 paint = DlPaint{};
985 paint.setColorSource(DlColorSource::MakeLinear(
986 /*start_point=*/{0, 0},
987 /*end_point=*/{200, 200},
988 /*stop_count=*/colors.size(),
989 /*colors=*/colors.data(),
990 /*stops=*/stops.data(),
991 /*tile_mode=*/DlTileMode::kMirror));
992 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
993
994 DlPathBuilder path_builder;
995 path_builder.MoveTo(DlPoint(200, 200));
996 path_builder.LineTo(DlPoint(300, 400));
997 path_builder.LineTo(DlPoint(100, 400));
998 path_builder.Close();
999 builder.DrawPath(path_builder.TakePath(), paint);
1000
1001 // Draw another thing to make sure the clip area is reset.
1002 DlPaint red;
1003 red.setColor(DlColor::kRed());
1004 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1005 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1006 }

References x.

## ◆ TEST_P() [234/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolid |
| ) |  |

Definition at line 702 of file aiks_dl_blur_unittests.cc.

702 {
703 DisplayListBuilder builder;
704 builder.Scale(GetContentScale().x, GetContentScale().y);
705
706 DlPaint paint;
707 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
708 builder.DrawPaint(paint);
709
710 paint.setColor(DlColor::kGreen());
711 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
712
713 DlPathBuilder path_builder;
714 path_builder.MoveTo(DlPoint(200, 200));
715 path_builder.LineTo(DlPoint(300, 400));
716 path_builder.LineTo(DlPoint(100, 400));
717 path_builder.Close();
718
719 builder.DrawPath(path_builder.TakePath(), paint);
720
721 // Draw another thing to make sure the clip area is reset.
722 DlPaint red;
723 red.setColor(DlColor::kRed());
724 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
725
726 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
727 }

References x.

## ◆ TEST_P() [235/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolidGradient |
| ) |  |

Definition at line 936 of file aiks_dl_blur_unittests.cc.

936 {
937 DisplayListBuilder builder;
938 builder.Scale(GetContentScale().x, GetContentScale().y);
939
940 DlPaint paint;
941 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
942 builder.DrawPaint(paint);
943
944 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
945 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
946 std::vector<Scalar> stops = {0.0, 1.0};
947
948 paint = DlPaint{};
949 paint.setColorSource(DlColorSource::MakeLinear(
950 /*start_point=*/{0, 0},
951 /*end_point=*/{200, 200},
952 /*stop_count=*/colors.size(),
953 /*colors=*/colors.data(),
954 /*stops=*/stops.data(),
955 /*tile_mode=*/DlTileMode::kMirror));
956 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
957
958 DlPathBuilder path_builder;
959 path_builder.MoveTo(DlPoint(200, 200));
960 path_builder.LineTo(DlPoint(300, 400));
961 path_builder.LineTo(DlPoint(100, 400));
962 path_builder.Close();
963 builder.DrawPath(path_builder.TakePath(), paint);
964
965 // Draw another thing to make sure the clip area is reset.
966 DlPaint red;
967 red.setColor(DlColor::kRed());
968 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
969 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
970 }

References x.

## ◆ TEST_P() [236/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlur |
| ) |  |

Definition at line 103 of file aiks_dl_blur_unittests.cc.

103 {
104 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
105 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
106 }
impeller::testing::DoGradientOvalStrokeMaskBlur
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
Definition: aiks_dl_blur_unittests.cc:62

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [237/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurInner |
| ) |  |

Definition at line 118 of file aiks_dl_blur_unittests.cc.

118 {
119 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
120 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
121 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [238/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurOuter |
| ) |  |

Definition at line 113 of file aiks_dl_blur_unittests.cc.

113 {
114 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
115 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
116 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [239/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSigmaZero |
| ) |  |

Definition at line 108 of file aiks_dl_blur_unittests.cc.

108 {
109 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
110 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
111 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [240/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSolid |
| ) |  |

Definition at line 123 of file aiks_dl_blur_unittests.cc.

123 {
124 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
125 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
126 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [241/549]

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

References impeller::DrawPlaygroundLine(), impeller::TPoint< T >::GetDistance(), impeller::Matrix::Invert(), impeller::Matrix::IsInvertible(), impeller::Color::ToARGB(), and x.

## ◆ TEST_P() [242/549]

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() [243/549]

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() [244/549]

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() [245/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageColorSourceEffectTransform |
| ) |  |

Definition at line 1434 of file aiks_dl_basic_unittests.cc.

1434 {
1435 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
1436
1437 DisplayListBuilder builder;
1438 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
1439
1440 DlPaint paint;
1441 paint.setColor(DlColor::kWhite());
1442 builder.DrawPaint(paint);
1443
1444 // Translation
1445 {
1446 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
1447 DlPaint paint;
1448 paint.setColorSource(DlColorSource::MakeImage(
1449 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1450 DlImageSampling::kNearestNeighbor, &matrix));
1451
1452 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
1453 }
1454
1455 // Rotation/skew
1456 {
1457 builder.Save();
1458 builder.Rotate(45);
1459 DlPaint paint;
1460
1461 Matrix matrix(1, -1, 0, 0, //
1462 1, 1, 0, 0, //
1463 0, 0, 1, 0, //
1464 0, 0, 0, 1);
1465 paint.setColorSource(DlColorSource::MakeImage(
1466 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1467 DlImageSampling::kNearestNeighbor, &matrix));
1468 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
1469 builder.Restore();
1470 }
1471
1472 // Scale
1473 {
1474 builder.Save();
1475 builder.Translate(100, 0);
1476 builder.Scale(100, 100);
1477 DlPaint paint;
1478
1479 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
1480 paint.setColorSource(DlColorSource::MakeImage(
1481 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1482 DlImageSampling::kNearestNeighbor, &matrix));
1483
1484 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
1485 builder.Restore();
1486 }
1487
1488 // Perspective
1489 {
1490 builder.Save();
1491 builder.Translate(150, 150);
1492 DlPaint paint;
1493
1494 DlMatrix matrix =
1495 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
1496 paint.setColorSource(DlColorSource::MakeImage(
1497 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1498 DlImageSampling::kNearestNeighbor, &matrix));
1499
1500 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
1501 builder.Restore();
1502 }
1503
1504 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1505 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [246/549]

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

## ◆ TEST_P() [247/549]

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() [248/549]

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() [249/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurDoesntStretchContents |
| ) |  |

Definition at line 758 of file aiks_dl_blur_unittests.cc.

758 {
759 Scalar sigma = 70;
760 auto callback = [&]() -> sk_sp<DisplayList> {
761 if (AiksTest::ImGuiBegin("Controls", nullptr,
762 ImGuiWindowFlags_AlwaysAutoResize)) {
763 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
764 ImGui::End();
765 }
766
767 DisplayListBuilder builder;
768 builder.Scale(GetContentScale().x, GetContentScale().y);
769
770 DlPaint paint;
771 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
772 builder.DrawPaint(paint);
773
774 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
775
776 builder.Transform(Matrix::MakeTranslation({100, 100}) *
777 Matrix::MakeScale({0.5, 0.5, 1.0f}));
778
779 paint.setColorSource(DlColorSource::MakeImage(
780 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
781 DlImageSampling::kMipmapLinear));
782 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
783
784 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
785 boston->GetSize().height),
786 paint);
787
788 return builder.Build();
789 };
790 ASSERT_TRUE(OpenPlaygroundHere(callback));
791 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and x.

## ◆ TEST_P() [250/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurOnZeroDimensionIsSkippedWideGamut |
| ) |  |

Definition at line 474 of file aiks_dl_blur_unittests.cc.

474 {
475 // Making sure this test is run on a wide gamut enabled backend
476 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
477 PixelFormat::kB10G10R10A10XR);
478
479 DisplayListBuilder builder;
480 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
481
482 DlPaint paint;
483 paint.setColor(DlColor::kBlue());
484 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
485
486 // Zero height above
487 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
488 // Regular rect
489 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
490 // Zero width to the right
491 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
492
493 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
494 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [251/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurTexture |
| ) |  |

Definition at line 729 of file aiks_dl_blur_unittests.cc.

729 {
730 Scalar sigma = 30;
731 auto callback = [&]() -> sk_sp<DisplayList> {
732 if (AiksTest::ImGuiBegin("Controls", nullptr,
733 ImGuiWindowFlags_AlwaysAutoResize)) {
734 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
735 ImGui::End();
736 }
737
738 DisplayListBuilder builder;
739 builder.Scale(GetContentScale().x, GetContentScale().y);
740
741 DlPaint paint;
742 paint.setColor(DlColor::kGreen());
743 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
744
745 builder.DrawImage(
746 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
747 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
748
749 DlPaint red;
750 red.setColor(DlColor::kRed());
751 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
752
753 return builder.Build();
754 };
755 ASSERT_TRUE(OpenPlaygroundHere(callback));
756 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [252/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurWithZeroSigmaIsSkipped |
| ) |  |

Definition at line 461 of file aiks_dl_blur_unittests.cc.

461 {
462 DisplayListBuilder builder;
463
464 DlPaint paint;
465 paint.setColor(DlColor::kBlue());
466 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
467
468 builder.DrawCircle(DlPoint(300, 300), 200, paint);
469 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
470
471 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
472 }

## ◆ TEST_P() [253/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScaleConvertToPath |
| ) |  |

Definition at line 196 of file aiks_dl_text_unittests.cc.

196 {
197 Scalar scale = 16.0;
198 auto callback = [&]() -> sk_sp<DisplayList> {
199 if (AiksTest::ImGuiBegin("Controls", nullptr,
200 ImGuiWindowFlags_AlwaysAutoResize)) {
201 ImGui::SliderFloat("Scale", &scale, 4, 20);
202 ImGui::End();
203 }
204
205 DisplayListBuilder builder;
206 DlPaint paint;
207 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
208 builder.DrawPaint(paint);
209
210 builder.Scale(scale, scale);
211 RenderTextInCanvasSkia(
212 GetContext(), builder, "HELLO", "Roboto-Regular.ttf",
213 TextRenderOptions{.font_size = 16,
214 .color = (16 * scale >= 250) ? DlColor::kYellow()
215 : DlColor::kOrange(),
216 .position = DlPoint(0, 20)});
217 return builder.Build();
218 };
219
220 ASSERT_TRUE(OpenPlaygroundHere(callback));
221 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [254/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScalingMatrixImageFilter |
| ) |  |

Definition at line 2078 of file aiks_dl_basic_unittests.cc.

2078 {
2079 if (GetBackend() == PlaygroundBackend::kVulkan) {
2080 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
2081 }
2082 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
2083
2084 auto filter = DlImageFilter::MakeMatrix(
2085 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
2086
2087 DlPaint paint;
2088 paint.setImageFilter(filter);
2089 builder.SaveLayer(std::nullopt, &paint);
2090 {
2091 DlPaint paint;
2092 paint.setColor(DlColor::kRed());
2093 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
2094 }
2095 builder.Restore();
2096
2097 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2098 }

References impeller::kVulkan.

## ◆ TEST_P() [255/549]

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() [256/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen |
| ) |  |

Definition at line 1557 of file aiks_dl_basic_unittests.cc.

1558 {
1559 DisplayListBuilder builder;
1560 builder.Scale(GetContentScale().x, GetContentScale().y);
1561 builder.Translate(100, 100);
1562 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1563 // +300 translation applied by a SaveLayer image filter.
1564
1565 DlPaint paint;
1566 paint.setImageFilter(DlImageFilter::MakeMatrix(
1567 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1568 DlImageSampling::kNearestNeighbor));
1569 builder.SaveLayer(std::nullopt, &paint);
1570
1571 DlPaint circle_paint;
1572 circle_paint.setColor(DlColor::kGreen());
1573 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1574 builder.Restore();
1575
1576 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1577 }

References x.

## ◆ TEST_P() [257/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen |
| ) |  |

Definition at line 1536 of file aiks_dl_basic_unittests.cc.

1536 {
1537 DisplayListBuilder builder;
1538 builder.Scale(GetContentScale().x, GetContentScale().y);
1539 builder.Translate(100, 100);
1540 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1541 // +300 translation applied by a SaveLayer image filter.
1542 DlPaint paint;
1543 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1544 paint.setImageFilter(
1545 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1546 builder.SaveLayer(std::nullopt, &paint);
1547
1548 DlPaint circle_paint;
1549 circle_paint.setColor(DlColor::kGreen());
1550 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1551 builder.Restore();
1552
1553 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1554 }

References x.

## ◆ TEST_P() [258/549]

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() [259/549]

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() [260/549]

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() [261/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MultipleTextWithShadowCache |
| ) |  |

Definition at line 804 of file aiks_dl_text_unittests.cc.

804 {
805 DisplayListBuilder builder;
806 builder.Scale(GetContentScale().x, GetContentScale().y);
807 DlPaint paint;
808 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
809 builder.DrawPaint(paint);
810
811 AiksContext aiks_context(GetContext(),
812 std::make_shared<TypographerContextSkia>());
813 // Cache empty
814 EXPECT_EQ(aiks_context.GetContentContext()
815 .GetTextShadowCache()
816 .GetCacheSizeForTesting(),
817 0u);
818
819 for (auto i = 0; i < 5; i++) {
820 ASSERT_TRUE(RenderTextInCanvasSkia(
821 GetContext(), builder, "Hello World", kFontFixture,
822 TextRenderOptions{
823 .color = DlColor::kBlue(),
824 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
825 }
826
827 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
828
829 // Text should be cached. Each text gets its own entry as we don't analyze the
830 // strings.
831 EXPECT_EQ(aiks_context.GetContentContext()
832 .GetTextShadowCache()
833 .GetCacheSizeForTesting(),
834 5u);
835 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [262/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NoDimplesInRRectPath |
| ) |  |

Definition at line 2100 of file aiks_dl_basic_unittests.cc.

2100 {
2101 Scalar width = 200.f;
2102 Scalar height = 60.f;
2103 Scalar corner = 1.f;
2104 auto callback = [&]() -> sk_sp<DisplayList> {
2105 if (AiksTest::ImGuiBegin("Controls", nullptr,
2106 ImGuiWindowFlags_AlwaysAutoResize)) {
2107 ImGui::SliderFloat("width", &width, 0, 200);
2108 ImGui::SliderFloat("height", &height, 0, 200);
2109 ImGui::SliderFloat("corner", &corner, 0, 1);
2110 ImGui::End();
2111 }
2112
2113 DisplayListBuilder builder;
2114 builder.Scale(GetContentScale().x, GetContentScale().y);
2115
2116 DlPaint background_paint;
2117 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
2118 builder.DrawPaint(background_paint);
2119
2120 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
2121 std::vector<Scalar> stops = {0.0, 1.0};
2122
2123 DlPaint paint;
2124 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
2125 2, colors.data(), stops.data(),
2126 DlTileMode::kClamp);
2127 paint.setColorSource(gradient);
2128 paint.setColor(DlColor::kWhite());
2129 paint.setDrawStyle(DlDrawStyle::kStroke);
2130 paint.setStrokeWidth(20);
2131
2132 builder.Save();
2133 builder.Translate(100, 100);
2134
2135 Scalar corner_x = ((1 - corner) * 50) + 50;
2136 Scalar corner_y = corner * 50 + 50;
2137 DlRoundRect rrect = DlRoundRect::MakeRectXY(
2138 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
2139 builder.DrawRoundRect(rrect, paint);
2140 builder.Restore();
2141 return builder.Build();
2142 };
2143 ASSERT_TRUE(OpenPlaygroundHere(callback));
2144 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [263/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectly |
| ) |  |

Definition at line 891 of file aiks_dl_basic_unittests.cc.

891 {
892 DisplayListBuilder builder;
893 builder.Scale(GetContentScale().x, GetContentScale().y);
894 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
895
896 DlPaint paint;
897 paint.setColor(DlColor::kBlue());
898
899 RenderArcFarm(builder, paint,
900 {
901 .use_center = false,
902 .full_circles = false,
903 .vertical_scale = 0.8f,
904 });
905
906 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
907 }

References x.

## ◆ TEST_P() [264/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectlyWithCenter |
| ) |  |

Definition at line 909 of file aiks_dl_basic_unittests.cc.

909 {
910 DisplayListBuilder builder;
911 builder.Scale(GetContentScale().x, GetContentScale().y);
912 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
913
914 DlPaint paint;
915 paint.setColor(DlColor::kBlue());
916
917 RenderArcFarm(builder, paint,
918 {
919 .use_center = true,
920 .full_circles = false,
921 .vertical_scale = 0.8f,
922 });
923
924 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
925 }

References x.

## ◆ TEST_P() [265/549]

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() [266/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PipelineBlendSingleParameter |
| ) |  |

Definition at line 2052 of file aiks_dl_basic_unittests.cc.

2052 {
2053 DisplayListBuilder builder;
2054
2055 // Should render a green square in the middle of a blue circle.
2056 DlPaint paint;
2057 builder.SaveLayer(std::nullopt, &paint);
2058 {
2059 builder.Translate(100, 100);
2060 paint.setColor(DlColor::kBlue());
2061 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2062 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
2063
2064 paint.setColor(DlColor::kGreen());
2065 paint.setBlendMode(DlBlendMode::kSrcOver);
2066 paint.setImageFilter(DlImageFilter::MakeColorFilter(
2067 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
2068 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2069 builder.Restore();
2070 }
2071
2072 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2073 }

## ◆ TEST_P() [267/549]

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() [268/549]

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() [269/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RoundSuperellipseShadowComparison |
| ) |  |

Definition at line 390 of file canvas_unittests.cc.

390 {
391 // Config
392 Size default_size(600, 400);
393 Point left_center(400, 700);
394 Point right_center(1300, 700);
395 Color color = Color::Red();
396
397 // Convert `color` to a `color_source`. This forces
398 // `canvas.DrawRoundSuperellipse` to use the regular shadow algorithm
399 // (blurring) instead of the fast shadow algorithm.
400 std::shared_ptr<flutter::DlColorSource> color_source;
401 {
402 flutter::DlColor dl_color = flutter::DlColor(color.ToARGB());
403 std::vector<flutter::DlColor> colors = {dl_color, dl_color};
404 std::vector<Scalar> stops = {0.0, 1.0};
405 color_source = flutter::DlColorSource::MakeLinear(
406 {0, 0}, {1000, 1000}, 2, colors.data(), stops.data(),
407 flutter::DlTileMode::kClamp);
408 }
409
410 auto RectMakeCenterHalfSize = [](Point center, Point half_size) {
411 Size size(half_size.x * 2, half_size.y * 2);
412 return Rect::MakeOriginSize(center - half_size, size);
413 };
414
415 RenderCallback callback = [&](RenderTarget& render_target) {
416 ContentContext context(GetContext(), nullptr);
417 Canvas canvas(context, render_target, true, false);
418 // Somehow there's a scaling factor between PlaygroundPoint and Canvas.
419 Matrix ctm = Matrix::MakeScale(Vector2(1, 1) * 0.5);
420 Matrix i_ctm = ctm.Invert();
421
422 static Scalar sigma = 0.05;
423 static Scalar radius = 200;
424
425 // Define the ImGui
426 ImGui::Begin("Shadow", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
427 {
428 ImGui::SliderFloat("Sigma", &sigma, 0, 100);
429 ImGui::SliderFloat("Radius", &radius, 0, 1000);
430 }
431 ImGui::End();
432
433 static PlaygroundPoint right_reference_var(
434 ctm * (right_center + default_size / 2), 30, Color::White());
435 Point right_reference = i_ctm * DrawPlaygroundPoint(right_reference_var);
436 Point half_size = (right_reference - right_center).Abs();
437 Rect left_bounds = RectMakeCenterHalfSize(left_center, half_size);
438 Rect right_bounds = RectMakeCenterHalfSize(right_center, half_size);
439
440 Paint paint{
441 .color = color,
442 .mask_blur_descriptor =
443 Paint::MaskBlurDescriptor{
444 .sigma = Sigma(sigma),
445 },
446 };
447
448 // Left: Draw with canvas
449 canvas.DrawRoundSuperellipse(
450 RoundSuperellipse::MakeRectRadius(left_bounds, radius), paint);
451
452 // Right: Direct draw
453 paint.color_source = color_source.get();
454 canvas.DrawRoundSuperellipse(
455 RoundSuperellipse::MakeRectRadius(right_bounds, radius), paint);
456
457 canvas.EndReplay();
458 return true;
459 };
460
461 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
462 }

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() [270/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RuntimeEffectWithInvalidSamplerDoesNotCrash |
| ) |  |

Definition at line 112 of file aiks_dl_runtime_effect_unittests.cc.

112 {
113 ScopedValidationDisable disable_validation;
114
115 // Create a sampler that is not usable as an input to the runtime effect.
116 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
117 flutter::DlColor::kRed()};
118 const float stops[2] = {0.0, 1.0};
119 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
120 2, colors.data(), stops,
121 flutter::DlTileMode::kClamp);
122 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
123 linear,
124 };
125
126 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
127 uniform_data->resize(sizeof(Vector2));
128
129 DlPaint paint;
130 paint.setColorSource(
131 MakeRuntimeEffect(this, "runtime_stage_filter_example.frag.iplr",
132 uniform_data, sampler_inputs));
133
134 DisplayListBuilder builder;
135 builder.DrawPaint(paint);
136
137 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
138 }

## ◆ TEST_P() [271/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerDrawsBehindSubsequentEntities |
| ) |  |

Definition at line 1907 of file aiks_dl_basic_unittests.cc.

1907 {
1908 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1909 DisplayListBuilder builder;
1910 DlPaint paint;
1911
1912 paint.setColor(DlColor::kBlack());
1913 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1914 builder.DrawRect(rect, paint);
1915
1916 builder.Translate(10, 10);
1917
1918 DlPaint save_paint;
1919 builder.SaveLayer(std::nullopt, &save_paint);
1920
1921 paint.setColor(DlColor::kGreen());
1922 builder.DrawRect(rect, paint);
1923
1924 builder.Restore();
1925
1926 builder.Translate(10, 10);
1927 paint.setColor(DlColor::kRed());
1928 builder.DrawRect(rect, paint);
1929
1930 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1931 }

## ◆ TEST_P() [272/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerFiltersScaleWithTransform |
| ) |  |

Definition at line 1999 of file aiks_dl_basic_unittests.cc.

1999 {
2000 DisplayListBuilder builder;
2001
2002 builder.Scale(GetContentScale().x, GetContentScale().y);
2003 builder.Translate(100, 100);
2004
2005 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
2006 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
2007 builder.SaveLayer(std::nullopt, &paint);
2008 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
2009 builder.Restore();
2010 };
2011
2012 DlPaint effect_paint;
2013 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
2014 draw_image_layer(effect_paint);
2015
2016 builder.Translate(300, 300);
2017 builder.Scale(3, 3);
2018 draw_image_layer(effect_paint);
2019
2020 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2021 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [273/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaledK |
| ) |  |

Definition at line 174 of file aiks_dl_text_unittests.cc.

174 {
175 DisplayListBuilder builder;
176 DlPaint paint;
177 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
178 builder.DrawPaint(paint);
179 for (int i = 0; i < 6; ++i) {
180 builder.Save();
181 builder.Translate(300 * i, 0);
182 Scalar scale = 0.445 - (i / 1000.f);
183 builder.Scale(scale, scale);
184 RenderTextInCanvasSkia(
185 GetContext(), builder, "k", "Roboto-Regular.ttf",
186 TextRenderOptions{.font_size = 600, .position = DlPoint(10, 500)});
187 RenderTextInCanvasSkia(
188 GetContext(), builder, "k", "Roboto-Regular.ttf",
189 TextRenderOptions{.font_size = 300, .position = DlPoint(10, 800)});
190 builder.Restore();
191 }
192 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
193 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [274/549]

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() [275/549]

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() [276/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SiblingSaveLayerBoundsAreRespected |
| ) |  |

Definition at line 1933 of file aiks_dl_basic_unittests.cc.

1933 {
1934 DisplayListBuilder builder;
1935 DlPaint paint;
1936 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
1937
1938 // Black, green, and red squares offset by [10, 10].
1939 {
1940 DlPaint save_paint;
1941 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
1942 builder.SaveLayer(bounds, &save_paint);
1943 paint.setColor(DlColor::kBlack());
1944 builder.DrawRect(rect, paint);
1945 builder.Restore();
1946 }
1947
1948 {
1949 DlPaint save_paint;
1950 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
1951 builder.SaveLayer(bounds, &save_paint);
1952 paint.setColor(DlColor::kGreen());
1953 builder.DrawRect(rect, paint);
1954 builder.Restore();
1955 }
1956
1957 {
1958 DlPaint save_paint;
1959 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
1960 builder.SaveLayer(bounds, &save_paint);
1961 paint.setColor(DlColor::kRed());
1962 builder.DrawRect(rect, paint);
1963 builder.Restore();
1964 }
1965
1966 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1967 }

## ◆ TEST_P() [277/549]

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(), and x.

## ◆ TEST_P() [278/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SingleIconShadowTest |
| ) |  |

Definition at line 837 of file aiks_dl_text_unittests.cc.

837 {
838 DisplayListBuilder builder;
839 builder.Scale(GetContentScale().x, GetContentScale().y);
840 DlPaint paint;
841 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
842 builder.DrawPaint(paint);
843
844 AiksContext aiks_context(GetContext(),
845 std::make_shared<TypographerContextSkia>());
846 // Cache empty
847 EXPECT_EQ(aiks_context.GetContentContext()
848 .GetTextShadowCache()
849 .GetCacheSizeForTesting(),
850 0u);
851
852 // Create font instance outside loop so all draws use identical font instance.
853 auto c_font_fixture = std::string(kFontFixture);
854 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
855 ASSERT_TRUE(mapping);
856 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
857 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
858
859 for (auto i = 0; i < 10; i++) {
860 ASSERT_TRUE(RenderTextInCanvasSkia(
861 GetContext(), builder, "A", kFontFixture,
862 TextRenderOptions{
863 .color = DlColor::kBlue(),
864 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
865 sk_font));
866 }
867
868 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
869
870 // Text should be cached. All 10 glyphs use the same cache entry.
871 EXPECT_EQ(aiks_context.GetContentContext()
872 .GetTextShadowCache()
873 .GetCacheSizeForTesting(),
874 1u);
875 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [279/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCircleMaskBlurTinySigma |
| ) |  |

Definition at line 128 of file aiks_dl_blur_unittests.cc.

128 {
129 DisplayListBuilder builder;
130 builder.Scale(GetContentScale().x, GetContentScale().y);
131
132 std::vector<float> sigmas = {0.0, 0.01, 1.0};
133 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
134 DlColor::kRed()};
135 for (uint32_t i = 0; i < sigmas.size(); ++i) {
136 DlPaint paint;
137 paint.setColor(colors[i]);
138 paint.setMaskFilter(
139 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
140
141 builder.Save();
142 builder.Translate(100 + (i * 100), 100);
143 DlRoundRect rrect = DlRoundRect::MakeRectXY(
144 DlRect::MakeXYWH(0, 0, 100.0f, 100.0f), 100, 100);
145 builder.DrawRoundRect(rrect, paint);
146 builder.Restore();
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

References x.

## ◆ TEST_P() [280/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCirclesOvalsRRectsMaskBlurCorrectly |
| ) |  |

Definition at line 1269 of file aiks_dl_basic_unittests.cc.

1269 {
1270 DisplayListBuilder builder;
1271 builder.Scale(GetContentScale().x, GetContentScale().y);
1272 DlPaint paint;
1273 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
1274
1275 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1276
1277 paint.setColor(
1278 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
1279 Scalar y = 100.0f;
1280 for (int i = 0; i < 5; i++) {
1281 Scalar x = (i + 1) * 100;
1282 Scalar radius = x / 10.0f;
1283 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1284 radius, 60.0f - radius),
1285 paint);
1286 }
1287
1288 paint.setColor(DlColor::kBlue());
1289 y += 100.0f;
1290 for (int i = 0; i < 5; i++) {
1291 Scalar x = (i + 1) * 100;
1292 Scalar radius = x / 10.0f;
1293 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
1294 }
1295
1296 paint.setColor(DlColor::kGreen());
1297 y += 100.0f;
1298 for (int i = 0; i < 5; i++) {
1299 Scalar x = (i + 1) * 100;
1300 Scalar radius = x / 10.0f;
1301 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1302 radius, 60.0f - radius),
1303 paint);
1304 }
1305
1306 paint.setColor(
1307 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
1308 y += 100.0f;
1309 for (int i = 0; i < 5; i++) {
1310 Scalar x = (i + 1) * 100;
1311 Scalar radius = x / 20.0f;
1312 builder.DrawRoundRect(
1313 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1314 radius, radius),
1315 paint);
1316 }
1317
1318 paint.setColor(
1319 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
1320 y += 100.0f;
1321 for (int i = 0; i < 5; i++) {
1322 Scalar x = (i + 1) * 100;
1323 Scalar radius = x / 20.0f;
1324 builder.DrawRoundRect(
1325 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1326 radius, 5.0f),
1327 paint);
1328 }
1329
1330 auto dl = builder.Build();
1331 ASSERT_TRUE(OpenPlaygroundHere(dl));
1332 }

References x.

## ◆ TEST_P() [281/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorOvalsMaskBlurTinySigma |
| ) |  |

Definition at line 38 of file aiks_dl_blur_unittests.cc.

38 {
39 DisplayListBuilder builder;
40 builder.Scale(GetContentScale().x, GetContentScale().y);
41
42 std::vector<float> sigmas = {0.0, 0.01, 1.0};
43 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
44 DlColor::kRed()};
45 for (uint32_t i = 0; i < sigmas.size(); ++i) {
46 DlPaint paint;
47 paint.setColor(colors[i]);
48 paint.setMaskFilter(
49 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
50
51 builder.Save();
52 builder.Translate(100 + (i * 100), 100);
53 DlRoundRect rrect =
54 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 60.0f, 160.0f), 50, 100);
55 builder.DrawRoundRect(rrect, paint);
56 builder.Restore();
57 }
58
59 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
60 }

References x.

## ◆ TEST_P() [282/549]

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

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() [283/549]

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() [284/549]

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() [285/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsCoverFullArcWithButtEnds |
| ) |  |

Definition at line 1120 of file aiks_dl_basic_unittests.cc.

1120 {
1121 // This test compares the rendering of a full circle arc against a partial
1122 // arc by drawing a one over the other in high contrast. If the partial
1123 // arc misses any pixels that were drawn by the full arc, there will be
1124 // some "pixel dirt" around the missing "erased" parts of the arcs. This
1125 // case arises while rendering a CircularProgressIndicator with a background
1126 // color where we want the rendering of the background full arc to hit the
1127 // same pixels around the edges as the partial arc that covers it.
1128 //
1129 // In this case we draw a full blue circle and then draw a partial arc
1130 // over it in the background color (white).
1131
1132 DisplayListBuilder builder;
1133 builder.Scale(GetContentScale().x, GetContentScale().y);
1134 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1135
1136 DlPaint paint;
1137 paint.setDrawStyle(DlDrawStyle::kStroke);
1138 paint.setStrokeWidth(6.0f);
1139 paint.setStrokeCap(DlStrokeCap::kButt);
1140 paint.setColor(DlColor::kBlue());
1141
1142 // First draw full circles in blue to establish the pixels to be erased
1143 RenderArcFarm(builder, paint,
1144 {
1145 .use_center = false,
1146 .full_circles = true,
1147 });
1148
1149 paint.setColor(DlColor::kWhite());
1150
1151 // Then draw partial arcs in white over the circles to "erase" them
1152 RenderArcFarm(builder, paint,
1153 {
1154 .use_center = false,
1155 .full_circles = false,
1156 });
1157
1158 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1159 }

References x.

## ◆ TEST_P() [286/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter |
| ) |  |

Definition at line 987 of file aiks_dl_basic_unittests.cc.

987 {
988 DisplayListBuilder builder;
989 builder.Scale(GetContentScale().x, GetContentScale().y);
990 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
991
992 DlPaint paint;
993 paint.setDrawStyle(DlDrawStyle::kStroke);
994 paint.setStrokeWidth(6.0f);
995 paint.setStrokeJoin(DlStrokeJoin::kBevel);
996 paint.setColor(DlColor::kBlue());
997
998 RenderArcFarm(builder, paint,
999 {
1000 .use_center = true,
1001 .full_circles = false,
1002 .sweeps_over_360 = true,
1003 });
1004
1005 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1006 }

References x.

## ◆ TEST_P() [287/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithButtEnds |
| ) |  |

Definition at line 927 of file aiks_dl_basic_unittests.cc.

927 {
928 DisplayListBuilder builder;
929 builder.Scale(GetContentScale().x, GetContentScale().y);
930 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
931
932 DlPaint paint;
933 paint.setDrawStyle(DlDrawStyle::kStroke);
934 paint.setStrokeWidth(6.0f);
935 paint.setStrokeCap(DlStrokeCap::kButt);
936 paint.setColor(DlColor::kBlue());
937
938 RenderArcFarm(builder, paint,
939 {
940 .use_center = false,
941 .full_circles = false,
942 });
943
944 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
945 }

References x.

## ◆ TEST_P() [288/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter |
| ) |  |

Definition at line 1008 of file aiks_dl_basic_unittests.cc.

1008 {
1009 DisplayListBuilder builder;
1010 builder.Scale(GetContentScale().x, GetContentScale().y);
1011 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1012
1013 DlPaint paint;
1014 paint.setDrawStyle(DlDrawStyle::kStroke);
1015 paint.setStrokeWidth(6.0f);
1016 paint.setStrokeJoin(DlStrokeJoin::kMiter);
1017 // Default miter of 4.0 does a miter on all of the centers, but
1018 // using 3.0 will show some bevels on the widest interior angles...
1019 paint.setStrokeMiter(3.0f);
1020 paint.setColor(DlColor::kBlue());
1021
1022 RenderArcFarm(builder, paint,
1023 {
1024 .use_center = true,
1025 .full_circles = false,
1026 .sweeps_over_360 = true,
1027 });
1028
1029 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1030 }

References x.

## ◆ TEST_P() [289/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundEnds |
| ) |  |

Definition at line 967 of file aiks_dl_basic_unittests.cc.

967 {
968 DisplayListBuilder builder;
969 builder.Scale(GetContentScale().x, GetContentScale().y);
970 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
971
972 DlPaint paint;
973 paint.setDrawStyle(DlDrawStyle::kStroke);
974 paint.setStrokeWidth(6.0f);
975 paint.setStrokeCap(DlStrokeCap::kRound);
976 paint.setColor(DlColor::kBlue());
977
978 RenderArcFarm(builder, paint,
979 {
980 .use_center = false,
981 .full_circles = false,
982 });
983
984 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
985 }

References x.

## ◆ TEST_P() [290/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter |
| ) |  |

Definition at line 1032 of file aiks_dl_basic_unittests.cc.

1032 {
1033 DisplayListBuilder builder;
1034 builder.Scale(GetContentScale().x, GetContentScale().y);
1035 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1036
1037 DlPaint paint;
1038 paint.setDrawStyle(DlDrawStyle::kStroke);
1039 paint.setStrokeWidth(6.0f);
1040 paint.setStrokeJoin(DlStrokeJoin::kRound);
1041 paint.setColor(DlColor::kBlue());
1042
1043 RenderArcFarm(builder, paint,
1044 {
1045 .use_center = true,
1046 .full_circles = false,
1047 .sweeps_over_360 = true,
1048 });
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1051 }

References x.

## ◆ TEST_P() [291/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds |
| ) |  |

Definition at line 1082 of file aiks_dl_basic_unittests.cc.

1082 {
1083 DisplayListBuilder builder;
1084 builder.Scale(GetContentScale().x, GetContentScale().y);
1085 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1086
1087 DlPaint paint;
1088 paint.setDrawStyle(DlDrawStyle::kStroke);
1089 paint.setStrokeWidth(8.0f);
1090 paint.setStrokeCap(DlStrokeCap::kSquare);
1091 paint.setColor(DlColor::kRed());
1092
1093 RenderArcFarm(builder, paint,
1094 {
1095 .use_center = false,
1096 .full_circles = false,
1097 });
1098
1099 paint.setStrokeCap(DlStrokeCap::kRound);
1100 paint.setColor(DlColor::kGreen());
1101
1102 RenderArcFarm(builder, paint,
1103 {
1104 .use_center = false,
1105 .full_circles = false,
1106 });
1107
1108 paint.setStrokeCap(DlStrokeCap::kButt);
1109 paint.setColor(DlColor::kBlue());
1110
1111 RenderArcFarm(builder, paint,
1112 {
1113 .use_center = false,
1114 .full_circles = false,
1115 });
1116
1117 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1118 }

References x.

## ◆ TEST_P() [292/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtEnds |
| ) |  |

Definition at line 1053 of file aiks_dl_basic_unittests.cc.

1053 {
1054 DisplayListBuilder builder;
1055 builder.Scale(GetContentScale().x, GetContentScale().y);
1056 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1057
1058 DlPaint paint;
1059 paint.setDrawStyle(DlDrawStyle::kStroke);
1060 paint.setStrokeWidth(8.0f);
1061 paint.setStrokeCap(DlStrokeCap::kSquare);
1062 paint.setColor(DlColor::kRed());
1063
1064 RenderArcFarm(builder, paint,
1065 {
1066 .use_center = false,
1067 .full_circles = false,
1068 });
1069
1070 paint.setStrokeCap(DlStrokeCap::kButt);
1071 paint.setColor(DlColor::kBlue());
1072
1073 RenderArcFarm(builder, paint,
1074 {
1075 .use_center = false,
1076 .full_circles = false,
1077 });
1078
1079 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1080 }

References x.

## ◆ TEST_P() [293/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareEnds |
| ) |  |

Definition at line 947 of file aiks_dl_basic_unittests.cc.

947 {
948 DisplayListBuilder builder;
949 builder.Scale(GetContentScale().x, GetContentScale().y);
950 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
951
952 DlPaint paint;
953 paint.setDrawStyle(DlDrawStyle::kStroke);
954 paint.setStrokeWidth(6.0f);
955 paint.setStrokeCap(DlStrokeCap::kSquare);
956 paint.setColor(DlColor::kBlue());
957
958 RenderArcFarm(builder, paint,
959 {
960 .use_center = false,
961 .full_circles = false,
962 });
963
964 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
965 }

References x.

## ◆ TEST_P() [294/549]

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() [295/549]

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() [296/549]

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() [297/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SubpassWithClearColorOptimization |
| ) |  |

Definition at line 1507 of file aiks_dl_basic_unittests.cc.

1507 {
1508 DisplayListBuilder builder;
1509
1510 // Use a non-srcOver blend mode to ensure that we don't detect this as an
1511 // opacity peephole optimization.
1512 DlPaint paint;
1513 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1514 paint.setBlendMode(DlBlendMode::kSrc);
1515
1516 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
1517 builder.SaveLayer(bounds, &paint);
1518
1519 paint.setColor(DlColor::kTransparent());
1520 paint.setBlendMode(DlBlendMode::kSrc);
1521 builder.DrawPaint(paint);
1522 builder.Restore();
1523
1524 paint.setColor(DlColor::kBlue());
1525 paint.setBlendMode(DlBlendMode::kDstOver);
1526 builder.SaveLayer(std::nullopt, &paint);
1527 builder.Restore();
1528
1529 // This playground should appear blank on CI since we are only drawing
1530 // transparent black. If the clear color optimization is broken, the texture
1531 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
1532 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1533 }

## ◆ TEST_P() [298/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SupportsBlitToOnscreen |
| ) |  |

Definition at line 378 of file canvas_unittests.cc.

378 {
379 ContentContext context(GetContext(), nullptr);
380 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
381 /*requires_readback=*/true);
382
383 if (GetBackend() != PlaygroundBackend::kMetal) {
384 EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
385 } else {
386 EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
387 }
388 }

References CreateTestCanvas(), impeller::kMetal, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [299/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextContentsMismatchedTransformTest |
| ) |  |

Definition at line 708 of file aiks_dl_text_unittests.cc.

708 {
709 AiksContext aiks_context(GetContext(),
710 std::make_shared<TypographerContextSkia>());
711
712 // Verifies that TextContents only use the scale/transform that is
713 // computed during preroll.
714 constexpr const char* font_fixture = "Roboto-Regular.ttf";
715
716 // Construct the text blob.
717 auto c_font_fixture = std::string(font_fixture);
718 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
719 ASSERT_TRUE(mapping);
720
721 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
722 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
723
724 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
725 ASSERT_TRUE(blob);
726
727 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
728
729 // Simulate recording the text frame during preroll.
730 Matrix preroll_matrix =
731 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
732 Point preroll_point = Point{23, 45};
733 {
734 auto scale = TextFrame::RoundScaledFontSize(
735 (preroll_matrix * Matrix::MakeTranslation(preroll_point))
736 .GetMaxBasisLengthXY());
737
738 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
739 text_frame, //
740 scale, //
741 preroll_point, //
742 preroll_matrix,
743 std::nullopt //
744 );
745 }
746
747 // Now simulate rendering with a slightly different scale factor.
748 RenderTarget render_target =
749 aiks_context.GetContentContext()
750 .GetRenderTargetCache()
751 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
752
753 TextContents text_contents;
754 text_contents.SetTextFrame(text_frame);
755 text_contents.SetOffset(preroll_point);
756 text_contents.SetScale(1.6);
757 text_contents.SetColor(Color::Aqua());
758
759 Matrix not_preroll_matrix =
760 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
761
762 Entity entity;
763 entity.SetTransform(not_preroll_matrix);
764
765 std::shared_ptr<CommandBuffer> command_buffer =
766 aiks_context.GetContext()->CreateCommandBuffer();
767 std::shared_ptr<RenderPass> render_pass =
768 command_buffer->CreateRenderPass(render_target);
769
770 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
771 *render_pass));
772 }

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() [300/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextForegroundShaderWithTransform |
| ) |  |

Definition at line 593 of file aiks_dl_text_unittests.cc.

593 {
594 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
595 ASSERT_NE(mapping, nullptr);
596
597 Scalar font_size = 100;
598 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
599 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
600
601 DlPaint text_paint;
602 text_paint.setColor(DlColor::kBlue());
603
604 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
605 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
606 std::vector<Scalar> stops = {
607 0.0,
608 1.0,
609 };
610 text_paint.setColorSource(DlColorSource::MakeLinear(
611 /*start_point=*/DlPoint(0, 0), //
612 /*end_point=*/DlPoint(100, 100), //
613 /*stop_count=*/2, //
614 /*colors=*/colors.data(), //
615 /*stops=*/stops.data(), //
616 /*tile_mode=*/DlTileMode::kRepeat //
617 ));
618
619 DisplayListBuilder builder;
620 builder.Translate(100, 100);
621 builder.Rotate(45);
622
623 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
624 ASSERT_NE(blob, nullptr);
625 auto frame = MakeTextFrameFromTextBlobSkia(blob);
626 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
627
628 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
629 }

References font_size, flutter::DlTextImpeller::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [301/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextFrameSubpixelAlignment |
| ) |  |

Definition at line 317 of file aiks_dl_text_unittests.cc.

317 {
318 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
319 std::array<Scalar, 20> phase_offsets = {
320 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
321 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
322 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
323 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
324 auto callback = [&]() -> sk_sp<DisplayList> {
325 static float font_size = 20;
326 static float phase_variation = 0.2;
327 static float speed = 0.5;
328 static float magnitude = 100;
329 if (AiksTest::ImGuiBegin("Controls", nullptr,
330 ImGuiWindowFlags_AlwaysAutoResize)) {
331 ImGui::SliderFloat("Font size", &font_size, 5, 50);
332 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
333 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
334 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
335 ImGui::End();
336 }
337
338 DisplayListBuilder builder;
339 builder.Scale(GetContentScale().x, GetContentScale().y);
340
341 for (size_t i = 0; i < phase_offsets.size(); i++) {
342 DlPoint position = DlPoint(
343 200 +
344 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
345 GetSecondsElapsed() * speed)), //
346 200 + i * font_size * 1.1 //
347 );
348 if (!RenderTextInCanvasSkia(
349 GetContext(), builder,
350 "the quick brown fox jumped over "
351 "the lazy dog!.?",
352 "Roboto-Regular.ttf",
353 {.font_size = font_size, .position = position})) {
354 return nullptr;
355 }
356 }
357 return builder.Build();
358 };
359
360 ASSERT_TRUE(OpenPlaygroundHere(callback));
361 }

References font_size, impeller::k2Pi, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [302/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated |
| ) |  |

Definition at line 489 of file aiks_dl_text_unittests.cc.

489 {
490 DisplayListBuilder builder;
491
492 builder.Scale(GetContentScale().x, GetContentScale().y);
493 DlPaint paint;
494 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
495 builder.DrawPaint(paint);
496
497 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
498 0, 0.5, 0, 0, //
499 0, 0, 0.3, 0, //
500 100, 100, 0, 1.3));
501 ASSERT_TRUE(RenderTextInCanvasSkia(
502 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
503 "Roboto-Regular.ttf"));
504
505 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
506 }

References RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [303/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated180Degrees |
| ) |  |

Definition at line 280 of file aiks_dl_text_unittests.cc.

280 {
281 float fpivot[2] = {200 + 30, 200 - 20};
282 float rotation = 180;
283 float foffset[2] = {200, 200};
284
285 auto callback = [&]() -> sk_sp<DisplayList> {
286 if (AiksTest::ImGuiBegin("Controls", nullptr,
287 ImGuiWindowFlags_AlwaysAutoResize)) {
288 ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
289 ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
290 ImGui::SliderFloat("rotation", &rotation, 0, 360);
291 ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
292 ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
293 ImGui::End();
294 }
295 DisplayListBuilder builder;
296 builder.Scale(GetContentScale().x, GetContentScale().y);
297 builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
298
299 builder.Save();
300 DlPoint pivot = Point(fpivot[0], fpivot[1]);
301 builder.Translate(pivot.x, pivot.y);
302 builder.Rotate(rotation);
303 builder.Translate(-pivot.x, -pivot.y);
304
305 RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
306 TextRenderOptions{
307 .color = DlColor::kBlack(),
308 .position = DlPoint(foffset[0], foffset[1]),
309 });
310
311 builder.Restore();
312 return builder.Build();
313 };
314 ASSERT_TRUE(OpenPlaygroundHere(callback));
315 }

References impeller::testing::TextRenderOptions::color, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [304/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextWithShadowCache |
| ) |  |

Definition at line 774 of file aiks_dl_text_unittests.cc.

774 {
775 DisplayListBuilder builder;
776 builder.Scale(GetContentScale().x, GetContentScale().y);
777 DlPaint paint;
778 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
779 builder.DrawPaint(paint);
780
781 AiksContext aiks_context(GetContext(),
782 std::make_shared<TypographerContextSkia>());
783 // Cache empty
784 EXPECT_EQ(aiks_context.GetContentContext()
785 .GetTextShadowCache()
786 .GetCacheSizeForTesting(),
787 0u);
788
789 ASSERT_TRUE(RenderTextInCanvasSkia(
790 GetContext(), builder, "Hello World", kFontFixture,
791 TextRenderOptions{
792 .color = DlColor::kBlue(),
793 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
794
795 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
796
797 // Text should be cached.
798 EXPECT_EQ(aiks_context.GetContentContext()
799 .GetTextShadowCache()
800 .GetCacheSizeForTesting(),
801 1u);
802 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [305/549]

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() [306/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransformMultipliesCorrectly |
| ) |  |

Definition at line 71 of file canvas_unittests.cc.

71 {
72 ContentContext context(GetContext(), nullptr);
73 auto canvas = CreateTestCanvas(context);
74
75 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
76
77 // clang-format off
78 canvas->Translate(Vector3(100, 200));
79 ASSERT_MATRIX_NEAR(
80 canvas->GetCurrentTransform(),
81 Matrix( 1, 0, 0, 0,
82 0, 1, 0, 0,
83 0, 0, 1, 0,
84 100, 200, 0, 1));
85
86 canvas->Rotate(Radians(kPiOver2));
87 ASSERT_MATRIX_NEAR(
88 canvas->GetCurrentTransform(),
89 Matrix( 0, 1, 0, 0,
90 -1, 0, 0, 0,
91 0, 0, 1, 0,
92 100, 200, 0, 1));
93
94 canvas->Scale(Vector3(2, 3));
95 ASSERT_MATRIX_NEAR(
96 canvas->GetCurrentTransform(),
97 Matrix( 0, 2, 0, 0,
98 -3, 0, 0, 0,
99 0, 0, 0, 0,
100 100, 200, 0, 1));
101
102 canvas->Translate(Vector3(100, 200));
103 ASSERT_MATRIX_NEAR(
104 canvas->GetCurrentTransform(),
105 Matrix( 0, 2, 0, 0,
106 -3, 0, 0, 0,
107 0, 0, 0, 0,
108 -500, 400, 0, 1));
109 // clang-format on
110 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [307/549]

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() [308/549]

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() [309/549]

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() [310/549]

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() [311/549]

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() [312/549]

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() [313/549]

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() [314/549]

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() [315/549]

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() [316/549]

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() [317/549]

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() [318/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VarietyOfTextScalesShowingRasterAndPath |
| ) |  |

Definition at line 877 of file aiks_dl_text_unittests.cc.

877 {
878 DisplayListBuilder builder;
879 DlPaint paint;
880 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
881 builder.DrawPaint(paint);
882 builder.Scale(GetContentScale().x, GetContentScale().y);
883
884 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
885 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
886 Scalar space = 16;
887 Scalar x = 0;
888 for (auto i = 0u; i < scales.size(); i++) {
889 builder.Save();
890 builder.Scale(scales[i], scales[i]);
891 RenderTextInCanvasSkia(
892 GetContext(), builder, "lo", "Roboto-Regular.ttf",
893 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
894 space += spacing[i];
895 if (i == 3) {
896 x = 10;
897 space = 16;
898 }
899 builder.Restore();
900 }
901 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
902 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [319/549]

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() [320/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionData |
| ) |  |

Definition at line 98 of file aiks_dl_vertices_unittests.cc.

98 {
99 DisplayListBuilder builder;
100 DlPaint paint;
101 auto image =
102 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
103 auto size = image->impeller_texture()->GetSize();
104
105 paint.setColorSource(
106 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
107
108 std::vector<DlPoint> positions = {
109 DlPoint(0, 0), DlPoint(size.width, 0),
110 DlPoint(0, size.height), DlPoint(size.width, 0),
111 DlPoint(0, 0), DlPoint(size.width, size.height),
112 };
113 std::vector<DlColor> colors = {
114 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
115 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
116 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
117 };
118
119 auto vertices =
120 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
121
122 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
123 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
124 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [321/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionDataAdvancedBlend |
| ) |  |

Definition at line 126 of file aiks_dl_vertices_unittests.cc.

126 {
127 DisplayListBuilder builder;
128 DlPaint paint;
129 auto image =
130 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
131 auto size = image->impeller_texture()->GetSize();
132
133 paint.setColorSource(
134 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
135
136 std::vector<DlPoint> positions = {
137 DlPoint(0, 0), DlPoint(size.width, 0),
138 DlPoint(0, size.height), DlPoint(size.width, 0),
139 DlPoint(0, 0), DlPoint(size.width, size.height),
140 };
141 std::vector<DlColor> colors = {
142 DlColor::kRed().modulateOpacity(0.5),
143 DlColor::kBlue().modulateOpacity(0.5),
144 DlColor::kGreen().modulateOpacity(0.5),
145 DlColor::kRed().modulateOpacity(0.5),
146 DlColor::kBlue().modulateOpacity(0.5),
147 DlColor::kGreen().modulateOpacity(0.5),
148 };
149
150 auto vertices =
151 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
152
153 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
154 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
155 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [322/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionData |
| ) |  |

Definition at line 50 of file aiks_dl_vertices_unittests.cc.

50 {
51 DisplayListBuilder builder;
52 DlPaint paint;
53 auto image =
54 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
55 auto size = image->impeller_texture()->GetSize();
56
57 paint.setColorSource(
58 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
59
60 std::vector<DlPoint> vertex_coordinates = {
61 DlPoint(0, 0),
62 DlPoint(size.width, 0),
63 DlPoint(0, size.height),
64 };
65 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
66 {0, 1, 2}, {}, {});
67
68 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
69 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
70 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [323/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionDataWithTranslate |
| ) |  |

Definition at line 73 of file aiks_dl_vertices_unittests.cc.

73 {
74 DisplayListBuilder builder;
75 DlPaint paint;
76 auto image =
77 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
78 auto size = image->impeller_texture()->GetSize();
79
80 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
81 paint.setColorSource(
82 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp,
83 DlImageSampling::kLinear, &matrix));
84
85 std::vector<DlPoint> positions = {
86 DlPoint(0, 0),
87 DlPoint(size.width, 0),
88 DlPoint(0, size.height),
89 };
90 auto vertices =
91 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
92
93 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
94 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
95 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [324/549]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryWithMaskFilter |
| ) |  |

Definition at line 556 of file aiks_dl_vertices_unittests.cc.

556 {
557 DisplayListBuilder builder;
558 DlPaint paint;
559 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
560
561 std::vector<DlPoint> vertex_coordinates = {
562 DlPoint(0, 0),
563 DlPoint(400, 0),
564 DlPoint(0, 400),
565 };
566 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
567 {0, 1, 2}, {}, {});
568
569 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
570 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
571 }

## ◆ TEST_P() [325/549]

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() [326/549]

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() [327/549]

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() [328/549]

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() [329/549]

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() [330/549]

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() [331/549]

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() [332/549]

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() [333/549]

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() [334/549]

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() [335/549]

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() [336/549]

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() [337/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 177 of file compute_unittests.cc.

177 {
178 using CS = ThreadgroupSizingTestComputeShader;
179 auto context = GetContext();
180 ASSERT_TRUE(context);
181 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
182
183 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
184 auto pipeline_desc =
185 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
186 ASSERT_TRUE(pipeline_desc.has_value());
187 auto compute_pipeline =
188 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
189 ASSERT_TRUE(compute_pipeline);
190
191 auto cmd_buffer = context->CreateCommandBuffer();
192 auto pass = cmd_buffer->CreateComputePass();
193 ASSERT_TRUE(pass && pass->IsValid());
194
195 static constexpr size_t kCount = 2048;
196
197 pass->SetPipeline(compute_pipeline);
198
199 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
200 context, "Output Buffer");
201
202 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
203
204 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
205 ASSERT_TRUE(pass->EncodeCommands());
206
207 fml::AutoResetWaitableEvent latch;
208 ASSERT_TRUE(
209 context->GetCommandQueue()
210 ->Submit({cmd_buffer},
211 [&latch, output_buffer](CommandBuffer::Status status) {
212 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
213
214 auto view = DeviceBuffer::AsBufferView(output_buffer);
215 EXPECT_EQ(view.GetRange().length,
216 sizeof(CS::OutputData<kCount>));
217
218 CS::OutputData<kCount>* output =
219 reinterpret_cast<CS::OutputData<kCount>*>(
220 output_buffer->OnGetContents());
221 EXPECT_TRUE(output);
222 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
223 latch.Signal();
224 })
225 .ok());
226
227 latch.Wait();
228 }

## ◆ TEST_P() [338/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCompute1DimensionalData |
| ) |  |

Definition at line 377 of file compute_unittests.cc.

377 {
378 using CS = SampleComputeShader;
379 auto context = GetContext();
380 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
381 context->GetIdleWaiter());
382 ASSERT_TRUE(context);
383 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
384
385 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
386 auto pipeline_desc =
387 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
388 ASSERT_TRUE(pipeline_desc.has_value());
389 auto compute_pipeline =
390 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
391 ASSERT_TRUE(compute_pipeline);
392
393 auto cmd_buffer = context->CreateCommandBuffer();
394 auto pass = cmd_buffer->CreateComputePass();
395 ASSERT_TRUE(pass && pass->IsValid());
396
397 static constexpr size_t kCount = 5;
398
399 pass->SetPipeline(compute_pipeline);
400
401 CS::Info info{.count = kCount};
402 CS::Input0<kCount> input_0;
403 CS::Input1<kCount> input_1;
404 for (size_t i = 0; i < kCount; i++) {
405 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
406 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
407 }
408
409 input_0.fixed_array[1] = IPoint32(2, 2);
410 input_1.fixed_array[0] = UintPoint32(3, 3);
411 input_0.some_int = 5;
412 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
413
414 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
415 context, "Output Buffer");
416
417 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
418 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
419 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
420 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
421
422 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
423 ASSERT_TRUE(pass->EncodeCommands());
424
425 fml::AutoResetWaitableEvent latch;
426 ASSERT_TRUE(
427 context->GetCommandQueue()
428 ->Submit(
429 {cmd_buffer},
430 [&latch, output_buffer, &input_0,
431 &input_1](CommandBuffer::Status status) {
432 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
433
434 auto view = DeviceBuffer::AsBufferView(output_buffer);
435 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
436
437 CS::Output<kCount>* output =
438 reinterpret_cast<CS::Output<kCount>*>(
439 output_buffer->OnGetContents());
440 EXPECT_TRUE(output);
441 for (size_t i = 0; i < kCount; i++) {
442 Vector4 vector = output->elements[i];
443 Vector4 computed = input_0.elements[i] * input_1.elements[i];
444 EXPECT_EQ(vector,
445 Vector4(computed.x + 2 + input_1.some_struct.i,
446 computed.y + 3 + input_1.some_struct.vf.x,
447 computed.z + 5 + input_1.some_struct.vf.y,
448 computed.w));
449 }
450 latch.Signal();
451 })
452 .ok());
453
454 latch.Wait();
455 }
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:329
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:330

References impeller::interop::Create().

## ◆ TEST_P() [339/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 110 of file compute_unittests.cc.

110 {
111 using CS = PrefixSumTestComputeShader;
112 auto context = GetContext();
113 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
114 context->GetIdleWaiter());
115 ASSERT_TRUE(context);
116 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
117
118 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
119 auto pipeline_desc =
120 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
121 ASSERT_TRUE(pipeline_desc.has_value());
122 auto compute_pipeline =
123 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
124 ASSERT_TRUE(compute_pipeline);
125
126 auto cmd_buffer = context->CreateCommandBuffer();
127 auto pass = cmd_buffer->CreateComputePass();
128 ASSERT_TRUE(pass && pass->IsValid());
129
130 static constexpr size_t kCount = 5;
131
132 pass->SetPipeline(compute_pipeline);
133
134 CS::InputData<kCount> input_data;
135 input_data.count = kCount;
136 for (size_t i = 0; i < kCount; i++) {
137 input_data.data[i] = 1 + i;
138 }
139
140 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
141 context, "Output Buffer");
142
143 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
144 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
145
146 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
147 ASSERT_TRUE(pass->EncodeCommands());
148
149 fml::AutoResetWaitableEvent latch;
150 ASSERT_TRUE(
151 context->GetCommandQueue()
152 ->Submit({cmd_buffer},
153 [&latch, output_buffer](CommandBuffer::Status status) {
154 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
155
156 auto view = DeviceBuffer::AsBufferView(output_buffer);
157 EXPECT_EQ(view.GetRange().length,
158 sizeof(CS::OutputData<kCount>));
159
160 CS::OutputData<kCount>* output =
161 reinterpret_cast<CS::OutputData<kCount>*>(
162 output_buffer->OnGetContents());
163 EXPECT_TRUE(output);
164
165 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
166 for (size_t i = 0; i < kCount; i++) {
167 auto computed_sum = output->data[i];
168 EXPECT_EQ(computed_sum, expected[i]);
169 }
170 latch.Signal();
171 })
172 .ok());
173
174 latch.Wait();
175 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [340/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 230 of file compute_unittests.cc.

230 {
231 using CS = PrefixSumTestComputeShader;
232
233 auto context = GetContext();
234 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
235 context->GetIdleWaiter());
236
237 ASSERT_TRUE(context);
238 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
239
240 auto callback = [&](RenderPass& render_pass) -> bool {
241 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
242 auto pipeline_desc =
243 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
244 auto compute_pipeline =
245 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
246
247 auto cmd_buffer = context->CreateCommandBuffer();
248 auto pass = cmd_buffer->CreateComputePass();
249
250 static constexpr size_t kCount = 1023;
251
252 pass->SetPipeline(compute_pipeline);
253
254 CS::InputData<kCount> input_data;
255 input_data.count = kCount;
256 for (size_t i = 0; i < kCount; i++) {
257 input_data.data[i] = 1 + i;
258 }
259
260 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
261 context, "Output Buffer");
262
263 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
264 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
265
266 pass->Compute(ISize(kCount, 1));
267 pass->EncodeCommands();
268 host_buffer->Reset();
269 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
270 };
271 ASSERT_TRUE(OpenPlaygroundHere(callback));
272 }

References impeller::interop::Create().

## ◆ TEST_P() [341/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCreateComputePass |
| ) |  |

Definition at line 30 of file compute_unittests.cc.

30 {
31 using CS = SampleComputeShader;
32 auto context = GetContext();
33 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
34 context->GetIdleWaiter());
35 ASSERT_TRUE(context);
36 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
37
38 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
39 auto pipeline_desc =
40 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
41 ASSERT_TRUE(pipeline_desc.has_value());
42 auto compute_pipeline =
43 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
44 ASSERT_TRUE(compute_pipeline);
45
46 auto cmd_buffer = context->CreateCommandBuffer();
47 auto pass = cmd_buffer->CreateComputePass();
48 ASSERT_TRUE(pass && pass->IsValid());
49
50 static constexpr size_t kCount = 5;
51
52 pass->SetPipeline(compute_pipeline);
53
54 CS::Info info{.count = kCount};
55 CS::Input0<kCount> input_0;
56 CS::Input1<kCount> input_1;
57 for (size_t i = 0; i < kCount; i++) {
58 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
59 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
60 }
61
62 input_0.fixed_array[1] = IPoint32(2, 2);
63 input_1.fixed_array[0] = UintPoint32(3, 3);
64 input_0.some_int = 5;
65 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
66
67 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
68 context, "Output Buffer");
69
70 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
71 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
72 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
73 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
74
75 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
76 ASSERT_TRUE(pass->EncodeCommands());
77
78 fml::AutoResetWaitableEvent latch;
79 ASSERT_TRUE(
80 context->GetCommandQueue()
81 ->Submit(
82 {cmd_buffer},
83 [&latch, output_buffer, &input_0,
84 &input_1](CommandBuffer::Status status) {
85 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
86
87 auto view = DeviceBuffer::AsBufferView(output_buffer);
88 EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
89
90 CS::Output<kCount>* output =
91 reinterpret_cast<CS::Output<kCount>*>(
92 output_buffer->OnGetContents());
93 EXPECT_TRUE(output);
94 for (size_t i = 0; i < kCount; i++) {
95 Vector4 vector = output->elements[i];
96 Vector4 computed = input_0.elements[i] * input_1.elements[i];
97 EXPECT_EQ(vector,
98 Vector4(computed.x + 2 + input_1.some_struct.i,
99 computed.y + 3 + input_1.some_struct.vf.x,
100 computed.z + 5 + input_1.some_struct.vf.y,
101 computed.w));
102 }
103 latch.Signal();
104 })
105 .ok());
106
107 latch.Wait();
108 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [342/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CapabilitiesReportSupport |
| ) |  |

Definition at line 24 of file compute_unittests.cc.

24 {
25 auto context = GetContext();
26 ASSERT_TRUE(context);
27 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
28 }

## ◆ TEST_P() [343/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 274 of file compute_unittests.cc.

274 {
275 using CS1 = Stage1ComputeShader;
276 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
277 using CS2 = Stage2ComputeShader;
278 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
279
280 auto context = GetContext();
281 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
282 context->GetIdleWaiter());
283 ASSERT_TRUE(context);
284 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
285
286 auto pipeline_desc_1 =
287 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
288 ASSERT_TRUE(pipeline_desc_1.has_value());
289 auto compute_pipeline_1 =
290 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
291 ASSERT_TRUE(compute_pipeline_1);
292
293 auto pipeline_desc_2 =
294 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
295 ASSERT_TRUE(pipeline_desc_2.has_value());
296 auto compute_pipeline_2 =
297 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
298 ASSERT_TRUE(compute_pipeline_2);
299
300 auto cmd_buffer = context->CreateCommandBuffer();
301 auto pass = cmd_buffer->CreateComputePass();
302 ASSERT_TRUE(pass && pass->IsValid());
303
304 static constexpr size_t kCount1 = 5;
305 static constexpr size_t kCount2 = kCount1 * 2;
306
307 CS1::Input<kCount1> input_1;
308 input_1.count = kCount1;
309 for (size_t i = 0; i < kCount1; i++) {
310 input_1.elements[i] = i;
311 }
312
313 CS2::Input<kCount2> input_2;
314 input_2.count = kCount2;
315 for (size_t i = 0; i < kCount2; i++) {
316 input_2.elements[i] = i;
317 }
318
319 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
320 context, "Output Buffer Stage 1");
321 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
322 context, "Output Buffer Stage 2");
323
324 {
325 pass->SetPipeline(compute_pipeline_1);
326
327 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
328 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
329
330 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
331 pass->AddBufferMemoryBarrier();
332 }
333
334 {
335 pass->SetPipeline(compute_pipeline_2);
336
337 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
338 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
339 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
340 }
341
342 ASSERT_TRUE(pass->EncodeCommands());
343
344 fml::AutoResetWaitableEvent latch;
345 ASSERT_TRUE(
346 context->GetCommandQueue()
347 ->Submit({cmd_buffer},
348 [&latch, &output_buffer_1,
349 &output_buffer_2](CommandBuffer::Status status) {
350 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
351
352 CS1::Output<kCount2>* output_1 =
353 reinterpret_cast<CS1::Output<kCount2>*>(
354 output_buffer_1->OnGetContents());
355 EXPECT_TRUE(output_1);
356 EXPECT_EQ(output_1->count, 10u);
357 EXPECT_THAT(
358 output_1->elements,
359 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
360
361 CS2::Output<kCount2>* output_2 =
362 reinterpret_cast<CS2::Output<kCount2>*>(
363 output_buffer_2->OnGetContents());
364 EXPECT_TRUE(output_2);
365 EXPECT_EQ(output_2->count, 10u);
366 EXPECT_THAT(output_2->elements,
367 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
368 18, 16, 24));
369
370 latch.Signal();
371 })
372 .ok());
373
374 latch.Wait();
375 }
impeller::SampleCount::kCount1
@ kCount1

References impeller::interop::Create(), and impeller::kCount1.

## ◆ TEST_P() [344/549]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 457 of file compute_unittests.cc.

457 {
458 using CS = SampleComputeShader;
459 auto context = GetContext();
460 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
461 context->GetIdleWaiter());
462 ASSERT_TRUE(context);
463 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
464
465 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
466 auto pipeline_desc =
467 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
468 ASSERT_TRUE(pipeline_desc.has_value());
469 auto compute_pipeline =
470 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
471 ASSERT_TRUE(compute_pipeline);
472
473 auto cmd_buffer = context->CreateCommandBuffer();
474 auto pass = cmd_buffer->CreateComputePass();
475 ASSERT_TRUE(pass && pass->IsValid());
476
477 static constexpr size_t kCount = 5;
478
479 pass->SetPipeline(compute_pipeline);
480
481 CS::Info info{.count = kCount};
482 CS::Input0<kCount> input_0;
483 CS::Input1<kCount> input_1;
484 for (size_t i = 0; i < kCount; i++) {
485 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
486 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
487 }
488
489 input_0.fixed_array[1] = IPoint32(2, 2);
490 input_1.fixed_array[0] = UintPoint32(3, 3);
491 input_0.some_int = 5;
492 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
493
494 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
495 context, "Output Buffer");
496
497 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
498 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
499 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
500 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
501
502 // Intentionally making the grid size zero in one dimension. No GPU will
503 // tolerate this.
504 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
505 pass->EncodeCommands();
506 }

References impeller::interop::Create().

## ◆ TEST_P() [345/549]

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() [346/549]

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() [347/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1180 of file dl_unittests.cc.

1180 {
1181 flutter::DisplayListBuilder builder;
1182
1183 {
1184 builder.SaveLayer(std::nullopt, nullptr);
1185 builder.Translate(100, 100);
1186 flutter::DlPaint paint;
1187 paint.setColor(flutter::DlColor::kRed());
1188 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1189 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1190 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1191 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1192 builder.Restore();
1193 }
1194 {
1195 builder.SaveLayer(std::nullopt, nullptr);
1196 builder.Translate(300, 100);
1197 flutter::DlPaint paint;
1198 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1199 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1200 paint.setColor(flutter::DlColor::kRed());
1201 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1202 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1203 builder.Restore();
1204 }
1205 {
1206 builder.SaveLayer(std::nullopt, nullptr);
1207 builder.Translate(100, 300);
1208 flutter::DlPaint paint;
1209 paint.setColor(flutter::DlColor::kRed());
1210 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1211 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1212 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1213 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1214 builder.Restore();
1215 }
1216 {
1217 builder.SaveLayer(std::nullopt, nullptr);
1218 builder.Translate(300, 300);
1219 flutter::DlPaint paint;
1220 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1221 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1222 paint.setColor(flutter::DlColor::kRed());
1223 paint.setBlendMode(flutter::DlBlendMode::kDst);
1224 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1225 builder.Restore();
1226 }
1227
1228 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1229 }

## ◆ TEST_P() [348/549]

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() [349/549]

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() [350/549]

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

References impeller::DrawPlaygroundLine(), use_center, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [351/549]

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(), impeller::Color::Red(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [352/549]

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() [353/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1231 of file dl_unittests.cc.

1231 {
1232 flutter::DisplayListBuilder builder;
1233 const float green_color_matrix[20] = {
1234 0, 0, 0, 0, 0, //
1235 0, 0, 0, 0, 1, //
1236 0, 0, 0, 0, 0, //
1237 0, 0, 0, 1, 0, //
1238 };
1239 const float blue_color_matrix[20] = {
1240 0, 0, 0, 0, 0, //
1241 0, 0, 0, 0, 0, //
1242 0, 0, 0, 0, 1, //
1243 0, 0, 0, 1, 0, //
1244 };
1245 auto green_color_filter =
1246 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1247 auto blue_color_filter =
1248 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1249 auto blue_image_filter =
1250 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1251
1252 flutter::DlPaint paint;
1253 paint.setColor(flutter::DlColor::kRed());
1254 paint.setColorFilter(green_color_filter);
1255 paint.setImageFilter(blue_image_filter);
1256 builder.DrawRect(DlRect::MakeLTRB(100, 100, 500, 500), paint);
1257 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1258 }

## ◆ TEST_P() [354/549]

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() [355/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 724 of file dl_unittests.cc.

724 {
725 // Image is drawn with corners to scale and center pieces stretched to fit.
726 auto texture = CreateTextureForFixture("embarcadero.jpg");
727 flutter::DisplayListBuilder builder;
728 auto size = texture->GetSize();
729 builder.DrawImageNine(
730 DlImageImpeller::Make(texture),
731 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
732 size.height * 3 / 4),
733 DlRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
734 flutter::DlFilterMode::kNearest, nullptr);
735 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
736 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [356/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 770 of file dl_unittests.cc.

770 {
771 // Edge case, the width and height of the corners does not leave any
772 // room for the center slices. Only the corners are displayed.
773 auto texture = CreateTextureForFixture("embarcadero.jpg");
774 flutter::DisplayListBuilder builder;
775 auto size = texture->GetSize();
776 builder.DrawImageNine(
777 DlImageImpeller::Make(texture),
778 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
779 size.height * 3 / 4),
780 DlRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
781 flutter::DlFilterMode::kNearest, nullptr);
782 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
783 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [357/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 754 of file dl_unittests.cc.

754 {
755 // Edge case, the height of the corners does not leave any room for the
756 // center slice. The center (across the horizontal axis) is folded out of the
757 // resulting image.
758 auto texture = CreateTextureForFixture("embarcadero.jpg");
759 flutter::DisplayListBuilder builder;
760 auto size = texture->GetSize();
761 builder.DrawImageNine(
762 DlImageImpeller::Make(texture),
763 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
764 size.height * 3 / 4),
765 DlRect::MakeLTRB(0, 0, size.width, size.height / 2),
766 flutter::DlFilterMode::kNearest, nullptr);
767 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
768 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [358/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 738 of file dl_unittests.cc.

738 {
739 // Edge case, the width of the corners does not leave any room for the
740 // center slice. The center (across the vertical axis) is folded out of the
741 // resulting image.
742 auto texture = CreateTextureForFixture("embarcadero.jpg");
743 flutter::DisplayListBuilder builder;
744 auto size = texture->GetSize();
745 builder.DrawImageNine(
746 DlImageImpeller::Make(texture),
747 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
748 size.height * 3 / 4),
749 DlRect::MakeLTRB(0, 0, size.width / 2, size.height),
750 flutter::DlFilterMode::kNearest, nullptr);
751 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
752 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [359/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 785 of file dl_unittests.cc.

785 {
786 // Edge case, there is not enough room for the corners to be drawn
787 // without scaling them down.
788 auto texture = CreateTextureForFixture("embarcadero.jpg");
789 flutter::DisplayListBuilder builder;
790 auto size = texture->GetSize();
791 builder.DrawImageNine(
792 DlImageImpeller::Make(texture),
793 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
794 size.height * 3 / 4),
795 DlRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
796 flutter::DlFilterMode::kNearest, nullptr);
797 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
798 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [360/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1128 of file dl_unittests.cc.

1128 {
1129 const flutter::DlColor colors[2] = {
1130 flutter::DlColor(0xFFF44336),
1131 flutter::DlColor(0xFF2196F3),
1132 };
1133 const float stops[2] = {0.0, 1.0};
1134 flutter::DlPaint paint;
1135 flutter::DisplayListBuilder builder;
1136 auto clip_bounds = DlRect::MakeWH(300.0, 300.0);
1137 builder.Save();
1138 builder.Translate(100, 100);
1139 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1140 auto linear =
1141 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1142 stops, flutter::DlTileMode::kRepeat);
1143 paint.setColorSource(linear);
1144 builder.DrawPaint(paint);
1145 builder.Restore();
1146
1147 builder.Save();
1148 builder.Translate(500, 100);
1149 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1150 auto radial = flutter::DlColorSource::MakeRadial(
1151 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1152 paint.setColorSource(radial);
1153 builder.DrawPaint(paint);
1154 builder.Restore();
1155
1156 builder.Save();
1157 builder.Translate(100, 500);
1158 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1159 auto sweep =
1160 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1161 stops, flutter::DlTileMode::kRepeat);
1162 paint.setColorSource(sweep);
1163 builder.DrawPaint(paint);
1164 builder.Restore();
1165
1166 builder.Save();
1167 builder.Translate(500, 500);
1168 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1169 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1170 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1171 flutter::DlTileMode::kRepeat,
1172 flutter::DlTileMode::kRepeat);
1173 paint.setColorSource(image);
1174 builder.DrawPaint(paint);
1175 builder.Restore();
1176
1177 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1178 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [361/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 812 of file dl_unittests.cc.

812 {
813 flutter::DisplayListBuilder builder;
814 DlPoint points[7] = {
815 {0, 0}, //
816 {100, 100}, //
817 {100, 0}, //
818 {0, 100}, //
819 {0, 0}, //
820 {48, 48}, //
821 {52, 52}, //
822 };
823 std::vector<flutter::DlStrokeCap> caps = {
824 flutter::DlStrokeCap::kButt,
825 flutter::DlStrokeCap::kRound,
826 flutter::DlStrokeCap::kSquare,
827 };
828 flutter::DlPaint paint =
829 flutter::DlPaint() //
830 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
831 .setStrokeWidth(20);
832 builder.Translate(50, 50);
833 for (auto cap : caps) {
834 paint.setStrokeCap(cap);
835 builder.Save();
836 builder.DrawPoints(flutter::DlPointMode::kPoints, 7, points, paint);
837 builder.Translate(150, 0);
838 builder.DrawPoints(flutter::DlPointMode::kLines, 5, points, paint);
839 builder.Translate(150, 0);
840 builder.DrawPoints(flutter::DlPointMode::kPolygon, 5, points, paint);
841 builder.Restore();
842 builder.Translate(0, 150);
843 }
844 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
845 }

References points.

## ◆ TEST_P() [362/549]

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() [363/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1114 of file dl_unittests.cc.

1114 {
1115 flutter::DlPaint paint;
1116 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1117 flutter::DisplayListBuilder builder;
1118 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1119 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1120 builder.Translate(0, 200);
1121
1122 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1123 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1124
1125 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1126 }

## ◆ TEST_P() [364/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 870 of file dl_unittests.cc.

870 {
871 flutter::DisplayListBuilder builder;
872 flutter::DlPaint paint;
873
874 auto content_scale = GetContentScale() * 0.8;
875 builder.Scale(content_scale.x, content_scale.y);
876
877 constexpr size_t star_spikes = 5;
878 constexpr DlScalar half_spike_rotation = kPi / star_spikes;
879 constexpr DlScalar radius = 40;
880 constexpr DlScalar spike_size = 10;
881 constexpr DlScalar outer_radius = radius + spike_size;
882 constexpr DlScalar inner_radius = radius - spike_size;
883 std::array<DlPoint, star_spikes * 2> star;
884 for (size_t i = 0; i < star_spikes; i++) {
885 const DlScalar rotation = half_spike_rotation * i * 2;
886 star[i * 2] = DlPoint(50 + std::sin(rotation) * outer_radius,
887 50 - std::cos(rotation) * outer_radius);
888 star[i * 2 + 1] =
889 DlPoint(50 + std::sin(rotation + half_spike_rotation) * inner_radius,
890 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
891 }
892
893 std::array<DlPath, 4> paths = {
894 DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100)),
895 DlPath::MakeRoundRectXY(DlRect::MakeXYWH(20, 0, 200, 100), 30, 30),
896 DlPath::MakeCircle(DlPoint(100, 50), 50),
897 DlPath::MakePoly(star.data(), star.size(), true),
898 };
899 paint.setColor(flutter::DlColor::kWhite());
900 builder.DrawPaint(paint);
901 paint.setColor(flutter::DlColor::kCyan());
902 builder.Translate(100, 50);
903 for (size_t x = 0; x < paths.size(); x++) {
904 builder.Save();
905 for (size_t y = 0; y < 6; y++) {
906 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
907 1);
908 builder.DrawPath(paths[x], paint);
909 builder.Translate(0, 150);
910 }
911 builder.Restore();
912 builder.Translate(250, 0);
913 }
914
915 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
916 }

References impeller::kPi, and x.

## ◆ TEST_P() [365/549]

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() [366/549]

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() [367/549]

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() [368/549]

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() [369/549]

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() [370/549]

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() [371/549]

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() [372/549]

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() [373/549]

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() [374/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 952 of file dl_unittests.cc.

952 {
953 auto boston = CreateTextureForFixture("boston.jpg");
954
955 auto callback = [&]() {
956 static int selected_matrix_type = 0;
957 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
958
959 static float ctm_translation[2] = {200, 200};
960 static float ctm_scale[2] = {0.65, 0.65};
961 static float ctm_skew[2] = {0, 0};
962
963 static bool enable = true;
964 static float translation[2] = {100, 100};
965 static float scale[2] = {0.8, 0.8};
966 static float skew[2] = {0.2, 0.2};
967
968 static bool enable_savelayer = true;
969
970 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
971 {
972 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
973 sizeof(matrix_type_names) / sizeof(char*));
974
975 ImGui::TextWrapped("Current Transform");
976 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
977 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
978 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
979
980 ImGui::TextWrapped(
981 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
982 "The only difference is that MatrixFilter doesn't affect the effect "
983 "transform, whereas LocalMatrixFilter does.");
984 // Note: See this behavior in:
985 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
986 ImGui::Checkbox("Enable", &enable);
987 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
988 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
989 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
990
991 ImGui::TextWrapped(
992 "Rendering the filtered image within a layer can expose bounds "
993 "issues. If the rendered image gets cut off when this setting is "
994 "enabled, there's a coverage bug in the filter.");
995 ImGui::Checkbox("Render in layer", &enable_savelayer);
996 }
997 ImGui::End();
998
999 flutter::DisplayListBuilder builder;
1000 flutter::DlPaint paint;
1001
1002 if (enable_savelayer) {
1003 builder.SaveLayer(std::nullopt, nullptr);
1004 }
1005 {
1006 auto content_scale = GetContentScale();
1007 builder.Scale(content_scale.x, content_scale.y);
1008
1009 // Set the current transform
1010 auto ctm_matrix = Matrix::MakeRow(
1011 ctm_scale[0], ctm_skew[0], 0.0f, ctm_translation[0], //
1012 ctm_skew[1], ctm_scale[1], 0.0f, ctm_translation[1], //
1013 0, 0, 1, 0, //
1014 0, 0, 0, 1);
1015 builder.Transform(ctm_matrix);
1016
1017 // Set the matrix filter
1018 auto filter_matrix =
1019 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1020 skew[1], scale[1], 0.0f, translation[1], //
1021 0.0f, 0.0f, 1.0f, 0.0f, //
1022 0.0f, 0.0f, 0.0f, 1.0f);
1023
1024 if (enable) {
1025 switch (selected_matrix_type) {
1026 case 0: {
1027 auto filter = flutter::DlMatrixImageFilter(
1028 filter_matrix, flutter::DlImageSampling::kLinear);
1029 paint.setImageFilter(&filter);
1030 break;
1031 }
1032 case 1: {
1033 auto internal_filter =
1034 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1035 .shared();
1036 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1037 internal_filter);
1038 paint.setImageFilter(&filter);
1039 break;
1040 }
1041 }
1042 }
1043
1044 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(),
1045 flutter::DlImageSampling::kLinear, &paint);
1046 }
1047 if (enable_savelayer) {
1048 builder.Restore();
1049 }
1050
1051 return builder.Build();
1052 };
1053
1054 ASSERT_TRUE(OpenPlaygroundHere(callback));
1055 }

References impeller::DlImageImpeller::Make(), and impeller::Matrix::MakeRow().

## ◆ TEST_P() [375/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1057 of file dl_unittests.cc.

1057 {
1058 auto callback = [&]() {
1059 static float translation[2] = {0, 0};
1060 static bool enable_save_layer = true;
1061
1062 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1063 ImGui::SliderFloat2("Translation", translation, -130, 130);
1064 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1065 ImGui::End();
1066
1067 flutter::DisplayListBuilder builder;
1068 builder.Save();
1069 builder.Scale(2.0, 2.0);
1070 flutter::DlPaint paint;
1071 paint.setColor(flutter::DlColor::kYellow());
1072 builder.DrawRect(DlRect::MakeWH(300, 300), paint);
1073 paint.setStrokeWidth(1.0);
1074 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1075 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1076 builder.DrawLine(DlPoint(150, 0), DlPoint(150, 300), paint);
1077 builder.DrawLine(DlPoint(0, 150), DlPoint(300, 150), paint);
1078
1079 flutter::DlPaint save_paint;
1080 DlRect bounds = DlRect::MakeXYWH(100, 100, 100, 100);
1081 Matrix translate_matrix =
1082 Matrix::MakeTranslation({translation[0], translation[1]});
1083 if (enable_save_layer) {
1084 auto filter = flutter::DlMatrixImageFilter(
1085 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1086 save_paint.setImageFilter(filter.shared());
1087 builder.SaveLayer(bounds, &save_paint);
1088 } else {
1089 builder.Save();
1090 builder.Transform(translate_matrix);
1091 }
1092
1093 Matrix filter_matrix;
1094 filter_matrix.Translate({150, 150});
1095 filter_matrix.Scale({0.2f, 0.2f});
1096 filter_matrix.Translate({-150, -150});
1097 auto filter = flutter::DlMatrixImageFilter(
1098 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1099
1100 save_paint.setImageFilter(filter.shared());
1101
1102 builder.SaveLayer(bounds, &save_paint);
1103 flutter::DlPaint paint2;
1104 paint2.setColor(flutter::DlColor::kBlue());
1105 builder.DrawRect(bounds, paint2);
1106 builder.Restore();
1107 builder.Restore();
1108 return builder.Build();
1109 };
1110
1111 ASSERT_TRUE(OpenPlaygroundHere(callback));
1112 }

References impeller::Matrix::MakeTranslation(), impeller::Matrix::Scale(), and impeller::Matrix::Translate().

## ◆ TEST_P() [376/549]

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() [377/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 847 of file dl_unittests.cc.

847 {
848 flutter::DisplayListBuilder builder;
849 std::vector<flutter::DlStrokeCap> caps = {
850 flutter::DlStrokeCap::kButt,
851 flutter::DlStrokeCap::kRound,
852 flutter::DlStrokeCap::kSquare,
853 };
854 flutter::DlPaint paint =
855 flutter::DlPaint() //
856 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
857 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
858 .setStrokeCap(flutter::DlStrokeCap::kButt) //
859 .setStrokeWidth(20);
860 DlPath path = DlPath::MakeLine({150, 50}, {150, 50});
861 for (auto cap : caps) {
862 paint.setStrokeCap(cap);
863 builder.DrawLine(DlPoint(50, 50), DlPoint(50, 50), paint);
864 builder.DrawPath(path, paint);
865 builder.Translate(0, 150);
866 }
867 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }

## ◆ TEST_P() [378/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 918 of file dl_unittests.cc.

918 {
919 flutter::DisplayListBuilder builder;
920 std::vector<flutter::DlStrokeCap> caps = {
921 flutter::DlStrokeCap::kButt,
922 flutter::DlStrokeCap::kRound,
923 flutter::DlStrokeCap::kSquare,
924 };
925 flutter::DlPaint paint = //
926 flutter::DlPaint() //
927 .setColor(flutter::DlColor::kWhite()) //
928 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
929 .setStrokeWidth(0);
930 flutter::DlPaint outline_paint = //
931 flutter::DlPaint() //
932 .setColor(flutter::DlColor::kYellow()) //
933 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
934 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
935 .setStrokeWidth(1);
936 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
937 for (auto cap : caps) {
938 paint.setStrokeCap(cap);
939 builder.DrawLine(DlPoint(50, 50), DlPoint(60, 50), paint);
940 builder.DrawRect(DlRect::MakeLTRB(45, 45, 65, 55), outline_paint);
941 builder.DrawLine(DlPoint{100, 50}, DlPoint{100, 50}, paint);
942 if (cap != flutter::DlStrokeCap::kButt) {
943 builder.DrawRect(DlRect::MakeLTRB(95, 45, 105, 55), outline_paint);
944 }
945 builder.DrawPath(path, paint);
946 builder.DrawRect(path.GetBounds().Expand(5, 5), outline_paint);
947 builder.Translate(0, 150);
948 }
949 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
950 }

## ◆ TEST_P() [379/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1347 of file dl_unittests.cc.

1347 {
1348 flutter::DisplayListBuilder builder;
1349
1350 flutter::DlPaint fill_paint = //
1351 flutter::DlPaint() //
1352 .setColor(flutter::DlColor::kBlue()) //
1353 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1354 .setStrokeWidth(10);
1355 flutter::DlPaint stroke_paint = //
1356 flutter::DlPaint() //
1357 .setColor(flutter::DlColor::kGreen()) //
1358 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1359 .setStrokeWidth(10);
1360
1361 builder.DrawRoundRect(
1362 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1363 fill_paint);
1364 builder.DrawRoundRect(
1365 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1366 stroke_paint);
1367
1368 builder.DrawRoundRect(
1369 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1370 fill_paint);
1371 builder.DrawRoundRect(
1372 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1373 stroke_paint);
1374
1375 flutter::DlPaint reference_paint = //
1376 flutter::DlPaint() //
1377 .setColor(flutter::DlColor::kMidGrey()) //
1378 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1379 .setStrokeWidth(10);
1380
1381 builder.DrawRoundRect(
1382 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1383 reference_paint);
1384 builder.DrawRoundRect(
1385 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1386 reference_paint);
1387
1388 flutter::DlPaint clip_fill_paint = //
1389 flutter::DlPaint() //
1390 .setColor(flutter::DlColor::kCyan()) //
1391 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1392 .setStrokeWidth(10);
1393
1394 builder.Save();
1395 builder.ClipRoundRect(
1396 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1397 builder.DrawPaint(clip_fill_paint);
1398 builder.Restore();
1399
1400 builder.Save();
1401 builder.ClipRoundRect(
1402 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1403 builder.DrawPaint(clip_fill_paint);
1404 builder.Restore();
1405
1406 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1407 }

## ◆ TEST_P() [380/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1523 of file dl_unittests.cc.

1523 {
1524 flutter::DisplayListBuilder builder;
1525 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1526 Vector2 scale = GetContentScale();
1527 builder.Scale(scale.x, scale.y);
1528
1529 builder.Save();
1530 // We need a small transform op to avoid a deferred save
1531 builder.Translate(1.0f, 1.0f);
1532 auto solid_filter =
1533 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1534 flutter::DlPaint solid_alpha_paint =
1535 flutter::DlPaint() //
1536 .setMaskFilter(solid_filter) //
1537 .setColor(flutter::DlColor::kBlue()) //
1538 .setAlpha(0x7f);
1539 for (int x = 1; x <= 4; x++) {
1540 for (int y = 1; y <= 4; y++) {
1541 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1542 solid_alpha_paint);
1543 }
1544 }
1545 builder.Restore();
1546
1547 builder.Save();
1548 builder.Translate(500.0f, 0.0f);
1549 auto normal_filter =
1550 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1551 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1552 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1553 flutter::DlPaint normal_if_paint =
1554 flutter::DlPaint() //
1555 .setMaskFilter(solid_filter) //
1556 .setImageFilter(rotate_if) //
1557 .setColor(flutter::DlColor::kGreen()) //
1558 .setAlpha(0x7f);
1559 for (int x = 1; x <= 4; x++) {
1560 for (int y = 1; y <= 4; y++) {
1561 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1562 normal_if_paint);
1563 }
1564 }
1565 builder.Restore();
1566
1567 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1568 }

References impeller::Matrix::MakeRotationZ(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [381/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1500 of file dl_unittests.cc.

1500 {
1501 flutter::DisplayListBuilder builder;
1502 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1503
1504 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1505 builder.DrawCircle(DlPoint(300, 300), 200,
1506 flutter::DlPaint().setMaskFilter(&filter));
1507
1508 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1509 flutter::DlColor::kGreen()};
1510 const float stops[2] = {0.0, 1.0};
1511 auto linear = flutter::DlColorSource::MakeLinear(
1512 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1513 flutter::DlTileMode::kRepeat);
1514 flutter::DlPaint blend_paint =
1515 flutter::DlPaint() //
1516 .setColorSource(linear) //
1517 .setBlendMode(flutter::DlBlendMode::kScreen);
1518 builder.DrawPaint(blend_paint);
1519
1520 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1521 }

## ◆ TEST_P() [382/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1308 of file dl_unittests.cc.

1308 {
1309 flutter::DisplayListBuilder builder;
1310 std::vector<flutter::DlStrokeJoin> joins = {
1311 flutter::DlStrokeJoin::kBevel,
1312 flutter::DlStrokeJoin::kRound,
1313 flutter::DlStrokeJoin::kMiter,
1314 };
1315 flutter::DlPaint paint = //
1316 flutter::DlPaint() //
1317 .setColor(flutter::DlColor::kWhite()) //
1318 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1319 .setStrokeWidth(10);
1320 flutter::DlPaint stroke_paint = //
1321 flutter::DlPaint() //
1322 .setColor(flutter::DlColor::kWhite()) //
1323 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1324 .setStrokeWidth(10);
1325 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1326
1327 builder.Translate(300, 50);
1328 builder.Scale(0.8, 0.8);
1329 for (auto join : joins) {
1330 paint.setStrokeJoin(join);
1331 stroke_paint.setStrokeJoin(join);
1332 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1333 builder.DrawRect(DlRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1334 builder.DrawRoundRect(
1335 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 0, 100, 100), 30, 30),
1336 paint);
1337 builder.DrawRoundRect(
1338 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1339 stroke_paint);
1340 builder.DrawCircle(DlPoint(350, 50), 50, paint);
1341 builder.DrawCircle(DlPoint(350, 200), 50, stroke_paint);
1342 builder.Translate(0, 300);
1343 }
1344 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1345 }

## ◆ TEST_P() [383/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1409 of file dl_unittests.cc.

1409 {
1410 std::vector<const char*> blend_mode_names;
1411 std::vector<flutter::DlBlendMode> blend_mode_values;
1412 {
1413 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1414 // Pipeline blends (Porter-Duff alpha compositing)
1415 {"Clear", flutter::DlBlendMode::kClear},
1416 {"Source", flutter::DlBlendMode::kSrc},
1417 {"Destination", flutter::DlBlendMode::kDst},
1418 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1419 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1420 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1421 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1422 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1423 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1424 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1425 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1426 {"Xor", flutter::DlBlendMode::kXor},
1427 {"Plus", flutter::DlBlendMode::kPlus},
1428 {"Modulate", flutter::DlBlendMode::kModulate},
1429 // Advanced blends (color component blends)
1430 {"Screen", flutter::DlBlendMode::kScreen},
1431 {"Overlay", flutter::DlBlendMode::kOverlay},
1432 {"Darken", flutter::DlBlendMode::kDarken},
1433 {"Lighten", flutter::DlBlendMode::kLighten},
1434 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1435 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1436 {"HardLight", flutter::DlBlendMode::kHardLight},
1437 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1438 {"Difference", flutter::DlBlendMode::kDifference},
1439 {"Exclusion", flutter::DlBlendMode::kExclusion},
1440 {"Multiply", flutter::DlBlendMode::kMultiply},
1441 {"Hue", flutter::DlBlendMode::kHue},
1442 {"Saturation", flutter::DlBlendMode::kSaturation},
1443 {"Color", flutter::DlBlendMode::kColor},
1444 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1445 };
1446 assert(blends.size() ==
1447 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1448 for (const auto& [name, mode] : blends) {
1449 blend_mode_names.push_back(name);
1450 blend_mode_values.push_back(mode);
1451 }
1452 }
1453
1454 auto callback = [&]() {
1455 static int current_blend_index = 3;
1456 static float dst_alpha = 1;
1457 static float src_alpha = 1;
1458 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1459 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1460 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1461 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1462
1463 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1464 {
1465 ImGui::ListBox("Blending mode", &current_blend_index,
1466 blend_mode_names.data(), blend_mode_names.size());
1467 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1468 ImGui::ColorEdit4("Color A", color0);
1469 ImGui::ColorEdit4("Color B", color1);
1470 ImGui::ColorEdit4("Color C", color2);
1471 ImGui::ColorEdit4("Source Color", src_color);
1472 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1473 }
1474 ImGui::End();
1475
1476 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1477 DlPoint(200, 100), //
1478 DlPoint(300, 300)};
1479 std::vector<flutter::DlColor> colors = {
1480 toColor(color0).modulateOpacity(dst_alpha),
1481 toColor(color1).modulateOpacity(dst_alpha),
1482 toColor(color2).modulateOpacity(dst_alpha)};
1483
1484 auto vertices = flutter::DlVertices::Make(
1485 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1486 /*texture_coordinates=*/nullptr, colors.data());
1487
1488 flutter::DisplayListBuilder builder;
1489 flutter::DlPaint paint;
1490
1491 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1492 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1493 paint);
1494 return builder.Build();
1495 };
1496
1497 ASSERT_TRUE(OpenPlaygroundHere(callback));
1498 }
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:39

References toColor().

## ◆ TEST_P() [384/549]

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() [385/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1260 of file dl_unittests.cc.

1260 {
1261 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1262 flutter::DlBlurStyle::kNormal, 10);
1263
1264 flutter::DisplayListBuilder builder;
1265
1266 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1267 flutter::DlColor::kGreen()};
1268 std::array<float, 2> stops = {0, 1};
1269 auto texture = CreateTextureForFixture("airplane.jpg");
1270 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1271 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1272 flutter::DlColorSource::MakeImage(
1273 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1274 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1275 &matrix),
1276 flutter::DlColorSource::MakeLinear(
1277 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1278 stops.data(), flutter::DlTileMode::kClamp),
1279 };
1280
1281 builder.Save();
1282 builder.Translate(0, 100);
1283 for (const auto& color_source : color_sources) {
1284 flutter::DlPaint paint;
1285 paint.setColorSource(color_source);
1286 paint.setMaskFilter(blur_filter);
1287
1288 builder.Save();
1289 builder.Translate(100, 0);
1290 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1291 builder.DrawRoundRect(
1292 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1293
1294 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1295 paint.setStrokeWidth(10);
1296 builder.Translate(200, 0);
1297 builder.DrawRoundRect(
1298 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1299
1300 builder.Restore();
1301 builder.Translate(0, 100);
1302 }
1303 builder.Restore();
1304
1305 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1306 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [386/549]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 800 of file dl_unittests.cc.

800 {
801 // Draw a nine patch image with colored corners and verify that the corner
802 // color does not leak outside the intended region.
803 auto texture = CreateTextureForFixture("nine_patch_corners.png");
804 flutter::DisplayListBuilder builder;
805 builder.DrawImageNine(DlImageImpeller::Make(texture),
806 DlIRect::MakeXYWH(10, 10, 1, 1),
807 DlRect::MakeXYWH(0, 0, 200, 100),
808 flutter::DlFilterMode::kNearest, nullptr);
809 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
810 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [387/549]

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() [388/549]

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() [389/549]

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() [390/549]

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() [391/549]

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() [392/549]

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() [393/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 879 of file entity_unittests.cc.

879 {
880 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
881 static float scale = 20;
882
883 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
884 ImGui::SliderFloat("Scale", &scale, 1, 100);
885 ImGui::End();
886
887 Entity entity;
888 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
889 auto path = flutter::DlPathBuilder{}
890 .MoveTo({97.325, 34.818})
891 .CubicCurveTo({98.50862885295136, 34.81812293973836},
892 {99.46822048142015, 33.85863261475589},
893 {99.46822048142015, 32.67499810206613})
894 .CubicCurveTo({99.46822048142015, 31.491363589376355},
895 {98.50862885295136, 30.53187326439389},
896 {97.32499434685802, 30.531998226542708})
897 .CubicCurveTo({96.14153655073771, 30.532123170035373},
898 {95.18222070648729, 31.491540299350355},
899 {95.18222070648729, 32.67499810206613})
900 .CubicCurveTo({95.18222070648729, 33.85845590478189},
901 {96.14153655073771, 34.81787303409686},
902 {97.32499434685802, 34.81799797758954})
903 .Close()
904 .TakePath();
905 entity.SetTransform(
906 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
907
908 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
909
910 auto contents = std::make_shared<SolidColorContents>();
911 contents->SetColor(Color::Red());
912 contents->SetGeometry(geom.get());
913
914 entity.SetContents(contents);
915 return entity.Render(context, pass);
916 };
917 ASSERT_TRUE(OpenPlaygroundHere(callback));
918 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [394/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 747 of file entity_unittests.cc.

747 {
748 std::vector<const char*> blend_mode_names;
749 std::vector<BlendMode> blend_mode_values;
750 {
751 // Force an exhausiveness check with a switch. When adding blend modes,
752 // update this switch with a new name/value to make it selectable in the
753 // test GUI.
754
755 const BlendMode b{};
756 static_assert(b == BlendMode::kClear); // Ensure the first item in
757 // the switch is the first
758 // item in the enum.
759 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
760 switch (b) {
761 case BlendMode::kClear:
762 blend_mode_names.push_back("Clear");
763 blend_mode_values.push_back(BlendMode::kClear);
764 case BlendMode::kSrc:
765 blend_mode_names.push_back("Source");
766 blend_mode_values.push_back(BlendMode::kSrc);
767 case BlendMode::kDst:
768 blend_mode_names.push_back("Destination");
769 blend_mode_values.push_back(BlendMode::kDst);
770 case BlendMode::kSrcOver:
771 blend_mode_names.push_back("SourceOver");
772 blend_mode_values.push_back(BlendMode::kSrcOver);
773 case BlendMode::kDstOver:
774 blend_mode_names.push_back("DestinationOver");
775 blend_mode_values.push_back(BlendMode::kDstOver);
776 case BlendMode::kSrcIn:
777 blend_mode_names.push_back("SourceIn");
778 blend_mode_values.push_back(BlendMode::kSrcIn);
779 case BlendMode::kDstIn:
780 blend_mode_names.push_back("DestinationIn");
781 blend_mode_values.push_back(BlendMode::kDstIn);
782 case BlendMode::kSrcOut:
783 blend_mode_names.push_back("SourceOut");
784 blend_mode_values.push_back(BlendMode::kSrcOut);
785 case BlendMode::kDstOut:
786 blend_mode_names.push_back("DestinationOut");
787 blend_mode_values.push_back(BlendMode::kDstOut);
788 case BlendMode::kSrcATop:
789 blend_mode_names.push_back("SourceATop");
790 blend_mode_values.push_back(BlendMode::kSrcATop);
791 case BlendMode::kDstATop:
792 blend_mode_names.push_back("DestinationATop");
793 blend_mode_values.push_back(BlendMode::kDstATop);
794 case BlendMode::kXor:
795 blend_mode_names.push_back("Xor");
796 blend_mode_values.push_back(BlendMode::kXor);
797 case BlendMode::kPlus:
798 blend_mode_names.push_back("Plus");
799 blend_mode_values.push_back(BlendMode::kPlus);
800 case BlendMode::kModulate:
801 blend_mode_names.push_back("Modulate");
802 blend_mode_values.push_back(BlendMode::kModulate);
803 };
804 }
805
806 auto callback = [&](ContentContext& context, RenderPass& pass) {
807 auto world_matrix = Matrix::MakeScale(GetContentScale());
808 auto draw_rect = [&context, &pass, &world_matrix](
809 Rect rect, Color color, BlendMode blend_mode) -> bool {
810 using VS = SolidFillPipeline::VertexShader;
811 using FS = SolidFillPipeline::FragmentShader;
812
813 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
814 {
815 auto r = rect.GetLTRB();
816 vtx_builder.AddVertices({
817 {Point(r[0], r[1])},
818 {Point(r[2], r[1])},
819 {Point(r[2], r[3])},
820 {Point(r[0], r[1])},
821 {Point(r[2], r[3])},
822 {Point(r[0], r[3])},
823 });
824 }
825
826 pass.SetCommandLabel("Blended Rectangle");
827 auto options = OptionsFromPass(pass);
828 options.blend_mode = blend_mode;
829 options.primitive_type = PrimitiveType::kTriangle;
830 pass.SetPipeline(context.GetSolidFillPipeline(options));
831 pass.SetVertexBuffer(
832 vtx_builder.CreateVertexBuffer(context.GetTransientsDataBuffer(),
833 context.GetTransientsIndexesBuffer()));
834
835 VS::FrameInfo frame_info;
836 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
837 VS::BindFrameInfo(
838 pass, context.GetTransientsDataBuffer().EmplaceUniform(frame_info));
839 FS::FragInfo frag_info;
840 frag_info.color = color.Premultiply();
841 FS::BindFragInfo(
842 pass, context.GetTransientsDataBuffer().EmplaceUniform(frag_info));
843 return pass.Draw().ok();
844 };
845
846 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
847 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
848 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
849 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
850 static int current_blend_index = 3;
851 ImGui::ListBox("Blending mode", &current_blend_index,
852 blend_mode_names.data(), blend_mode_names.size());
853 ImGui::End();
854
855 BlendMode selected_mode = blend_mode_values[current_blend_index];
856
857 Point a, b, c, d;
858 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
859 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
860 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
861 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
862 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
863 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
864
865 bool result = true;
866 result = result &&
867 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
868 pass.GetRenderTargetSize().height),
869 Color(), BlendMode::kClear);
870 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
871 BlendMode::kSrcOver);
872 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
873 selected_mode);
874 return result;
875 };
876 ASSERT_TRUE(OpenPlaygroundHere(callback));
877 }
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, 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() [395/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1320 of file entity_unittests.cc.

1320 {
1321 auto fill = std::make_shared<SolidColorContents>();
1322 auto geom = Geometry::MakeFillPath(
1323 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1324 fill->SetGeometry(geom.get());
1325 fill->SetColor(Color::CornflowerBlue());
1326 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1327 FilterInput::Make(fill), Radius{3}, Radius{4});
1328
1329 {
1330 Entity e;
1331 e.SetTransform(Matrix());
1332 auto actual = border_mask_blur->GetCoverage(e);
1333 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1334 ASSERT_TRUE(actual.has_value());
1335 ASSERT_RECT_NEAR(actual.value(), expected);
1336 }
1337
1338 {
1339 Entity e;
1340 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1341 auto actual = border_mask_blur->GetCoverage(e);
1342 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1343 ASSERT_TRUE(actual.has_value());
1344 ASSERT_RECT_NEAR(actual.value(), expected);
1345 }
1346 }
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() [396/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2317 of file entity_unittests.cc.

2317 {
2318 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2319
2320 EXPECT_TRUE(path.GetBounds().IsEmpty());
2321
2322 auto geom = Geometry::MakeFillPath(path);
2323
2324 Entity entity;
2325 RenderTarget target =
2326 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2327 *GetContext(), {1, 1}, 1u);
2328 testing::MockRenderPass render_pass(GetContext(), target);
2329 auto position_result =
2330 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2331
2332 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2333
2334 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2335 }

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

## ◆ TEST_P() [397/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 72 of file entity_unittests.cc.

72 {
73 Entity entity;
74 ASSERT_TRUE(entity.GetTransform().IsIdentity());
75 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [398/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 399 of file entity_unittests.cc.

399 {
400 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
401 const char* input_axis[] = {"X", "Y", "Z"};
402 static int rotation_axis_index = 0;
403 static float rotation = 0;
404 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
405 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
406 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
407 sizeof(input_axis) / sizeof(char*));
408 Matrix rotation_matrix;
409 switch (rotation_axis_index) {
410 case 0:
411 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
412 break;
413 case 1:
414 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
415 break;
416 case 2:
417 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
418 break;
419 default:
420 rotation_matrix = Matrix{};
421 break;
422 }
423
424 if (ImGui::Button("Reset")) {
425 rotation = 0;
426 }
427 ImGui::End();
428 Matrix current_transform =
429 Matrix::MakeScale(GetContentScale())
430 .MakeTranslation(
431 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
432 pass.GetRenderTargetSize().height / 2.0)));
433 Matrix result_transform = current_transform * rotation_matrix;
434 flutter::DlPath path =
435 flutter::DlPath::MakeRect(Rect::MakeXYWH(-300, -400, 600, 800));
436
437 Entity entity;
438 entity.SetTransform(result_transform);
439
440 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
441
442 auto contents = std::make_shared<SolidColorContents>();
443 contents->SetColor(Color::Red());
444 contents->SetGeometry(geom.get());
445
446 entity.SetContents(contents);
447 return entity.Render(context, pass);
448 };
449 ASSERT_TRUE(OpenPlaygroundHere(callback));
450 }

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() [399/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2337 of file entity_unittests.cc.

2337 {
2338 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2339
2340 EXPECT_TRUE(path.GetBounds().IsEmpty());
2341
2342 auto contents = std::make_shared<SolidColorContents>();
2343 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2344 contents->SetGeometry(geom.get());
2345 contents->SetColor(Color::Red());
2346
2347 Entity entity;
2348 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2349 entity.SetContents(contents);
2350
2351 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2352 }

References impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [400/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2161 of file entity_unittests.cc.

2161 {
2162 Entity entity;
2163 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2164 auto src_contents = std::make_shared<SolidColorContents>();
2165 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2166 src_contents->SetGeometry(src_geom.get());
2167 src_contents->SetColor(Color::Red());
2168
2169 auto dst_contents = std::make_shared<SolidColorContents>();
2170 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2171 dst_contents->SetGeometry(dst_geom.get());
2172 dst_contents->SetColor(Color::Blue());
2173
2174 auto contents = ColorFilterContents::MakeBlend(
2175 BlendMode::kSrcOver, {FilterInput::Make(dst_contents, false),
2176 FilterInput::Make(src_contents, false)});
2177 entity.SetContents(std::move(contents));
2178 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2179 }

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() [401/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1924 of file entity_unittests.cc.

1924 {
1925 auto image = CreateTextureForFixture("boston.jpg");
1926 auto filter = ColorFilterContents::MakeBlend(
1927 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1928
1929 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1930 Entity entity;
1931 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1932 Matrix::MakeTranslation({500, 300}) *
1933 Matrix::MakeScale(Vector2{0.5, 0.5}));
1934 entity.SetContents(filter);
1935 return entity.Render(context, pass);
1936 };
1937 ASSERT_TRUE(OpenPlaygroundHere(callback));
1938 }

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() [402/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1940 of file entity_unittests.cc.

1940 {
1941 auto image = CreateTextureForFixture("boston.jpg");
1942 auto filter = ColorFilterContents::MakeBlend(
1943 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1944
1945 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1946 Entity entity;
1947 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1948 Matrix::MakeTranslation({500, 300}) *
1949 Matrix::MakeScale(Vector2{0.5, 0.5}));
1950 entity.SetContents(filter);
1951 return entity.Render(context, pass);
1952 };
1953 ASSERT_TRUE(OpenPlaygroundHere(callback));
1954 }

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() [403/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1972 of file entity_unittests.cc.

1972 {
1973 auto image = CreateTextureForFixture("boston.jpg");
1974 auto filter = ColorFilterContents::MakeBlend(
1975 BlendMode::kDst, FilterInput::Make({image}), Color::Red());
1976
1977 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1978 Entity entity;
1979 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1980 Matrix::MakeTranslation({500, 300}) *
1981 Matrix::MakeScale(Vector2{0.5, 0.5}));
1982 entity.SetContents(filter);
1983 return entity.Render(context, pass);
1984 };
1985 ASSERT_TRUE(OpenPlaygroundHere(callback));
1986 }

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() [404/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1956 of file entity_unittests.cc.

1956 {
1957 auto image = CreateTextureForFixture("boston.jpg");
1958 auto filter = ColorFilterContents::MakeBlend(
1959 BlendMode::kSrc, FilterInput::Make({image}), Color::Red());
1960
1961 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1962 Entity entity;
1963 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1964 Matrix::MakeTranslation({500, 300}) *
1965 Matrix::MakeScale(Vector2{0.5, 0.5}));
1966 entity.SetContents(filter);
1967 return entity.Render(context, pass);
1968 };
1969 ASSERT_TRUE(OpenPlaygroundHere(callback));
1970 }

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() [405/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 1988 of file entity_unittests.cc.

1988 {
1989 auto image = CreateTextureForFixture("boston.jpg");
1990 auto filter = ColorFilterContents::MakeBlend(
1991 BlendMode::kSrcIn, FilterInput::Make({image}), Color::Red());
1992
1993 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1994 Entity entity;
1995 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1996 Matrix::MakeTranslation({500, 300}) *
1997 Matrix::MakeScale(Vector2{0.5, 0.5}));
1998 entity.SetContents(filter);
1999 return entity.Render(context, pass);
2000 };
2001 ASSERT_TRUE(OpenPlaygroundHere(callback));
2002 }

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() [406/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1447 of file entity_unittests.cc.

1447 {
1448 // Set up a simple color background.
1449 auto fill = std::make_shared<SolidColorContents>();
1450 auto geom = Geometry::MakeFillPath(
1451 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1452 fill->SetGeometry(geom.get());
1453 fill->SetColor(Color::Coral());
1454
1455 // Set the color matrix filter.
1456 ColorMatrix matrix = {
1457 1, 1, 1, 1, 1, //
1458 1, 1, 1, 1, 1, //
1459 1, 1, 1, 1, 1, //
1460 1, 1, 1, 1, 1, //
1461 };
1462
1463 auto filter =
1464 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1465
1466 Entity e;
1467 e.SetTransform(Matrix());
1468
1469 // Confirm that the actual filter coverage matches the expected coverage.
1470 auto actual = filter->GetCoverage(e);
1471 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1472
1473 ASSERT_TRUE(actual.has_value());
1474 ASSERT_RECT_NEAR(actual.value(), expected);
1475 }

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() [407/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1477 of file entity_unittests.cc.

1477 {
1478 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1479 ASSERT_TRUE(bay_bridge);
1480
1481 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1482 // UI state.
1483 static ColorMatrix color_matrix = {
1484 1, 0, 0, 0, 0, //
1485 0, 3, 0, 0, 0, //
1486 0, 0, 1, 0, 0, //
1487 0, 0, 0, 1, 0, //
1488 };
1489 static float offset[2] = {500, 400};
1490 static float rotation = 0;
1491 static float scale[2] = {0.65, 0.65};
1492 static float skew[2] = {0, 0};
1493
1494 // Define the ImGui
1495 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1496 {
1497 std::string label = "##1";
1498 for (int i = 0; i < 20; i += 5) {
1499 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1500 &(color_matrix.array[i]), 5, nullptr, nullptr,
1501 "%.2f", 0);
1502 label[2]++;
1503 }
1504
1505 ImGui::SliderFloat2("Translation", &offset[0], 0,
1506 pass.GetRenderTargetSize().width);
1507 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1508 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1509 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1510 }
1511 ImGui::End();
1512
1513 // Set the color matrix filter.
1514 auto filter = ColorFilterContents::MakeColorMatrix(
1515 FilterInput::Make(bay_bridge), color_matrix);
1516
1517 // Define the entity with the color matrix filter.
1518 Entity entity;
1519 entity.SetTransform(
1520 Matrix::MakeScale(GetContentScale()) *
1521 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1522 Matrix::MakeRotationZ(Radians(rotation)) *
1523 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1524 Matrix::MakeSkew(skew[0], skew[1]) *
1525 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1526 entity.SetContents(filter);
1527 entity.Render(context, pass);
1528
1529 return true;
1530 };
1531
1532 ASSERT_TRUE(OpenPlaygroundHere(callback));
1533 }

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() [408/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2049 of file entity_unittests.cc.

2049 {
2050 Matrix matrix;
2051 ConicalGradientContents contents;
2052 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2053 contents.SetGeometry(geom.get());
2054
2055 contents.SetColors({Color::CornflowerBlue()});
2056 EXPECT_FALSE(contents.IsOpaque(matrix));
2057 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2058 EXPECT_FALSE(contents.IsOpaque(matrix));
2059
2060 // Create stroked path that required alpha coverage.
2061 geom = Geometry::MakeStrokePath(
2062 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2063 {.width = 0.05f});
2064 contents.SetGeometry(geom.get());
2065 contents.SetColors({Color::CornflowerBlue()});
2066
2067 EXPECT_FALSE(contents.IsOpaque(matrix));
2068 }

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() [409/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2228 of file entity_unittests.cc.

2228 {
2229 ContentContextOptions opts;
2230 auto hash_a = opts.ToKey();
2231
2232 opts.blend_mode = BlendMode::kColorBurn;
2233 auto hash_b = opts.ToKey();
2234
2235 opts.has_depth_stencil_attachments = false;
2236 auto hash_c = opts.ToKey();
2237
2238 opts.primitive_type = PrimitiveType::kPoint;
2239 auto hash_d = opts.ToKey();
2240
2241 EXPECT_NE(hash_a, hash_b);
2242 EXPECT_NE(hash_b, hash_c);
2243 EXPECT_NE(hash_c, hash_d);
2244 }

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() [410/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1243 of file entity_unittests.cc.

1243 {
1244 Entity entity;
1245 entity.SetContents(std::make_shared<SolidColorContents>());
1246 ASSERT_FALSE(entity.GetCoverage().has_value());
1247 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [411/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2004 of file entity_unittests.cc.

2004 {
2005 auto arrow_head = flutter::DlPathBuilder{}
2006 .MoveTo({50, 120})
2007 .LineTo({120, 190})
2008 .LineTo({190, 120})
2009 .TakePath();
2010 auto geometry = Geometry::MakeStrokePath(arrow_head, //
2011 {
2012 .width = 15.0f,
2013 .cap = Cap::kRound,
2014 .join = Join::kRound,
2015 .miter_limit = 4.0f,
2016 });
2017
2018 auto transform = Matrix::MakeTranslation({300, 300}) *
2019 Matrix::MakeRotationZ(Radians(kPiOver2));
2020 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2021 // due to floating point inaccuracy in the transcendental trig functions.
2022 // e[1][0] is the intended negative value that we care about (-1.0) as it
2023 // comes from the rotation of pi/2.
2024 EXPECT_LT(transform.e[1][0], 0.0f);
2025 auto coverage = geometry->GetCoverage(transform);
2026 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2027 }

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() [412/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 452 of file entity_unittests.cc.

452 {
453 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
454 flutter::DlPath path =
455 flutter::DlPathBuilder{}
456 .MoveTo({359.934, 96.6335})
457 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
458 {354.673, 96.8895})
459 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
460 {354.367, 96.9075})
461 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
462 {349.259, 97.2355})
463 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
464 {348.625, 97.2834})
465 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
466 {343.789, 97.6722})
467 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
468 {342.703, 97.7734})
469 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
470 {338.246, 98.207})
471 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
472 {336.612, 98.3894})
473 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
474 {332.623, 98.8476})
475 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
476 {332.237, 98.8982})
477 .LineTo({332.237, 102.601})
478 .LineTo({321.778, 102.601})
479 .LineTo({321.778, 100.382})
480 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
481 {321.161, 100.476})
482 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
483 {315.332, 101.479})
484 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
485 {315.301, 101.484})
486 .LineTo({310.017, 105.94})
487 .LineTo({309.779, 105.427})
488 .LineTo({314.403, 101.651})
489 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
490 {314.368, 101.658})
491 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
492 {308.846, 102.748})
493 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
494 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
495 {303.425, 103.936})
496 .LineTo({299.105, 107.578})
497 .LineTo({298.867, 107.065})
498 .LineTo({302.394, 104.185})
499 .LineTo({302.412, 104.171})
500 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
501 {299.344, 104.921})
502 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
503 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
504 {291.462, 106.979})
505 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
506 {290.471, 107.257})
507 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
508 {287.449, 108.139})
509 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
510 {284.536, 109.035})
511 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
512 {281.952, 109.859})
513 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
514 {279.633, 110.638})
515 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
516 {276.803, 111.607})
517 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
518 {276.672, 111.653})
519 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
520 {271.721, 113.463})
521 .LineTo({271.717, 113.449})
522 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
523 {270.963, 113.628})
524 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
525 {270.748, 113.682})
526 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
527 {269.839, 113.926})
528 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
529 {269.681, 113.972})
530 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
531 {268.756, 114.239})
532 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
533 {268.367, 114.354})
534 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
535 {267.752, 114.54})
536 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
537 {253.564, 119.252})
538 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
539 {253.538, 119.261})
540 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
541 {248.189, 121.131})
542 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
543 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
544 {245.975, 121.912})
545 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
546 {244.698, 122.364})
547 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
548 {242.794, 123.04})
549 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
550 {240.961, 123.693})
551 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
552 {240.052, 124.018})
553 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
554 .LineTo({237.164, 125.003})
555 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
556 {235.81, 125.538})
557 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
558 {234.592, 125.977})
559 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
560 {234.59, 125.977})
561 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
562 {192.381, 141.429})
563 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
564 .LineTo({360, 160})
565 .LineTo({360, 119.256})
566 .LineTo({360, 106.332})
567 .LineTo({360, 96.6307})
568 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
569 {359.934, 96.6335})
570 .Close()
571 .MoveTo({337.336, 124.143})
572 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
573 {338.903, 121.511})
574 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
575 {337.336, 124.143})
576 .Close()
577 .MoveTo({340.082, 121.849})
578 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
579 {340.046, 122.075})
580 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
581 {340.023, 122.177})
582 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
583 {339.952, 122.437})
584 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
585 {339.918, 122.544})
586 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
587 {339.75, 122.938})
588 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
589 {339.74, 122.955})
590 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
591 {339.501, 123.328})
592 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
593 {339.41, 123.438})
594 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
595 {339.145, 123.714})
596 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
597 {339.025, 123.821})
598 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
599 {338.539, 124.143})
600 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
601 {338.58, 123.626})
602 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
603 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
604 {338.704, 123.151})
605 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
606 {338.714, 123.117})
607 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
608 {338.905, 122.712})
609 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
610 {338.922, 122.682})
611 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
612 {339.155, 122.34})
613 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
614 {339.172, 122.319})
615 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
616 {339.425, 122.037})
617 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
618 {339.435, 122.027})
619 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
620 {340.106, 121.511})
621 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
622 {340.082, 121.849})
623 .Close()
624 .MoveTo({340.678, 113.245})
625 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
626 {340.135, 113.775})
627 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
628 {339.115, 114.151})
629 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
630 {336.448, 114.516})
631 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
632 {334.384, 114.513})
633 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
634 {333.605, 114.424})
635 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
636 {331.41, 113.883})
637 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
638 {330.672, 112.813})
639 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
640 {334.526, 113.833})
641 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
642 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
643 {332.76, 110.402})
644 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
645 {335.228, 113.395})
646 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
647 {335.661, 109.592})
648 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
649 {336.07, 113.389})
650 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
651 {338.563, 110.402})
652 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
653 {336.753, 113.784})
654 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
655 {336.796, 113.833})
656 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
657 {340.65, 112.813})
658 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
659 {340.678, 113.245})
660 .Close()
661 .MoveTo({346.357, 106.771})
662 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
663 {347.924, 104.139})
664 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
665 {346.357, 106.771})
666 .Close()
667 .MoveTo({347.56, 106.771})
668 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
669 {349.127, 104.139})
670 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
671 {347.56, 106.771})
672 .Close()
673 .TakePath();
674 Entity entity;
675 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
676
677 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
678
679 auto contents = std::make_shared<SolidColorContents>();
680 contents->SetColor(Color::Red());
681 contents->SetGeometry(geom.get());
682
683 entity.SetContents(contents);
684 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
685 }

References impeller::Close(), impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [413/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 370 of file entity_unittests.cc.

370 {
371 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
372 flutter::DlPath path =
373 flutter::DlPathBuilder{}
374 .MoveTo({237.164, 125.003})
375 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
376 {235.81, 125.538})
377 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
378 {234.592, 125.977})
379 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
380 {234.59, 125.977})
381 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
382 {192.381, 141.429})
383 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
384 .Close()
385 .TakePath();
386 Entity entity;
387 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
388
389 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
390
391 auto contents = std::make_shared<SolidColorContents>();
392 contents->SetColor(Color::Red());
393 contents->SetGeometry(geom.get());
394
395 entity.SetContents(contents);
396 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
397 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [414/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2212 of file entity_unittests.cc.

2212 {
2213 auto content_context = GetContentContext();
2214 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2215 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2216 });
2217
2218 auto decal_supported = static_cast<Scalar>(
2219 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2220 std::vector<Scalar> expected_constants = {decal_supported};
2221 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2222 expected_constants);
2223 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [415/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipse |
| ) |  |

Definition at line 2387 of file entity_unittests.cc.

2387 {
2388 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2389 // UI state.
2390 static int style_index = 0;
2391 static float center[2] = {830, 830};
2392 static float size[2] = {600, 600};
2393 static bool horizontal_symmetry = true;
2394 static bool vertical_symmetry = true;
2395 static bool corner_symmetry = true;
2396
2397 const char* style_options[] = {"Fill", "Stroke"};
2398
2399 // Initially radius_tl[0] will be mirrored to all 8 values since all 3
2400 // symmetries are enabled.
2401 static std::array<float, 2> radius_tl = {200};
2402 static std::array<float, 2> radius_tr;
2403 static std::array<float, 2> radius_bl;
2404 static std::array<float, 2> radius_br;
2405
2406 auto AddRadiusControl = [](std::array<float, 2>& radii, const char* tb_name,
2407 const char* lr_name) {
2408 std::string name = "Radius";
2409 if (!horizontal_symmetry || !vertical_symmetry) {
2410 name += ":";
2411 }
2412 if (!vertical_symmetry) {
2413 name = name + " " + tb_name;
2414 }
2415 if (!horizontal_symmetry) {
2416 name = name + " " + lr_name;
2417 }
2418 if (corner_symmetry) {
2419 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2420 } else {
2421 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2422 }
2423 };
2424
2425 if (corner_symmetry) {
2426 radius_tl[1] = radius_tl[0];
2427 radius_tr[1] = radius_tr[0];
2428 radius_bl[1] = radius_bl[0];
2429 radius_br[1] = radius_br[0];
2430 }
2431
2432 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2433 {
2434 ImGui::Combo("Style", &style_index, style_options,
2435 sizeof(style_options) / sizeof(char*));
2436 ImGui::SliderFloat2("Center", center, 0, 1000);
2437 ImGui::SliderFloat2("Size", size, 0, 1000);
2438 ImGui::Checkbox("Symmetry: Horizontal", &horizontal_symmetry);
2439 ImGui::Checkbox("Symmetry: Vertical", &vertical_symmetry);
2440 ImGui::Checkbox("Symmetry: Corners", &corner_symmetry);
2441 AddRadiusControl(radius_tl, "Top", "Left");
2442 if (!horizontal_symmetry) {
2443 AddRadiusControl(radius_tr, "Top", "Right");
2444 } else {
2445 radius_tr = radius_tl;
2446 }
2447 if (!vertical_symmetry) {
2448 AddRadiusControl(radius_bl, "Bottom", "Left");
2449 } else {
2450 radius_bl = radius_tl;
2451 }
2452 if (!horizontal_symmetry && !vertical_symmetry) {
2453 AddRadiusControl(radius_br, "Bottom", "Right");
2454 } else {
2455 if (horizontal_symmetry) {
2456 radius_br = radius_bl;
2457 } else {
2458 radius_br = radius_tr;
2459 }
2460 }
2461 }
2462
2463 ImGui::End();
2464
2465 RoundingRadii radii{
2466 .top_left = {radius_tl[0], radius_tl[1]},
2467 .top_right = {radius_tr[0], radius_tr[1]},
2468 .bottom_left = {radius_bl[0], radius_bl[1]},
2469 .bottom_right = {radius_br[0], radius_br[1]},
2470 };
2471
2472 auto rse = RoundSuperellipse::MakeRectRadii(
2473 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}), radii);
2474
2475 flutter::DlPath path;
2476 std::unique_ptr<Geometry> geom;
2477 if (style_index == 0) {
2478 geom = std::make_unique<RoundSuperellipseGeometry>(
2479 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}),
2480 radii);
2481 } else {
2482 path = flutter::DlPath::MakeRoundSuperellipse(rse);
2483 geom = Geometry::MakeStrokePath(path, {.width = 2.0f});
2484 }
2485
2486 auto contents = std::make_shared<SolidColorContents>();
2487 contents->SetColor(Color::Red());
2488 contents->SetGeometry(geom.get());
2489
2490 Entity entity;
2491 entity.SetContents(contents);
2492
2493 return entity.Render(context, pass);
2494 };
2495
2496 ASSERT_TRUE(OpenPlaygroundHere(callback));
2497 }
impeller::testing::RectMakeCenterSize
Rect RectMakeCenterSize(Point center, Size size)
Definition: entity_unittests.cc:68

References impeller::RoundSuperellipse::MakeRectRadii(), impeller::Geometry::MakeStrokePath(), RectMakeCenterSize(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [416/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2354 of file entity_unittests.cc.

2354 {
2355 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2356 // UI state.
2357 static float alpha = 10;
2358 static float beta = 10;
2359 static float radius = 40;
2360 static int degree = 4;
2361 static Color color = Color::Red();
2362
2363 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2364 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2365 ImGui::SliderFloat("Beta", &beta, 0, 100);
2366 ImGui::SliderInt("Degreee", &degree, 1, 20);
2367 ImGui::SliderFloat("Radius", &radius, 0, 400);
2368 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2369 ImGui::End();
2370
2371 auto contents = std::make_shared<SolidColorContents>();
2372 std::unique_ptr<SuperellipseGeometry> geom =
2373 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2374 alpha, beta);
2375 contents->SetColor(color);
2376 contents->SetGeometry(geom.get());
2377
2378 Entity entity;
2379 entity.SetContents(contents);
2380
2381 return entity.Render(context, pass);
2382 };
2383
2384 ASSERT_TRUE(OpenPlaygroundHere(callback));
2385 }

References impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [417/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2303 of file entity_unittests.cc.

2303 {
2304 if (GetParam() != PlaygroundBackend::kVulkan) {
2305 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2306 }
2307 EXPECT_DEATH(
2308 // The easiest way to trigger a validation error is to try to compile
2309 // a shader with an unsupported pixel format.
2310 GetContentContext()->GetBlendColorBurnPipeline({
2311 .color_attachment_pixel_format = PixelFormat::kUnknown,
2312 .has_depth_stencil_attachments = false,
2313 }),
2314 "");
2315 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [418/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2272 of file entity_unittests.cc.

2272 {
2273 RenderTarget target;
2274 testing::MockRenderPass mock_pass(GetContext(), target);
2275
2276 auto get_result = [this, &mock_pass](const flutter::DlPath& path) {
2277 auto geometry = Geometry::MakeFillPath(
2278 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2279 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2280 };
2281
2282 // Convex path
2283 {
2284 GeometryResult result =
2285 get_result(flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 100, 100)));
2286 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2287 }
2288
2289 // Concave path
2290 {
2291 flutter::DlPath path = flutter::DlPathBuilder{}
2292 .MoveTo({0, 0})
2293 .LineTo({100, 0})
2294 .LineTo({100, 100})
2295 .LineTo({51, 50})
2296 .Close()
2297 .TakePath();
2298 GeometryResult result = get_result(path);
2299 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2300 }
2301 }

References impeller::Close(), impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::GeometryResult::mode.

## ◆ TEST_P() [419/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 77 of file entity_unittests.cc.

77 {
78 auto image = CreateTextureForFixture("boston.jpg");
79 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
80 FilterInput::Make({image}));
81
82 // Without the crop rect (default behavior).
83 {
84 auto actual = filter->GetCoverage({});
85 auto expected = Rect::MakeSize(image->GetSize());
86
87 ASSERT_TRUE(actual.has_value());
88 ASSERT_RECT_NEAR(actual.value(), expected);
89 }
90
91 // With the crop rect.
92 {
93 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
94 filter->SetCoverageHint(expected);
95 auto actual = filter->GetCoverage({});
96
97 ASSERT_TRUE(actual.has_value());
98 ASSERT_RECT_NEAR(actual.value(), expected);
99 }
100 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [420/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 920 of file entity_unittests.cc.

920 {
921 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
922 auto boston = CreateTextureForFixture("boston.jpg");
923 auto kalimba = CreateTextureForFixture("kalimba.jpg");
924 ASSERT_TRUE(bridge && boston && kalimba);
925
926 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
927 auto fi_bridge = FilterInput::Make(bridge);
928 auto fi_boston = FilterInput::Make(boston);
929 auto fi_kalimba = FilterInput::Make(kalimba);
930
931 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
932 BlendMode::kModulate, {fi_kalimba, fi_boston});
933
934 auto blend1 = ColorFilterContents::MakeBlend(
935 BlendMode::kScreen,
936 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
937
938 Entity entity;
939 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
940 Matrix::MakeTranslation({500, 300}) *
941 Matrix::MakeScale(Vector2{0.5, 0.5}));
942 entity.SetContents(blend1);
943 return entity.Render(context, pass);
944 };
945 ASSERT_TRUE(OpenPlaygroundHere(callback));
946 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [421/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 948 of file entity_unittests.cc.

948 {
949 auto boston =
950 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
951 ASSERT_TRUE(boston);
952
953 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
954 const char* input_type_names[] = {"Texture", "Solid Color"};
955 const char* blur_type_names[] = {"Image blur", "Mask blur"};
956 const char* pass_variation_names[] = {"New"};
957 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
958 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
959 const FilterContents::BlurStyle blur_styles[] = {
960 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
961 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
962 const Entity::TileMode tile_modes[] = {
963 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
964 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
965
966 // UI state.
967 static int selected_input_type = 0;
968 static Color input_color = Color::Black();
969 static int selected_blur_type = 0;
970 static int selected_pass_variation = 0;
971 static bool combined_sigma = false;
972 static float blur_amount_coarse[2] = {0, 0};
973 static float blur_amount_fine[2] = {10, 10};
974 static int selected_blur_style = 0;
975 static int selected_tile_mode = 3;
976 static Color cover_color(1, 0, 0, 0.2);
977 static Color bounds_color(0, 1, 0, 0.1);
978 static float offset[2] = {500, 400};
979 static float rotation = 0;
980 static float scale[2] = {0.65, 0.65};
981 static float skew[2] = {0, 0};
982 static float path_rect[4] = {0, 0,
983 static_cast<float>(boston->GetSize().width),
984 static_cast<float>(boston->GetSize().height)};
985
986 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
987 {
988 ImGui::Combo("Input type", &selected_input_type, input_type_names,
989 sizeof(input_type_names) / sizeof(char*));
990 if (selected_input_type == 0) {
991 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
992 } else {
993 ImGui::ColorEdit4("Input color",
994 reinterpret_cast<float*>(&input_color));
995 }
996 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
997 sizeof(blur_type_names) / sizeof(char*));
998 if (selected_blur_type == 0) {
999 ImGui::Combo("Pass variation", &selected_pass_variation,
1000 pass_variation_names,
1001 sizeof(pass_variation_names) / sizeof(char*));
1002 }
1003 ImGui::Checkbox("Combined sigma", &combined_sigma);
1004 if (combined_sigma) {
1005 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1006 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1007 blur_amount_coarse[1] = blur_amount_coarse[0];
1008 blur_amount_fine[1] = blur_amount_fine[0];
1009 } else {
1010 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1011 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1012 }
1013 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1014 sizeof(blur_style_names) / sizeof(char*));
1015 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1016 sizeof(tile_mode_names) / sizeof(char*));
1017 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1018 ImGui::ColorEdit4("Bounds color ",
1019 reinterpret_cast<float*>(&bounds_color));
1020 ImGui::SliderFloat2("Translation", offset, 0,
1021 pass.GetRenderTargetSize().width);
1022 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1023 ImGui::SliderFloat2("Scale", scale, 0, 3);
1024 ImGui::SliderFloat2("Skew", skew, -3, 3);
1025 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1026 }
1027 ImGui::End();
1028
1029 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1030 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1031
1032 std::shared_ptr<Contents> input;
1033 Size input_size;
1034
1035 auto input_rect =
1036 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1037
1038 std::unique_ptr<Geometry> solid_color_input;
1039 if (selected_input_type == 0) {
1040 auto texture = std::make_shared<TextureContents>();
1041 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1042 texture->SetDestinationRect(input_rect);
1043 texture->SetTexture(boston);
1044 texture->SetOpacity(input_color.alpha);
1045
1046 input = texture;
1047 input_size = input_rect.GetSize();
1048 } else {
1049 auto fill = std::make_shared<SolidColorContents>();
1050 fill->SetColor(input_color);
1051 solid_color_input =
1052 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1053
1054 fill->SetGeometry(solid_color_input.get());
1055
1056 input = fill;
1057 input_size = input_rect.GetSize();
1058 }
1059
1060 std::shared_ptr<FilterContents> blur;
1061 switch (selected_pass_variation) {
1062 case 0:
1063 blur = std::make_shared<GaussianBlurFilterContents>(
1064 blur_sigma_x.sigma, blur_sigma_y.sigma,
1065 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1066 /*geometry=*/nullptr);
1067 blur->SetInputs({FilterInput::Make(input)});
1068 break;
1069 case 1:
1070 blur = FilterContents::MakeGaussianBlur(
1071 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1072 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1073 break;
1074 };
1075 FML_CHECK(blur);
1076
1077 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1078 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1079 blur_styles[selected_blur_style]);
1080
1081 auto ctm = Matrix::MakeScale(GetContentScale()) *
1082 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1083 Matrix::MakeRotationZ(Radians(rotation)) *
1084 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1085 Matrix::MakeSkew(skew[0], skew[1]) *
1086 Matrix::MakeTranslation(-Point(input_size) / 2);
1087
1088 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1089
1090 Entity entity;
1091 entity.SetContents(target_contents);
1092 entity.SetTransform(ctm);
1093
1094 entity.Render(context, pass);
1095
1096 // Renders a red "cover" rectangle that shows the original position of the
1097 // unfiltered input.
1098 Entity cover_entity;
1099 std::unique_ptr<Geometry> geom =
1100 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1101 auto contents = std::make_shared<SolidColorContents>();
1102 contents->SetColor(cover_color);
1103 contents->SetGeometry(geom.get());
1104 cover_entity.SetContents(std::move(contents));
1105 cover_entity.SetTransform(ctm);
1106 cover_entity.Render(context, pass);
1107
1108 // Renders a green bounding rect of the target filter.
1109 Entity bounds_entity;
1110 std::optional<Rect> target_contents_coverage =
1111 target_contents->GetCoverage(entity);
1112 if (target_contents_coverage.has_value()) {
1113 std::unique_ptr<Geometry> geom =
1114 Geometry::MakeFillPath(flutter::DlPath::MakeRect(
1115 target_contents->GetCoverage(entity).value()));
1116 auto contents = std::make_shared<SolidColorContents>();
1117 contents->SetColor(bounds_color);
1118 contents->SetGeometry(geom.get());
1119
1120 bounds_entity.SetContents(contents);
1121 bounds_entity.SetTransform(Matrix());
1122 bounds_entity.Render(context, pass);
1123 }
1124
1125 return true;
1126 };
1127 ASSERT_TRUE(OpenPlaygroundHere(callback));
1128 }

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() [422/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 102 of file entity_unittests.cc.

102 {
103 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
104 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
105
106 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
107 Rect::MakeXYWH(200, 200, 200, 200));
108 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [423/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantStrokePathAllocation |
| ) |  |

Definition at line 2529 of file entity_unittests.cc.

2529 {
2530 flutter::DlPathBuilder builder;
2531 for (int i = 0; i < 10000; i++) {
2532 builder.LineTo(Point(i, i));
2533 }
2534 flutter::DlPath path = builder.TakePath();
2535 auto geom = Geometry::MakeStrokePath(path, {.width = 10.0f});
2536
2537 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2538 Entity entity;
2539
2540 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2541
2542 RenderTargetAllocator allocator(
2543 content_context.GetContext()->GetResourceAllocator());
2544
2545 auto render_target = allocator.CreateOffscreen(
2546 *content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);
2547 auto pass = cmd_buffer->CreateRenderPass(render_target);
2548
2549 GeometryResult result =
2550 geom->GetPositionBuffer(content_context, entity, *pass);
2551
2552 // Validate the buffer data overflowed the small buffer
2553 EXPECT_GT(result.vertex_buffer.vertex_count, kPointArenaSize);
2554
2555 // Validate that there are no uninitialized points near the gap.
2556 Point* written_data = reinterpret_cast<Point*>(
2557 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2558 result.vertex_buffer.vertex_buffer.GetRange().offset));
2559
2560 std::vector<Point> expected = {
2561 Point(2043.46, 2050.54), //
2562 Point(2050.54, 2043.46), //
2563 Point(2044.46, 2051.54), //
2564 Point(2051.54, 2044.46), //
2565 Point(2045.46, 2052.54) //
2566 };
2567
2568 Point point = written_data[kPointArenaSize - 2];
2569 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2570 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2571
2572 point = written_data[kPointArenaSize - 1];
2573 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2574 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2575
2576 point = written_data[kPointArenaSize];
2577 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2578 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2579
2580 point = written_data[kPointArenaSize + 1];
2581 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2582 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2583
2584 point = written_data[kPointArenaSize + 2];
2585 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2586 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2587 }
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() [424/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2070 of file entity_unittests.cc.

2070 {
2071 Matrix matrix;
2072 LinearGradientContents contents;
2073 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2074 contents.SetGeometry(geom.get());
2075
2076 contents.SetColors({Color::CornflowerBlue()});
2077 EXPECT_TRUE(contents.IsOpaque(matrix));
2078 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2079 EXPECT_FALSE(contents.IsOpaque(matrix));
2080 contents.SetColors({Color::CornflowerBlue()});
2081 contents.SetTileMode(Entity::TileMode::kDecal);
2082 EXPECT_FALSE(contents.IsOpaque(matrix));
2083
2084 // Create stroked path that required alpha coverage.
2085 geom = Geometry::MakeStrokePath(
2086 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2087 {.width = 0.05f});
2088 contents.SetGeometry(geom.get());
2089 contents.SetColors({Color::CornflowerBlue()});
2090
2091 EXPECT_FALSE(contents.IsOpaque(matrix));
2092 }

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() [425/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1557 of file entity_unittests.cc.

1557 {
1558 auto image = CreateTextureForFixture("kalimba.jpg");
1559 ASSERT_TRUE(image);
1560
1561 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1562 auto filtered =
1563 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1564
1565 // Define the entity that will serve as the control image as a Gaussian blur
1566 // filter with no filter at all.
1567 Entity entity_left;
1568 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1569 Matrix::MakeTranslation({100, 300}) *
1570 Matrix::MakeScale(Vector2{0.5, 0.5}));
1571 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1572 Sigma{0}, Sigma{0});
1573 entity_left.SetContents(unfiltered);
1574
1575 // Define the entity that will be filtered from linear to sRGB.
1576 Entity entity_right;
1577 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1578 Matrix::MakeTranslation({500, 300}) *
1579 Matrix::MakeScale(Vector2{0.5, 0.5}));
1580 entity_right.SetContents(filtered);
1581 return entity_left.Render(context, pass) &&
1582 entity_right.Render(context, pass);
1583 };
1584
1585 ASSERT_TRUE(OpenPlaygroundHere(callback));
1586 }

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() [426/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1535 of file entity_unittests.cc.

1535 {
1536 // Set up a simple color background.
1537 auto geom = Geometry::MakeFillPath(
1538 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1539 auto fill = std::make_shared<SolidColorContents>();
1540 fill->SetGeometry(geom.get());
1541 fill->SetColor(Color::MintCream());
1542
1543 auto filter =
1544 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1545
1546 Entity e;
1547 e.SetTransform(Matrix());
1548
1549 // Confirm that the actual filter coverage matches the expected coverage.
1550 auto actual = filter->GetCoverage(e);
1551 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1552
1553 ASSERT_TRUE(actual.has_value());
1554 ASSERT_RECT_NEAR(actual.value(), expected);
1555 }

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() [427/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1130 of file entity_unittests.cc.

1130 {
1131 auto boston = CreateTextureForFixture("boston.jpg");
1132 ASSERT_TRUE(boston);
1133
1134 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1135 const char* morphology_type_names[] = {"Dilate", "Erode"};
1136 const FilterContents::MorphType morphology_types[] = {
1137 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1138 static Color input_color = Color::Black();
1139 // UI state.
1140 static int selected_morphology_type = 0;
1141 static float radius[2] = {20, 20};
1142 static Color cover_color(1, 0, 0, 0.2);
1143 static Color bounds_color(0, 1, 0, 0.1);
1144 static float offset[2] = {500, 400};
1145 static float rotation = 0;
1146 static float scale[2] = {0.65, 0.65};
1147 static float skew[2] = {0, 0};
1148 static float path_rect[4] = {0, 0,
1149 static_cast<float>(boston->GetSize().width),
1150 static_cast<float>(boston->GetSize().height)};
1151 static float effect_transform_scale = 1;
1152
1153 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1154 {
1155 ImGui::Combo("Morphology type", &selected_morphology_type,
1156 morphology_type_names,
1157 sizeof(morphology_type_names) / sizeof(char*));
1158 ImGui::SliderFloat2("Radius", radius, 0, 200);
1159 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1160 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1161 ImGui::ColorEdit4("Bounds color ",
1162 reinterpret_cast<float*>(&bounds_color));
1163 ImGui::SliderFloat2("Translation", offset, 0,
1164 pass.GetRenderTargetSize().width);
1165 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1166 ImGui::SliderFloat2("Scale", scale, 0, 3);
1167 ImGui::SliderFloat2("Skew", skew, -3, 3);
1168 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1169 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1170 3);
1171 }
1172 ImGui::End();
1173
1174 std::shared_ptr<Contents> input;
1175 Size input_size;
1176
1177 auto input_rect =
1178 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1179 auto texture = std::make_shared<TextureContents>();
1180 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1181 texture->SetDestinationRect(input_rect);
1182 texture->SetTexture(boston);
1183 texture->SetOpacity(input_color.alpha);
1184
1185 input = texture;
1186 input_size = input_rect.GetSize();
1187
1188 auto contents = FilterContents::MakeMorphology(
1189 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1190 morphology_types[selected_morphology_type]);
1191 contents->SetEffectTransform(Matrix::MakeScale(
1192 Vector2{effect_transform_scale, effect_transform_scale}));
1193
1194 auto ctm = Matrix::MakeScale(GetContentScale()) *
1195 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1196 Matrix::MakeRotationZ(Radians(rotation)) *
1197 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1198 Matrix::MakeSkew(skew[0], skew[1]) *
1199 Matrix::MakeTranslation(-Point(input_size) / 2);
1200
1201 Entity entity;
1202 entity.SetContents(contents);
1203 entity.SetTransform(ctm);
1204
1205 entity.Render(context, pass);
1206
1207 // Renders a red "cover" rectangle that shows the original position of the
1208 // unfiltered input.
1209 Entity cover_entity;
1210 std::unique_ptr<Geometry> geom =
1211 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1212 auto cover_contents = std::make_shared<SolidColorContents>();
1213 cover_contents->SetColor(cover_color);
1214 cover_contents->SetGeometry(geom.get());
1215 cover_entity.SetContents(cover_contents);
1216 cover_entity.SetTransform(ctm);
1217 cover_entity.Render(context, pass);
1218
1219 // Renders a green bounding rect of the target filter.
1220 Entity bounds_entity;
1221 std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1222 flutter::DlPath::MakeRect(contents->GetCoverage(entity).value()));
1223 auto bounds_contents = std::make_shared<SolidColorContents>();
1224 bounds_contents->SetColor(bounds_color);
1225 bounds_contents->SetGeometry(bounds_geom.get());
1226 bounds_entity.SetContents(std::move(bounds_contents));
1227 bounds_entity.SetTransform(Matrix());
1228
1229 bounds_entity.Render(context, pass);
1230
1231 return true;
1232 };
1233 ASSERT_TRUE(OpenPlaygroundHere(callback));
1234 }

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() [428/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2153 of file entity_unittests.cc.

2153 {
2154 std::vector<Point> points = {{10, 20}, {100, 200}};
2155 PointFieldGeometry geometry(points.data(), 2, 5.0, false);
2156 ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2157 ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2158 Rect::MakeLTRB(35, 15, 135, 205));
2159 }

References impeller::PointFieldGeometry::GetCoverage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and points.

## ◆ TEST_P() [429/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2094 of file entity_unittests.cc.

2094 {
2095 Matrix matrix;
2096 RadialGradientContents contents;
2097 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2098 contents.SetGeometry(geom.get());
2099
2100 contents.SetColors({Color::CornflowerBlue()});
2101 EXPECT_TRUE(contents.IsOpaque(matrix));
2102 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2103 EXPECT_FALSE(contents.IsOpaque(matrix));
2104 contents.SetColors({Color::CornflowerBlue()});
2105 contents.SetTileMode(Entity::TileMode::kDecal);
2106 EXPECT_FALSE(contents.IsOpaque(matrix));
2107
2108 // Create stroked path that required alpha coverage.
2109 geom = Geometry::MakeStrokePath(
2110 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2111 {.width = 0.05});
2112 contents.SetGeometry(geom.get());
2113 contents.SetColors({Color::CornflowerBlue()});
2114
2115 EXPECT_FALSE(contents.IsOpaque(matrix));
2116 }

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() [430/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RoundSuperellipseGetPositionBufferFlushes |
| ) |  |

Definition at line 2650 of file entity_unittests.cc.

2650 {
2651 RenderTarget target;
2652 testing::MockRenderPass mock_pass(GetContext(), target);
2653
2654 auto content_context = std::make_shared<FlushTestContentContext>(
2655 GetContext(), GetTypographerContext(),
2656 std::make_shared<FlushTestAllocator>());
2657 auto geometry =
2658 Geometry::MakeRoundSuperellipse(Rect::MakeLTRB(0, 0, 100, 100), 5);
2659 auto result = geometry->GetPositionBuffer(*content_context, {}, mock_pass);
2660
2661 auto device_buffer = reinterpret_cast<const FlushTestDeviceBuffer*>(
2662 result.vertex_buffer.vertex_buffer.GetBuffer());
2663 EXPECT_TRUE(device_buffer->flush_called());
2664 }

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

## ◆ TEST_P() [431/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1393 of file entity_unittests.cc.

1393 {
1394 auto callback = [&](ContentContext& context, RenderPass& pass) {
1395 static Color color = Color::Red();
1396 static float corner_radius = 100;
1397 static float blur_radius = 100;
1398 static bool show_coverage = false;
1399 static Color coverage_color = Color::Green().WithAlpha(0.2);
1400 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1401 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1402 Color::White());
1403
1404 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1405 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1406 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1407 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1408 ImGui::Checkbox("Show coverage", &show_coverage);
1409 if (show_coverage) {
1410 ImGui::ColorEdit4("Coverage color",
1411 reinterpret_cast<Scalar*>(&coverage_color));
1412 }
1413 ImGui::End();
1414
1415 auto [top_left, bottom_right] =
1416 DrawPlaygroundLine(top_left_point, bottom_right_point);
1417 auto rect =
1418 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1419
1420 auto contents = std::make_unique<SolidRRectBlurContents>();
1421 contents->SetShape(rect, corner_radius);
1422 contents->SetColor(color);
1423 contents->SetSigma(Radius(blur_radius));
1424
1425 Entity entity;
1426 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1427 entity.SetContents(std::move(contents));
1428 entity.Render(context, pass);
1429
1430 auto coverage = entity.GetCoverage();
1431 if (show_coverage && coverage.has_value()) {
1432 auto bounds_contents = std::make_unique<SolidColorContents>();
1433 auto geom = Geometry::MakeFillPath(
1434 flutter::DlPath::MakeRect(entity.GetCoverage().value()));
1435 bounds_contents->SetGeometry(geom.get());
1436 bounds_contents->SetColor(coverage_color.Premultiply());
1437 Entity bounds_entity;
1438 bounds_entity.SetContents(std::move(bounds_contents));
1439 bounds_entity.Render(context, pass);
1440 }
1441
1442 return true;
1443 };
1444 ASSERT_TRUE(OpenPlaygroundHere(callback));
1445 }

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() [432/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1753 of file entity_unittests.cc.

1753 {
1754 auto runtime_stages =
1755 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1756 auto runtime_stage =
1757 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1758 ASSERT_TRUE(runtime_stage);
1759 ASSERT_TRUE(runtime_stage->IsDirty());
1760
1761 bool expect_dirty = true;
1762
1763 PipelineRef first_pipeline;
1764 std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1765
1766 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1767 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1768
1769 auto contents = std::make_shared<RuntimeEffectContents>();
1770 contents->SetGeometry(geom.get());
1771 contents->SetRuntimeStage(runtime_stage);
1772
1773 struct FragUniforms {
1774 Vector2 iResolution;
1775 Scalar iTime;
1776 } frag_uniforms = {
1777 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1778 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1779 };
1780 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1781 uniform_data->resize(sizeof(FragUniforms));
1782 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1783 contents->SetUniformData(uniform_data);
1784
1785 Entity entity;
1786 entity.SetContents(contents);
1787 bool result = contents->Render(context, entity, pass);
1788
1789 if (expect_dirty) {
1790 first_pipeline = pass.GetCommands().back().pipeline;
1791 } else {
1792 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1793 }
1794 expect_dirty = false;
1795 return result;
1796 };
1797
1798 // Simulate some renders and hot reloading of the shader.
1799 auto content_context = GetContentContext();
1800 {
1801 RenderTarget target =
1802 content_context->GetRenderTargetCache()->CreateOffscreen(
1803 *content_context->GetContext(), {1, 1}, 1u);
1804
1805 testing::MockRenderPass mock_pass(GetContext(), target);
1806 callback(*content_context, mock_pass);
1807 callback(*content_context, mock_pass);
1808
1809 // Dirty the runtime stage.
1810 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1811 runtime_stage =
1812 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1813
1814 ASSERT_TRUE(runtime_stage->IsDirty());
1815 expect_dirty = true;
1816
1817 callback(*content_context, mock_pass);
1818 }
1819 }
impeller::PipelineRef
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition: pipeline.h:88

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [433/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1868 of file entity_unittests.cc.

1868 {
1869 auto runtime_stages =
1870 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1871 auto runtime_stage =
1872 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1873 ASSERT_TRUE(runtime_stage);
1874 ASSERT_TRUE(runtime_stage->IsDirty());
1875
1876 auto contents = std::make_shared<RuntimeEffectContents>();
1877 contents->SetRuntimeStage(runtime_stage);
1878
1879 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1880 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [434/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1821 of file entity_unittests.cc.

1821 {
1822 auto runtime_stages =
1823 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1824 auto runtime_stage =
1825 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1826 ASSERT_TRUE(runtime_stage);
1827 ASSERT_TRUE(runtime_stage->IsDirty());
1828
1829 auto contents = std::make_shared<RuntimeEffectContents>();
1830 auto geom = Geometry::MakeCover();
1831 contents->SetGeometry(geom.get());
1832 contents->SetRuntimeStage(runtime_stage);
1833
1834 struct FragUniforms {
1835 Vector2 iResolution;
1836 Scalar iTime;
1837 } frag_uniforms = {
1838 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1839 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1840 };
1841 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1842 uniform_data->resize(sizeof(FragUniforms));
1843 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1844 contents->SetUniformData(uniform_data);
1845
1846 Entity entity;
1847 entity.SetContents(contents);
1848
1849 // Create a render target with a depth-stencil, similar to how EntityPass
1850 // does.
1851 RenderTarget target =
1852 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1853 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1854 "RuntimeEffect Texture");
1855 testing::MockRenderPass pass(GetContext(), target);
1856
1857 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1858 ASSERT_EQ(pass.GetCommands().size(), 1u);
1859 const auto& command = pass.GetCommands()[0];
1860 ASSERT_TRUE(command.pipeline->GetDescriptor()
1861 .GetDepthStencilAttachmentDescriptor()
1862 .has_value());
1863 ASSERT_TRUE(command.pipeline->GetDescriptor()
1864 .GetFrontStencilAttachmentDescriptor()
1865 .has_value());
1866 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [435/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1882 of file entity_unittests.cc.

1882 {
1883 if (GetBackend() != PlaygroundBackend::kVulkan) {
1884 GTEST_SKIP() << "Test only applies to Vulkan";
1885 }
1886
1887 auto runtime_stages =
1888 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1889 auto runtime_stage =
1890 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1891 ASSERT_TRUE(runtime_stage);
1892 ASSERT_TRUE(runtime_stage->IsDirty());
1893
1894 auto contents = std::make_shared<RuntimeEffectContents>();
1895 auto geom = Geometry::MakeCover();
1896 contents->SetGeometry(geom.get());
1897 contents->SetRuntimeStage(runtime_stage);
1898
1899 struct FragUniforms {
1900 Vector2 iResolution;
1901 Scalar iTime;
1902 } frag_uniforms = {
1903 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1904 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1905 };
1906 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1907 uniform_data->resize(sizeof(FragUniforms));
1908 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1909
1910 auto buffer_view = RuntimeEffectContents::EmplaceVulkanUniform(
1911 uniform_data, GetContentContext()->GetTransientsDataBuffer(),
1912 runtime_stage->GetUniforms()[0],
1913 GetContentContext()
1914 ->GetTransientsDataBuffer()
1915 .GetMinimumUniformAlignment());
1916
1917 // 16 bytes:
1918 // 8 bytes for iResolution
1919 // 4 bytes for iTime
1920 // 4 bytes padding
1921 EXPECT_EQ(buffer_view.GetRange().length, 16u);
1922 }

References buffer_view, impeller::RuntimeEffectContents::EmplaceVulkanUniform(), impeller::kVulkan, impeller::Geometry::MakeCover(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [436/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1236 of file entity_unittests.cc.

1236 {
1237 Entity entity;
1238 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSrcOver);
1239 entity.SetBlendMode(BlendMode::kClear);
1240 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1241 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSrcOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [437/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2499 of file entity_unittests.cc.

2499 {
2500 auto contents = SolidColorContents();
2501 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2502 auto result = contents.ApplyColorFilter([](const Color& color) {
2503 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2504 });
2505 ASSERT_TRUE(result);
2506 ASSERT_COLOR_NEAR(contents.GetColor(),
2507 Color(0.424452, 0.828743, 0.79105, 0.9375));
2508 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [438/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2029 of file entity_unittests.cc.

2029 {
2030 Matrix matrix;
2031 SolidColorContents contents;
2032 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2033 contents.SetGeometry(geom.get());
2034
2035 contents.SetColor(Color::CornflowerBlue());
2036 EXPECT_TRUE(contents.IsOpaque(matrix));
2037 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2038 EXPECT_FALSE(contents.IsOpaque(matrix));
2039
2040 // Create stroked path that required alpha coverage.
2041 geom = Geometry::MakeStrokePath(flutter::DlPath::MakeLine({0, 0}, {100, 100}),
2042 {.width = 0.05});
2043 contents.SetGeometry(geom.get());
2044 contents.SetColor(Color::CornflowerBlue());
2045
2046 EXPECT_FALSE(contents.IsOpaque(matrix));
2047 }

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() [439/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 719 of file entity_unittests.cc.

719 {
720 {
721 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{});
722 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
723 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
724 }
725
726 {
727 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
728 {
729 .width = 1.0f,
730 .miter_limit = 8.0f,
731 });
732 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
733 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
734 }
735
736 {
737 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
738 {
739 .width = 1.0f,
740 .miter_limit = -1.0f,
741 });
742 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
743 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
744 }
745 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [440/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 687 of file entity_unittests.cc.

687 {
688 {
689 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{});
690 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
691 // Defaults.
692 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
693 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
694 }
695
696 {
697 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
698 {
699 .width = 1.0f,
700 .cap = Cap::kSquare,
701 .miter_limit = 4.0f,
702 });
703 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
704 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
705 }
706
707 {
708 auto geometry = Geometry::MakeStrokePath(flutter::DlPath{}, //
709 {
710 .width = 1.0f,
711 .cap = Cap::kRound,
712 .miter_limit = 4.0f,
713 });
714 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
715 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
716 }
717 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [441/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1348 of file entity_unittests.cc.

1348 {
1349 // No transform
1350 {
1351 auto fill = std::make_shared<SolidColorContents>();
1352 fill->SetColor(Color::CornflowerBlue());
1353 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1354 auto geom = Geometry::MakeFillPath(flutter::DlPath::MakeRect(expected));
1355 fill->SetGeometry(geom.get());
1356
1357 auto coverage = fill->GetCoverage({});
1358 ASSERT_TRUE(coverage.has_value());
1359 ASSERT_RECT_NEAR(coverage.value(), expected);
1360 }
1361
1362 // Entity transform
1363 {
1364 auto fill = std::make_shared<SolidColorContents>();
1365 auto geom = Geometry::MakeFillPath(
1366 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1367 fill->SetColor(Color::CornflowerBlue());
1368 fill->SetGeometry(geom.get());
1369
1370 Entity entity;
1371 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1372 entity.SetContents(std::move(fill));
1373
1374 auto coverage = entity.GetCoverage();
1375 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1376 ASSERT_TRUE(coverage.has_value());
1377 ASSERT_RECT_NEAR(coverage.value(), expected);
1378 }
1379
1380 // No coverage for fully transparent colors
1381 {
1382 auto fill = std::make_shared<SolidColorContents>();
1383 auto geom = Geometry::MakeFillPath(
1384 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1385 fill->SetColor(Color::WhiteTransparent());
1386 fill->SetGeometry(geom.get());
1387
1388 auto coverage = fill->GetCoverage({});
1389 ASSERT_FALSE(coverage.has_value());
1390 }
1391 }

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() [442/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1249 of file entity_unittests.cc.

1249 {
1250 {
1251 auto geometry = Geometry::MakeStrokePath(
1252 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1253 {
1254 .width = 4.0f,
1255 .cap = Cap::kButt,
1256 .join = Join::kBevel,
1257 .miter_limit = 4.0f,
1258 });
1259
1260 Entity entity;
1261 auto contents = std::make_unique<SolidColorContents>();
1262 contents->SetGeometry(geometry.get());
1263 contents->SetColor(Color::Black());
1264 entity.SetContents(std::move(contents));
1265 auto actual = entity.GetCoverage();
1266 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1267
1268 ASSERT_TRUE(actual.has_value());
1269 ASSERT_RECT_NEAR(actual.value(), expected);
1270 }
1271
1272 // Cover the Cap::kSquare case.
1273 {
1274 auto geometry = Geometry::MakeStrokePath(
1275 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1276 {
1277 .width = 4.0,
1278 .cap = Cap::kSquare,
1279 .join = Join::kBevel,
1280 .miter_limit = 4.0,
1281 });
1282
1283 Entity entity;
1284 auto contents = std::make_unique<SolidColorContents>();
1285 contents->SetGeometry(geometry.get());
1286 contents->SetColor(Color::Black());
1287 entity.SetContents(std::move(contents));
1288 auto actual = entity.GetCoverage();
1289 auto expected =
1290 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1291
1292 ASSERT_TRUE(actual.has_value());
1293 ASSERT_RECT_NEAR(actual.value(), expected);
1294 }
1295
1296 // Cover the Join::kMiter case.
1297 {
1298 auto geometry = Geometry::MakeStrokePath(
1299 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1300 {
1301 .width = 4.0f,
1302 .cap = Cap::kSquare,
1303 .join = Join::kMiter,
1304 .miter_limit = 2.0f,
1305 });
1306
1307 Entity entity;
1308 auto contents = std::make_unique<SolidColorContents>();
1309 contents->SetGeometry(geometry.get());
1310 contents->SetColor(Color::Black());
1311 entity.SetContents(std::move(contents));
1312 auto actual = entity.GetCoverage();
1313 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1314
1315 ASSERT_TRUE(actual.has_value());
1316 ASSERT_RECT_NEAR(actual.value(), expected);
1317 }
1318 }

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() [443/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2189 of file entity_unittests.cc.

2189 {
2190 auto content_context = GetContentContext();
2191
2192 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2193 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2194 .has_depth_stencil_attachments = false,
2195 });
2196 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2197 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2198 .has_depth_stencil_attachments = true});
2199
2200 EXPECT_NE(default_gyph, alt_gyph);
2201 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2202 alt_gyph->GetDescriptor().GetSpecializationConstants());
2203
2204 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2205 PixelFormat::kA8UNormInt;
2206
2207 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2208 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2209 expected_constants);
2210 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [444/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1610 of file entity_unittests.cc.

1610 {
1611 auto image = CreateTextureForFixture("embarcadero.jpg");
1612 ASSERT_TRUE(image);
1613
1614 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1615 auto filtered =
1616 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1617
1618 // Define the entity that will serve as the control image as a Gaussian blur
1619 // filter with no filter at all.
1620 Entity entity_left;
1621 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1622 Matrix::MakeTranslation({100, 300}) *
1623 Matrix::MakeScale(Vector2{0.5, 0.5}));
1624 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1625 Sigma{0}, Sigma{0});
1626 entity_left.SetContents(unfiltered);
1627
1628 // Define the entity that will be filtered from sRGB to linear.
1629 Entity entity_right;
1630 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1631 Matrix::MakeTranslation({500, 300}) *
1632 Matrix::MakeScale(Vector2{0.5, 0.5}));
1633 entity_right.SetContents(filtered);
1634 return entity_left.Render(context, pass) &&
1635 entity_right.Render(context, pass);
1636 };
1637
1638 ASSERT_TRUE(OpenPlaygroundHere(callback));
1639 }

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() [445/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1588 of file entity_unittests.cc.

1588 {
1589 // Set up a simple color background.
1590 auto fill = std::make_shared<SolidColorContents>();
1591 auto geom = Geometry::MakeFillPath(
1592 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1593 fill->SetGeometry(geom.get());
1594 fill->SetColor(Color::DeepPink());
1595
1596 auto filter =
1597 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1598
1599 Entity e;
1600 e.SetTransform(Matrix());
1601
1602 // Confirm that the actual filter coverage matches the expected coverage.
1603 auto actual = filter->GetCoverage(e);
1604 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1605
1606 ASSERT_TRUE(actual.has_value());
1607 ASSERT_RECT_NEAR(actual.value(), expected);
1608 }

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() [446/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 200 of file entity_unittests.cc.

200 {
201 const Point padding(300, 250);
202 const Point margin(140, 180);
203
204 auto callback = [&](ContentContext& context, RenderPass& pass) {
205 // Slightly above sqrt(2) by default, so that right angles are just below
206 // the limit and acute angles are over the limit (causing them to get
207 // beveled).
208 static Scalar miter_limit = 1.41421357;
209 static Scalar width = 30;
210
211 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
212 {
213 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
214 ImGui::SliderFloat("Stroke width", &width, 0, 100);
215 if (ImGui::Button("Reset")) {
216 miter_limit = 1.41421357;
217 width = 30;
218 }
219 }
220 ImGui::End();
221
222 auto world_matrix = Matrix::MakeScale(GetContentScale());
223 auto render_path = [width = width, &context, &pass, &world_matrix](
224 const flutter::DlPath& path, Cap cap, Join join) {
225 auto contents = std::make_unique<SolidColorContents>();
226 std::unique_ptr<Geometry> geom =
227 Geometry::MakeStrokePath(path, {
228 .width = width,
229 .cap = cap,
230 .join = join,
231 .miter_limit = miter_limit,
232 });
233 contents->SetGeometry(geom.get());
234 contents->SetColor(Color::Red());
235
236 Entity entity;
237 entity.SetTransform(world_matrix);
238 entity.SetContents(std::move(contents));
239
240 auto coverage = entity.GetCoverage();
241 if (coverage.has_value()) {
242 auto bounds_contents = std::make_unique<SolidColorContents>();
243
244 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
245 flutter::DlPath::MakeRect(entity.GetCoverage().value()));
246
247 bounds_contents->SetGeometry(geom.get());
248 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
249 Entity bounds_entity;
250 bounds_entity.SetContents(std::move(bounds_contents));
251 bounds_entity.Render(context, pass);
252 }
253
254 entity.Render(context, pass);
255 };
256
257 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
258 e_def(75, 75);
259 const Scalar r = 30;
260 // Cap::kButt demo.
261 {
262 Point off = Point(0, 0) * padding + margin;
263 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
264 static PlaygroundPoint point_b(off + b_def, r, Color::White());
265 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
266 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
267 static PlaygroundPoint point_d(off + d_def, r, Color::White());
268 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
269 render_path(flutter::DlPathBuilder{} //
270 .MoveTo(a)
271 .CubicCurveTo(b, d, c)
272 .TakePath(),
273 Cap::kButt, Join::kBevel);
274 }
275
276 // Cap::kSquare demo.
277 {
278 Point off = Point(1, 0) * padding + margin;
279 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
280 static PlaygroundPoint point_b(off + b_def, r, Color::White());
281 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
282 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
283 static PlaygroundPoint point_d(off + d_def, r, Color::White());
284 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
285 render_path(flutter::DlPathBuilder{} //
286 .MoveTo(a)
287 .CubicCurveTo(b, d, c)
288 .TakePath(),
289 Cap::kSquare, Join::kBevel);
290 }
291
292 // Cap::kRound demo.
293 {
294 Point off = Point(2, 0) * padding + margin;
295 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
296 static PlaygroundPoint point_b(off + b_def, r, Color::White());
297 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
298 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
299 static PlaygroundPoint point_d(off + d_def, r, Color::White());
300 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
301 render_path(flutter::DlPathBuilder{} //
302 .MoveTo(a)
303 .CubicCurveTo(b, d, c)
304 .TakePath(),
305 Cap::kRound, Join::kBevel);
306 }
307
308 // Join::kBevel demo.
309 {
310 Point off = Point(0, 1) * padding + margin;
311 static PlaygroundPoint point_a =
312 PlaygroundPoint(off + a_def, r, Color::White());
313 static PlaygroundPoint point_b =
314 PlaygroundPoint(off + e_def, r, Color::White());
315 static PlaygroundPoint point_c =
316 PlaygroundPoint(off + c_def, r, Color::White());
317 Point a = DrawPlaygroundPoint(point_a);
318 Point b = DrawPlaygroundPoint(point_b);
319 Point c = DrawPlaygroundPoint(point_c);
320 render_path(flutter::DlPathBuilder{} //
321 .MoveTo(a)
322 .LineTo(b)
323 .LineTo(c)
324 .Close()
325 .TakePath(),
326 Cap::kButt, Join::kBevel);
327 }
328
329 // Join::kMiter demo.
330 {
331 Point off = Point(1, 1) * padding + margin;
332 static PlaygroundPoint point_a(off + a_def, r, Color::White());
333 static PlaygroundPoint point_b(off + e_def, r, Color::White());
334 static PlaygroundPoint point_c(off + c_def, r, Color::White());
335 Point a = DrawPlaygroundPoint(point_a);
336 Point b = DrawPlaygroundPoint(point_b);
337 Point c = DrawPlaygroundPoint(point_c);
338 render_path(flutter::DlPathBuilder{} //
339 .MoveTo(a)
340 .LineTo(b)
341 .LineTo(c)
342 .Close()
343 .TakePath(),
344 Cap::kButt, Join::kMiter);
345 }
346
347 // Join::kRound demo.
348 {
349 Point off = Point(2, 1) * padding + margin;
350 static PlaygroundPoint point_a(off + a_def, r, Color::White());
351 static PlaygroundPoint point_b(off + e_def, r, Color::White());
352 static PlaygroundPoint point_c(off + c_def, r, Color::White());
353 Point a = DrawPlaygroundPoint(point_a);
354 Point b = DrawPlaygroundPoint(point_b);
355 Point c = DrawPlaygroundPoint(point_c);
356 render_path(flutter::DlPathBuilder{} //
357 .MoveTo(a)
358 .LineTo(b)
359 .LineTo(c)
360 .Close()
361 .TakePath(),
362 Cap::kButt, Join::kRound);
363 }
364
365 return true;
366 };
367 ASSERT_TRUE(OpenPlaygroundHere(callback));
368 }
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:86
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(), 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() [447/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 132 of file entity_unittests.cc.

132 {
133 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
134 flutter::DlPath path = flutter::DlPathBuilder{}
135 .MoveTo({100, 100})
136 .LineTo({100, 200})
137 .MoveTo({100, 300})
138 .LineTo({100, 400})
139 .MoveTo({100, 500})
140 .LineTo({100, 600})
141 .TakePath();
142
143 Entity entity;
144 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
145 auto contents = std::make_unique<TiledTextureContents>();
146 std::unique_ptr<Geometry> geom =
147 Geometry::MakeStrokePath(path, {.width = 100.0f});
148 contents->SetGeometry(geom.get());
149 contents->SetTexture(bridge);
150 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
151 entity.SetContents(std::move(contents));
152 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
153 }

References impeller::Entity::kClamp, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [448/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2118 of file entity_unittests.cc.

2118 {
2119 Matrix matrix;
2120 RadialGradientContents contents;
2121 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2122 contents.SetGeometry(geom.get());
2123
2124 contents.SetColors({Color::CornflowerBlue()});
2125 EXPECT_TRUE(contents.IsOpaque(matrix));
2126 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2127 EXPECT_FALSE(contents.IsOpaque(matrix));
2128 contents.SetColors({Color::CornflowerBlue()});
2129 contents.SetTileMode(Entity::TileMode::kDecal);
2130 EXPECT_FALSE(contents.IsOpaque(matrix));
2131
2132 // Create stroked path that required alpha coverage.
2133 geom = Geometry::MakeStrokePath(
2134 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2135 {.width = 0.05f});
2136 contents.SetGeometry(geom.get());
2137 contents.SetColors({Color::CornflowerBlue()});
2138
2139 EXPECT_FALSE(contents.IsOpaque(matrix));
2140 }

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() [449/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2181 of file entity_unittests.cc.

2181 {
2182 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f), Rational(43, 100));
2183 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f), Rational(53, 100));
2184 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f), Rational(21, 10));
2185 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f), Rational(0, 1));
2186 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f), Rational(48, 1));
2187 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [450/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 110 of file entity_unittests.cc.

110 {
111 flutter::DlPath path = flutter::DlPathBuilder{}
112 .MoveTo({100, 100})
113 .LineTo({100, 200})
114 .MoveTo({100, 300})
115 .LineTo({100, 400})
116 .MoveTo({100, 500})
117 .LineTo({100, 600})
118 .TakePath();
119
120 Entity entity;
121 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
122 auto contents = std::make_unique<SolidColorContents>();
123
124 std::unique_ptr<Geometry> geom =
125 Geometry::MakeStrokePath(path, {.width = 5.0f});
126 contents->SetGeometry(geom.get());
127 contents->SetColor(Color::Red());
128 entity.SetContents(std::move(contents));
129 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
130 }

References impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [451/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2142 of file entity_unittests.cc.

2142 {
2143 Matrix matrix;
2144 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2145 TiledTextureContents contents;
2146 contents.SetTexture(bay_bridge);
2147 // This is a placeholder test. Images currently never decompress as opaque
2148 // (whether in Flutter or the playground), and so this should currently always
2149 // return false in practice.
2150 EXPECT_FALSE(contents.IsOpaque(matrix));
2151 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [452/549]

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

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() [453/549]

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() [454/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 155 of file entity_unittests.cc.

155 {
156 auto callback = [&](ContentContext& context, RenderPass& pass) {
157 Point offset(100, 100);
158
159 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
160 Point a = DrawPlaygroundPoint(point_a);
161 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
162 Point b = DrawPlaygroundPoint(point_b);
163 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
164 Color::White());
165 Point c = DrawPlaygroundPoint(point_c);
166 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
167 Point d = DrawPlaygroundPoint(point_d);
168 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
169 Point e = DrawPlaygroundPoint(point_e);
170 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
171 Point f = DrawPlaygroundPoint(point_f);
172 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
173 Point g = DrawPlaygroundPoint(point_g);
174 flutter::DlPath path = flutter::DlPathBuilder{}
175 .MoveTo(a)
176 .LineTo(b)
177 .LineTo(c)
178 .LineTo(d)
179 .Close()
180 .MoveTo(e)
181 .LineTo(f)
182 .LineTo(g)
183 .Close()
184 .TakePath();
185
186 Entity entity;
187 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
188 auto contents = std::make_unique<SolidColorContents>();
189 std::unique_ptr<Geometry> geom =
190 Geometry::MakeStrokePath(path, {.width = 20.0});
191 contents->SetGeometry(geom.get());
192 contents->SetColor(Color::Red());
193 entity.SetContents(std::move(contents));
194
195 return entity.Render(context, pass);
196 };
197 ASSERT_TRUE(OpenPlaygroundHere(callback));
198 }

References impeller::saturated::b, 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() [455/549]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1719 of file entity_unittests.cc.

1719 {
1720 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1721 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1722 GTEST_SKIP()
1723 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1724 }
1725
1726 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1727 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1728 YUVColorSpace::kBT601LimitedRange};
1729 for (int i = 0; i < 2; i++) {
1730 auto yuv_color_space = yuv_color_space_array[i];
1731 auto textures =
1732 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1733 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1734 textures[0], textures[1], yuv_color_space);
1735 Entity filter_entity;
1736 filter_entity.SetContents(filter_contents);
1737 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1738
1739 Entity entity;
1740 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1741 contents->SetTexture(snapshot->texture);
1742 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1743 entity.SetContents(contents);
1744 entity.SetTransform(
1745 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1746 entity.Render(context, pass);
1747 }
1748 return true;
1749 };
1750 ASSERT_TRUE(OpenPlaygroundHere(callback));
1751 }
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1658
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() [456/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 334 of file gaussian_blur_filter_contents_unittests.cc.

334 {
335 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
336 auto filter_input = FilterInput::Make(texture);
337 Entity entity;
338 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
339 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
340 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
341 EXPECT_TRUE(uvs_bounds.has_value());
342 if (uvs_bounds.has_value()) {
343 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
344 }
345 }
uvs
Quad uvs
Definition: gaussian_blur_filter_contents.cc:205

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and uvs.

## ◆ TEST_P() [457/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 186 of file gaussian_blur_filter_contents_unittests.cc.

186 {
187 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
188 fml::StatusOr<Scalar> sigma_radius_1 =
189 CalculateSigmaForBlurRadius(1.0, effect_transform);
190 ASSERT_TRUE(sigma_radius_1.ok());
191 GaussianBlurFilterContents contents(
192 /*sigma_x=*/sigma_radius_1.value(),
193 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
194 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
195 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
196 FilterInput::Vector inputs = {FilterInput::Make(texture)};
197 Entity entity;
198 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
199 std::optional<Rect> coverage =
200 contents.GetFilterCoverage(inputs, entity, effect_transform);
201 EXPECT_TRUE(coverage.has_value());
202 if (coverage.has_value()) {
203 EXPECT_RECT_NEAR(coverage.value(),
204 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
205 }
206 }

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() [458/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 165 of file gaussian_blur_filter_contents_unittests.cc.

165 {
166 fml::StatusOr<Scalar> sigma_radius_1 =
167 CalculateSigmaForBlurRadius(1.0, Matrix());
168 ASSERT_TRUE(sigma_radius_1.ok());
169 GaussianBlurFilterContents contents(
170 /*sigma_X=*/sigma_radius_1.value(),
171 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
172 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
173 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
174 FilterInput::Vector inputs = {FilterInput::Make(texture)};
175 Entity entity;
176 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
177 std::optional<Rect> coverage =
178 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
179
180 EXPECT_TRUE(coverage.has_value());
181 if (coverage.has_value()) {
182 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
183 }
184 }

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() [459/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 238 of file gaussian_blur_filter_contents_unittests.cc.

238 {
239 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
240 fml::StatusOr<Scalar> sigma_radius_1 =
241 CalculateSigmaForBlurRadius(1.0, Matrix());
242 ASSERT_TRUE(sigma_radius_1.ok());
243 auto contents = std::make_unique<GaussianBlurFilterContents>(
244 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
245 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
246 contents->SetInputs({FilterInput::Make(texture)});
247 std::shared_ptr<ContentContext> renderer = GetContentContext();
248
249 Entity entity;
250 std::optional<Entity> result =
251 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
252 EXPECT_TRUE(result.has_value());
253 if (result.has_value()) {
254 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
255 std::optional<Rect> result_coverage = result.value().GetCoverage();
256 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
257 EXPECT_TRUE(result_coverage.has_value());
258 EXPECT_TRUE(contents_coverage.has_value());
259 if (result_coverage.has_value() && contents_coverage.has_value()) {
260 EXPECT_TRUE(RectNear(contents_coverage.value(),
261 Rect::MakeLTRB(-1, -1, 101, 101)));
262 EXPECT_TRUE(
263 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
264 }
265 }
266 }

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

## ◆ TEST_P() [460/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 301 of file gaussian_blur_filter_contents_unittests.cc.

302 {
303 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
304 fml::StatusOr<Scalar> sigma_radius_1 =
305 CalculateSigmaForBlurRadius(1.0, Matrix());
306 auto contents = std::make_unique<GaussianBlurFilterContents>(
307 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
308 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
309 contents->SetInputs({FilterInput::Make(texture)});
310 std::shared_ptr<ContentContext> renderer = GetContentContext();
311
312 Entity entity;
313 // Rotate around the top left corner, then push it over to (100, 100).
314 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
315 Matrix::MakeRotationZ(Degrees(90.0)));
316 std::optional<Entity> result =
317 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
318 EXPECT_TRUE(result.has_value());
319 if (result.has_value()) {
320 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
321 std::optional<Rect> result_coverage = result.value().GetCoverage();
322 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
323 EXPECT_TRUE(result_coverage.has_value());
324 EXPECT_TRUE(contents_coverage.has_value());
325 if (result_coverage.has_value() && contents_coverage.has_value()) {
326 EXPECT_TRUE(RectNear(contents_coverage.value(),
327 Rect::MakeLTRB(99, 99, 401, 501)));
328 EXPECT_TRUE(
329 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
330 }
331 }
332 }

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() [461/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 268 of file gaussian_blur_filter_contents_unittests.cc.

269 {
270 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
271 fml::StatusOr<Scalar> sigma_radius_1 =
272 CalculateSigmaForBlurRadius(1.0, Matrix());
273 ASSERT_TRUE(sigma_radius_1.ok());
274 auto contents = std::make_unique<GaussianBlurFilterContents>(
275 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
276 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
277 contents->SetInputs({FilterInput::Make(texture)});
278 std::shared_ptr<ContentContext> renderer = GetContentContext();
279
280 Entity entity;
281 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
282 std::optional<Entity> result =
283 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
284
285 EXPECT_TRUE(result.has_value());
286 if (result.has_value()) {
287 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
288 std::optional<Rect> result_coverage = result.value().GetCoverage();
289 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
290 EXPECT_TRUE(result_coverage.has_value());
291 EXPECT_TRUE(contents_coverage.has_value());
292 if (result_coverage.has_value() && contents_coverage.has_value()) {
293 EXPECT_TRUE(RectNear(contents_coverage.value(),
294 Rect::MakeLTRB(99, 199, 201, 301)));
295 EXPECT_TRUE(
296 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
297 }
298 }
299 }

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() [462/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 347 of file gaussian_blur_filter_contents_unittests.cc.

347 {
348 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
349 auto texture_contents = std::make_shared<TextureContents>();
350 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
351 texture_contents->SetTexture(texture);
352 texture_contents->SetDestinationRect(Rect::MakeXYWH(
353 50, 40, texture->GetSize().width, texture->GetSize().height));
354
355 fml::StatusOr<Scalar> sigma_radius_1 =
356 CalculateSigmaForBlurRadius(1.0, Matrix());
357 auto contents = std::make_unique<GaussianBlurFilterContents>(
358 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
359 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
360 contents->SetInputs({FilterInput::Make(texture_contents)});
361 std::shared_ptr<ContentContext> renderer = GetContentContext();
362
363 Entity entity;
364 std::optional<Entity> result =
365 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
366 EXPECT_TRUE(result.has_value());
367 if (result.has_value()) {
368 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
369 std::optional<Rect> result_coverage = result.value().GetCoverage();
370 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
371 EXPECT_TRUE(result_coverage.has_value());
372 EXPECT_TRUE(contents_coverage.has_value());
373 if (result_coverage.has_value() && contents_coverage.has_value()) {
374 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
375 EXPECT_TRUE(RectNear(result_coverage.value(),
376 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
377 }
378 }
379 }

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() [463/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 381 of file gaussian_blur_filter_contents_unittests.cc.

382 {
383 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
384 auto texture_contents = std::make_shared<TextureContents>();
385 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
386 texture_contents->SetTexture(texture);
387 texture_contents->SetDestinationRect(Rect::MakeXYWH(
388 50, 40, texture->GetSize().width, texture->GetSize().height));
389
390 fml::StatusOr<Scalar> sigma_radius_1 =
391 CalculateSigmaForBlurRadius(1.0, Matrix());
392 auto contents = std::make_unique<GaussianBlurFilterContents>(
393 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
394 FilterContents::BlurStyle::kNormal,
395 /*mask_geometry=*/nullptr);
396 contents->SetInputs({FilterInput::Make(texture_contents)});
397 std::shared_ptr<ContentContext> renderer = GetContentContext();
398
399 Entity entity;
400 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
401 std::optional<Entity> result =
402 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
403 EXPECT_TRUE(result.has_value());
404 if (result.has_value()) {
405 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
406 std::optional<Rect> result_coverage = result.value().GetCoverage();
407 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
408 EXPECT_TRUE(result_coverage.has_value());
409 EXPECT_TRUE(contents_coverage.has_value());
410 if (result_coverage.has_value() && contents_coverage.has_value()) {
411 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
412 // Scaling a blurred entity doesn't seem to scale the blur radius linearly
413 // when comparing results with rrect_blur. That's why this is not
414 // Rect::MakeXYWH(98.f, 78.f, 204.0f, 204.f).
415 EXPECT_TRUE(RectNear(contents_coverage.value(),
416 Rect::MakeXYWH(94.f, 74.f, 212.0f, 212.f)));
417 }
418 }
419 }

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() [464/549]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithEffectTransform |
| ) |  |

Definition at line 421 of file gaussian_blur_filter_contents_unittests.cc.

421 {
422 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
423 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
424 auto texture_contents = std::make_shared<TextureContents>();
425 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
426 texture_contents->SetTexture(texture);
427 texture_contents->SetDestinationRect(Rect::MakeXYWH(
428 50, 40, texture->GetSize().width, texture->GetSize().height));
429
430 fml::StatusOr<Scalar> sigma_radius_1 =
431 CalculateSigmaForBlurRadius(1.0, effect_transform);
432 ASSERT_TRUE(sigma_radius_1.ok());
433 auto contents = std::make_unique<GaussianBlurFilterContents>(
434 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
435 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
436 contents->SetInputs({FilterInput::Make(texture_contents)});
437 contents->SetEffectTransform(effect_transform);
438 std::shared_ptr<ContentContext> renderer = GetContentContext();
439
440 Entity entity;
441 std::optional<Entity> result =
442 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
443 EXPECT_TRUE(result.has_value());
444 if (result.has_value()) {
445 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
446 std::optional<Rect> result_coverage = result.value().GetCoverage();
447 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
448 EXPECT_TRUE(result_coverage.has_value());
449 EXPECT_TRUE(contents_coverage.has_value());
450 if (result_coverage.has_value() && contents_coverage.has_value()) {
451 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
452 EXPECT_TRUE(RectNear(contents_coverage.value(),
453 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
454 }
455 }
456 }

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() [465/549]

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() [466/549]

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() [467/549]

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() [468/549]

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() [469/549]

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() [470/549]

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() [471/549]

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() [472/549]

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() [473/549]

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() [474/549]

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() [475/549]

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() [476/549]

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() [477/549]

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() [478/549]

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() [479/549]

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() [480/549]

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() [481/549]

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() [482/549]

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() [483/549]

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() [484/549]

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() [485/549]

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() [486/549]

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() [487/549]

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() [488/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
1038 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [489/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
174 pass.SetPipeline(pipeline);
175 pass.SetVertexBuffer(vertex_buffer);
176
177 FS::FragInfo frag_info;
178 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
179
180 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [490/549]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BindingNullTexturesDoesNotCrash |
| ) |  |

Definition at line 1620 of file renderer_unittests.cc.

1620 {
1621 using FS = BoxFadeFragmentShader;
1622
1623 auto context = GetContext();
1624 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1625 auto command_buffer = context->CreateCommandBuffer();
1626
1627 RenderTargetAllocator allocator(context->GetResourceAllocator());
1628 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1629
1630 auto pass = command_buffer->CreateRenderPass(target);
1631 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1632 }

References impeller::RenderTargetAllocator::CreateOffscreen().

## ◆ TEST_P() [491/549]

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() [492/549]

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() [493/549]

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() [494/549]

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 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
697 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [495/549]

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 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
582 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [496/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
99 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [497/549]

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 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
810 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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:425
impeller::MinMagFilter
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
Definition: formats.h:415

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() [498/549]

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() [499/549]

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 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
509 auto [data_host_buffer, indexes_host_buffer] =
510 createHostBuffers(GetContext());
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() [500/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
335 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [501/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
256 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [502/549]

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() [503/549]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1511 of file renderer_unittests.cc.

1511 {
1512 // Define shader types
1513 using TextureVS = TextureVertexShader;
1514 using TextureFS = TextureFragmentShader;
1515
1516 using SwizzleVS = SepiaVertexShader;
1517 using SwizzleFS = SwizzleFragmentShader;
1518
1519 using SepiaVS = SepiaVertexShader;
1520 using SepiaFS = SepiaFragmentShader;
1521
1522 auto context = GetContext();
1523 ASSERT_TRUE(context);
1524
1525 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1526 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1527 "support it.";
1528 return;
1529 }
1530
1531 // Create pipelines.
1532 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1533 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1534 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1535
1536 ASSERT_TRUE(texture_pipeline);
1537 ASSERT_TRUE(swizzle_pipeline);
1538 ASSERT_TRUE(sepia_pipeline);
1539
1540 // Vertex buffer builders.
1541 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1542 texture_vtx_builder.AddVertices({
1543 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1544 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1545 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1546 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1547 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1548 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1549 });
1550
1551 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1552 sepia_vtx_builder.AddVertices({
1553 {{100, 100, 0.0}}, // 1
1554 {{800, 100, 0.0}}, // 2
1555 {{800, 800, 0.0}}, // 3
1556 {{100, 100, 0.0}}, // 1
1557 {{800, 800, 0.0}}, // 3
1558 {{100, 800, 0.0}}, // 4
1559 });
1560
1561 auto boston = CreateTextureForFixture("boston.jpg");
1562 ASSERT_TRUE(boston);
1563
1564 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1565 ASSERT_TRUE(sampler);
1566
1567 SinglePassCallback callback = [&](RenderPass& pass) {
1568 auto data_buffer = HostBuffer::Create(
1569 context->GetResourceAllocator(), context->GetIdleWaiter(),
1570 context->GetCapabilities()->GetMinimumUniformAlignment());
1571
1572 // Draw the texture.
1573 {
1574 pass.SetPipeline(texture_pipeline);
1575 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1576 *context->GetResourceAllocator()));
1577 TextureVS::UniformBuffer uniforms;
1578 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1579 Matrix::MakeScale(GetContentScale());
1580 TextureVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1581 TextureFS::BindTextureContents(pass, boston, sampler);
1582 if (!pass.Draw().ok()) {
1583 return false;
1584 }
1585 }
1586
1587 // Draw the sepia toner.
1588 {
1589 pass.SetPipeline(sepia_pipeline);
1590 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1591 *context->GetResourceAllocator()));
1592 SepiaVS::UniformBuffer uniforms;
1593 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1594 Matrix::MakeScale(GetContentScale());
1595 SepiaVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1596 if (!pass.Draw().ok()) {
1597 return false;
1598 }
1599 }
1600
1601 // Draw the swizzle.
1602 {
1603 pass.SetPipeline(swizzle_pipeline);
1604 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1605 *context->GetResourceAllocator()));
1606 SwizzleVS::UniformBuffer uniforms;
1607 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1608 Matrix::MakeScale(GetContentScale());
1609 SwizzleVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1610 if (!pass.Draw().ok()) {
1611 return false;
1612 }
1613 }
1614
1615 return true;
1616 };
1617 OpenPlaygroundHere(callback);
1618 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [504/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
1473 auto buffer = HostBuffer::Create(
1474 context->GetResourceAllocator(), context->GetIdleWaiter(),
1475 context->GetCapabilities()->GetMinimumUniformAlignment());
1476
1477 // Draw the texture.
1478 {
1479 pass.SetPipeline(texture_pipeline);
1480 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1481 *context->GetResourceAllocator()));
1482 TextureVS::UniformBuffer uniforms;
1483 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1484 Matrix::MakeScale(GetContentScale());
1485 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1486 TextureFS::BindTextureContents(pass, boston, sampler);
1487 if (!pass.Draw().ok()) {
1488 return false;
1489 }
1490 }
1491
1492 // Draw the sepia toner.
1493 {
1494 pass.SetPipeline(sepia_pipeline);
1495 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1496 *context->GetResourceAllocator()));
1497 SepiaVS::UniformBuffer uniforms;
1498 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1499 Matrix::MakeScale(GetContentScale());
1500 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1501 if (!pass.Draw().ok()) {
1502 return false;
1503 }
1504 }
1505
1506 return true;
1507 };
1508 OpenPlaygroundHere(callback);
1509 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [505/549]

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() [506/549]

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() [507/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
1096 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [508/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
972 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [509/549]

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() [510/549]

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 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1261 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [511/549]

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 SinglePassCallback callback = [&](RenderPass& pass) {
923 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
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() [512/549]

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() [513/549]

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() [514/549]

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() [515/549]

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() [516/549]

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() [517/549]

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() [518/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 315 of file runtime_stage_unittests.cc.

315 {
316 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
317 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
318
319 ASSERT_TRUE(stage);
320 ASSERT_NE(stage, nullptr);
321 ASSERT_TRUE(RegisterStage(*stage));
322 auto library = GetContext()->GetShaderLibrary();
323 using VS = RuntimeEffectVertexShader;
324 PipelineDescriptor desc;
325 desc.SetLabel("Runtime Stage InkSparkle");
326 desc.AddStageEntrypoint(
327 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
328 desc.AddStageEntrypoint(
329 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
330 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
331 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
332 VS::kInterleavedBufferLayout);
333
334 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
335 VS::kDescriptorSetLayouts[0],
336 DescriptorSetLayout{
337 .binding = 64u,
338 .descriptor_type = DescriptorType::kUniformBuffer,
339 .shader_stage = ShaderStage::kFragment,
340 },
341 };
342 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
343
344 desc.SetVertexDescriptor(std::move(vertex_descriptor));
345 ColorAttachmentDescriptor color0;
346 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
347 StencilAttachmentDescriptor stencil0;
348 stencil0.stencil_compare = CompareFunction::kEqual;
349 desc.SetColorAttachmentDescriptor(0u, color0);
350 desc.SetStencilAttachmentDescriptors(stencil0);
351 const auto stencil_fmt =
352 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
353 desc.SetStencilPixelFormat(stencil_fmt);
354 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
355 ASSERT_NE(pipeline, nullptr);
356 }

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() [519/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniforms |
| ) |  |

Definition at line 56 of file runtime_stage_unittests.cc.

56 {
57 const std::shared_ptr<fml::Mapping> fixture =
58 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
59 ASSERT_TRUE(fixture);
60 ASSERT_GT(fixture->GetSize(), 0u);
61 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
62 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
63
64 ASSERT_TRUE(stage->IsValid());
65 switch (GetBackend()) {
66 case PlaygroundBackend::kMetal:
67 [[fallthrough]];
68 case PlaygroundBackend::kOpenGLES: {
69 ASSERT_EQ(stage->GetUniforms().size(), 17u);
70 {
71 auto uni = stage->GetUniform("u_color");
72 ASSERT_NE(uni, nullptr);
73 EXPECT_EQ(uni->dimensions.rows, 4u);
74 EXPECT_EQ(uni->dimensions.cols, 1u);
75 EXPECT_EQ(uni->location, 0u);
76 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
77 }
78 {
79 auto uni = stage->GetUniform("u_alpha");
80 ASSERT_NE(uni, nullptr);
81 EXPECT_EQ(uni->dimensions.rows, 1u);
82 EXPECT_EQ(uni->dimensions.cols, 1u);
83 EXPECT_EQ(uni->location, 1u);
84 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
85 }
86 {
87 auto uni = stage->GetUniform("u_sparkle_color");
88 ASSERT_NE(uni, nullptr);
89 EXPECT_EQ(uni->dimensions.rows, 4u);
90 EXPECT_EQ(uni->dimensions.cols, 1u);
91 EXPECT_EQ(uni->location, 2u);
92 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
93 }
94 {
95 auto uni = stage->GetUniform("u_sparkle_alpha");
96 ASSERT_NE(uni, nullptr);
97 EXPECT_EQ(uni->dimensions.rows, 1u);
98 EXPECT_EQ(uni->dimensions.cols, 1u);
99 EXPECT_EQ(uni->location, 3u);
100 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
101 }
102 {
103 auto uni = stage->GetUniform("u_blur");
104 ASSERT_NE(uni, nullptr);
105 EXPECT_EQ(uni->dimensions.rows, 1u);
106 EXPECT_EQ(uni->dimensions.cols, 1u);
107 EXPECT_EQ(uni->location, 4u);
108 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
109 }
110 {
111 auto uni = stage->GetUniform("u_radius_scale");
112 ASSERT_NE(uni, nullptr);
113 EXPECT_EQ(uni->dimensions.rows, 1u);
114 EXPECT_EQ(uni->dimensions.cols, 1u);
115 EXPECT_EQ(uni->location, 6u);
116 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
117 }
118 {
119 auto uni = stage->GetUniform("u_max_radius");
120 ASSERT_NE(uni, nullptr);
121 EXPECT_EQ(uni->dimensions.rows, 1u);
122 EXPECT_EQ(uni->dimensions.cols, 1u);
123 EXPECT_EQ(uni->location, 7u);
124 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
125 }
126 {
127 auto uni = stage->GetUniform("u_resolution_scale");
128 ASSERT_NE(uni, nullptr);
129 EXPECT_EQ(uni->dimensions.rows, 2u);
130 EXPECT_EQ(uni->dimensions.cols, 1u);
131 EXPECT_EQ(uni->location, 8u);
132 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
133 }
134 {
135 auto uni = stage->GetUniform("u_noise_scale");
136 ASSERT_NE(uni, nullptr);
137 EXPECT_EQ(uni->dimensions.rows, 2u);
138 EXPECT_EQ(uni->dimensions.cols, 1u);
139 EXPECT_EQ(uni->location, 9u);
140 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
141 }
142 {
143 auto uni = stage->GetUniform("u_noise_phase");
144 ASSERT_NE(uni, nullptr);
145 EXPECT_EQ(uni->dimensions.rows, 1u);
146 EXPECT_EQ(uni->dimensions.cols, 1u);
147 EXPECT_EQ(uni->location, 10u);
148 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
149 }
150
151 {
152 auto uni = stage->GetUniform("u_circle1");
153 ASSERT_NE(uni, nullptr);
154 EXPECT_EQ(uni->dimensions.rows, 2u);
155 EXPECT_EQ(uni->dimensions.cols, 1u);
156 EXPECT_EQ(uni->location, 11u);
157 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
158 }
159 {
160 auto uni = stage->GetUniform("u_circle2");
161 ASSERT_NE(uni, nullptr);
162 EXPECT_EQ(uni->dimensions.rows, 2u);
163 EXPECT_EQ(uni->dimensions.cols, 1u);
164 EXPECT_EQ(uni->location, 12u);
165 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
166 }
167 {
168 auto uni = stage->GetUniform("u_circle3");
169 ASSERT_NE(uni, nullptr);
170 EXPECT_EQ(uni->dimensions.rows, 2u);
171 EXPECT_EQ(uni->dimensions.cols, 1u);
172 EXPECT_EQ(uni->location, 13u);
173 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
174 }
175 {
176 auto uni = stage->GetUniform("u_rotation1");
177 ASSERT_NE(uni, nullptr);
178 EXPECT_EQ(uni->dimensions.rows, 2u);
179 EXPECT_EQ(uni->dimensions.cols, 1u);
180 EXPECT_EQ(uni->location, 14u);
181 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
182 }
183 {
184 auto uni = stage->GetUniform("u_rotation2");
185 ASSERT_NE(uni, nullptr);
186 EXPECT_EQ(uni->dimensions.rows, 2u);
187 EXPECT_EQ(uni->dimensions.cols, 1u);
188 EXPECT_EQ(uni->location, 15u);
189 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
190 }
191 {
192 auto uni = stage->GetUniform("u_rotation3");
193 ASSERT_NE(uni, nullptr);
194 EXPECT_EQ(uni->dimensions.rows, 2u);
195 EXPECT_EQ(uni->dimensions.cols, 1u);
196 EXPECT_EQ(uni->location, 16u);
197 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
198 }
199 break;
200 }
201 case PlaygroundBackend::kVulkan: {
202 EXPECT_EQ(stage->GetUniforms().size(), 1u);
203 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
204 ASSERT_TRUE(uni);
205 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
206 EXPECT_EQ(uni->struct_float_count, 32u);
207
208 // There are 36 4 byte chunks in the UBO: 32 for the 32 floats, and 4 for
209 // padding. Initialize a vector as if they'll all be floats, then manually
210 // set the few padding bytes. If the shader changes, the padding locations
211 // will change as well. For example, if `u_alpha` was moved to the end,
212 // three bytes of padding could potentially be dropped - or if some of the
213 // scalar floats were changed to vec2 or vec4s, or if any vec3s are
214 // introduced.
215 // This means 36 * 4 = 144 bytes total.
216
217 EXPECT_EQ(uni->GetSize(), 144u);
218 std::vector<uint8_t> layout(uni->GetSize() / sizeof(float), 1);
219 layout[5] = 0;
220 layout[6] = 0;
221 layout[7] = 0;
222 layout[23] = 0;
223
224 EXPECT_THAT(uni->struct_layout, ::testing::ElementsAreArray(layout));
225 break;
226 }
227 }
228 }
impeller::kStruct
@ kStruct
Definition: runtime_types.h:27

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFloat, impeller::kMetal, impeller::kOpenGLES, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [520/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerAfterUBO |
| ) |  |

Definition at line 255 of file runtime_stage_unittests.cc.

255 {
256 if (GetBackend() != PlaygroundBackend::kVulkan) {
257 GTEST_SKIP() << "Test only relevant for Vulkan";
258 }
259 const std::shared_ptr<fml::Mapping> fixture =
260 flutter::testing::OpenFixtureAsMapping(
261 "uniforms_and_sampler_2.frag.iplr");
262 ASSERT_TRUE(fixture);
263 ASSERT_GT(fixture->GetSize(), 0u);
264 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
265 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
266
267 EXPECT_EQ(stage->GetUniforms().size(), 2u);
268 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
269 ASSERT_TRUE(uni);
270 // Struct must be offset at 45.
271 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
272 EXPECT_EQ(uni->binding, 64u);
273 // Sampler should be offset at 64 but due to current bug
274 // has offset of 0, the correct offset is computed at runtime.
275 auto sampler_uniform = stage->GetUniform("u_texture");
276 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
277 EXPECT_EQ(sampler_uniform->binding, 65u);
278 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [521/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerBeforeUBO |
| ) |  |

Definition at line 230 of file runtime_stage_unittests.cc.

230 {
231 if (GetBackend() != PlaygroundBackend::kVulkan) {
232 GTEST_SKIP() << "Test only relevant for Vulkan";
233 }
234 const std::shared_ptr<fml::Mapping> fixture =
235 flutter::testing::OpenFixtureAsMapping(
236 "uniforms_and_sampler_1.frag.iplr");
237 ASSERT_TRUE(fixture);
238 ASSERT_GT(fixture->GetSize(), 0u);
239 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
240 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
241
242 EXPECT_EQ(stage->GetUniforms().size(), 2u);
243 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
244 ASSERT_TRUE(uni);
245 // Struct must be offset at 65.
246 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
247 EXPECT_EQ(uni->binding, 65u);
248 // Sampler should be offset at 64 but due to current bug
249 // has offset of 0, the correct offset is computed at runtime.
250 auto sampler_uniform = stage->GetUniform("u_texture");
251 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
252 EXPECT_EQ(sampler_uniform->binding, 64u);
253 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [522/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadValidBlob |
| ) |  |

Definition at line 29 of file runtime_stage_unittests.cc.

29 {
30 const std::shared_ptr<fml::Mapping> fixture =
31 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
32 ASSERT_TRUE(fixture);
33 ASSERT_GT(fixture->GetSize(), 0u);
34 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
35 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
36 ASSERT_TRUE(stage->IsValid());
37 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
38 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [523/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 280 of file runtime_stage_unittests.cc.

280 {
281 const std::shared_ptr<fml::Mapping> fixture =
282 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
283 ASSERT_TRUE(fixture);
284 ASSERT_GT(fixture->GetSize(), 0u);
285 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
286 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
287 ASSERT_TRUE(stage->IsValid());
288 std::promise<bool> registration;
289 auto future = registration.get_future();
290 auto library = GetContext()->GetShaderLibrary();
291 library->RegisterFunction(
292 stage->GetEntrypoint(), //
293 ToShaderStage(stage->GetShaderStage()), //
294 stage->GetCodeMapping(), //
295 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
296 reg.set_value(result);
297 }));
298 ASSERT_TRUE(future.get());
299 {
300 auto function =
301 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
302 ASSERT_NE(function, nullptr);
303 }
304
305 // Check if unregistering works.
306
307 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
308 {
309 auto function =
310 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
311 ASSERT_EQ(function, nullptr);
312 }
313 }
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() [524/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRejectInvalidBlob |
| ) |  |

Definition at line 40 of file runtime_stage_unittests.cc.

40 {
41 ScopedValidationDisable disable_validation;
42 const std::shared_ptr<fml::Mapping> fixture =
43 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
44 ASSERT_TRUE(fixture);
45 auto junk_allocation = std::make_shared<Allocation>();
46 ASSERT_TRUE(junk_allocation->Truncate(Bytes{fixture->GetSize()}, false));
47 // Not meant to be secure. Just reject obviously bad blobs using magic
48 // numbers.
49 ::memset(junk_allocation->GetBuffer(), 127,
50 junk_allocation->GetLength().GetByteSize());
51 auto stages = RuntimeStage::DecodeRuntimeStages(
52 CreateMappingFromAllocation(junk_allocation));
53 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
54 }
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(), impeller::RuntimeStage::DecodeRuntimeStages(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [525/549]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 358 of file runtime_stage_unittests.cc.

358 {
359 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
360 // Right now, SkSL gets implicitly bundled regardless of what the build rule
361 // for this test requested. After
362 // https://github.com/flutter/flutter/issues/138919, this may require a build
363 // rule change or a new test.
364 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
365
366 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
367 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
368 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
369 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [526/549]

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() [527/549]

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() [528/549]

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() [529/549]

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() [530/549]

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() [531/549]

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() [532/549]

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() [533/549]

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() [534/549]

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() [535/549]

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() [536/549]

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() [537/549]

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() [538/549]

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() [539/549]

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, buffer.glyphs, count);
482 sk_font.getPos(buffer.glyphs, count, buffer.points(), {0, 0});
483 };
484
485 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
486 add_char(sk_font, 'A');
487 add_char(sk_font_small, 'B');
488 auto blob = builder.make();
489
490 atlas =
491 CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
492 GlyphAtlas::Type::kAlphaBitmap, Rational(50 + i, 1),
493 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
494 ASSERT_TRUE(!!atlas);
495 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
496 expected_sizes[i]);
497 }
498
499 // The final atlas should contain both the "A" glyph (which was not present
500 // in the previous atlas) and the "B" glyph (which existed in the previous
501 // atlas).
502 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
503 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [540/549]

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() [541/549]

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() [542/549]

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() [543/549]

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() [544/549]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | InvalidAtlasForcesRepopulation |
| ) |  |

Definition at line 628 of file typographer_unittests.cc.

628 {
629 SkFont font = flutter::testing::CreateTestFontOfSize(12);
630 auto blob = SkTextBlob::MakeFromString(
631 "the quick brown fox jumped over the lazy dog.", font);
632 ASSERT_TRUE(blob);
633 auto frame = MakeTextFrameFromTextBlobSkia(blob);
634
635 EXPECT_FALSE(frame->IsFrameComplete());
636
637 auto context = TypographerContextSkia::Make();
638 auto atlas_context =
639 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
640 auto data_host_buffer = HostBuffer::Create(
641 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
642 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
643
644 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
645 GlyphAtlas::Type::kAlphaBitmap,
646 /*scale=*/Rational(1), atlas_context, frame);
647
648 // The glyph position in the atlas was not known when this value
649 // was recorded. It is marked as a placeholder.
650 EXPECT_TRUE(frame->IsFrameComplete());
651 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
652 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
653 // OpenGLES must always increase the atlas backend if the texture grows.
654 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
655 } else {
656 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
657 }
658
659 auto second_context = TypographerContextSkia::Make();
660 auto second_atlas_context =
661 second_context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
662
663 EXPECT_FALSE(second_atlas_context->GetGlyphAtlas()->IsValid());
664
665 atlas = CreateGlyphAtlas(*GetContext(), second_context.get(),
666 *data_host_buffer, GlyphAtlas::Type::kAlphaBitmap,
667 /*scale=*/Rational(1), second_atlas_context, frame);
668
669 EXPECT_TRUE(second_atlas_context->GetGlyphAtlas()->IsValid());
670 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [545/549]

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() [546/549]

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() [547/549]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameAtlasGenerationTracksState |
| ) |  |

Definition at line 575 of file typographer_unittests.cc.

575 {
576 SkFont font = flutter::testing::CreateTestFontOfSize(12);
577 auto blob = SkTextBlob::MakeFromString(
578 "the quick brown fox jumped over the lazy dog.", font);
579 ASSERT_TRUE(blob);
580 auto frame = MakeTextFrameFromTextBlobSkia(blob);
581
582 EXPECT_FALSE(frame->IsFrameComplete());
583
584 auto context = TypographerContextSkia::Make();
585 auto atlas_context =
586 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
587 auto data_host_buffer = HostBuffer::Create(
588 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
589 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
590
591 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
592 GlyphAtlas::Type::kAlphaBitmap,
593 /*scale=*/Rational(1), atlas_context, frame);
594
595 // The glyph position in the atlas was not known when this value
596 // was recorded. It is marked as a placeholder.
597 EXPECT_TRUE(frame->IsFrameComplete());
598 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
599 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
600 // OpenGLES must always increase the atlas backend if the texture grows.
601 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
602 } else {
603 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
604 }
605
606 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
607 GlyphAtlas::Type::kAlphaBitmap,
608 /*scale=*/Rational(1), atlas_context, frame);
609
610 // The second time the glyph is rendered, the bounds are correcly known.
611 EXPECT_TRUE(frame->IsFrameComplete());
612 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
613 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
614 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
615 } else {
616 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
617 }
618
619 // Force increase the generation.
620 atlas_context->GetGlyphAtlas()->SetAtlasGeneration(2u);
621 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
622 GlyphAtlas::Type::kAlphaBitmap,
623 /*scale=*/Rational(1), atlas_context, frame);
624
625 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 2u);
626 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [548/549]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInitialBoundsArePlaceholder |
| ) |  |

Definition at line 505 of file typographer_unittests.cc.

505 {
506 SkFont font = flutter::testing::CreateTestFontOfSize(12);
507 auto blob = SkTextBlob::MakeFromString(
508 "the quick brown fox jumped over the lazy dog.", font);
509 ASSERT_TRUE(blob);
510 auto frame = MakeTextFrameFromTextBlobSkia(blob);
511
512 EXPECT_FALSE(frame->IsFrameComplete());
513
514 auto context = TypographerContextSkia::Make();
515 auto atlas_context =
516 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
517 auto data_host_buffer = HostBuffer::Create(
518 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
519 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
520
521 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
522 GlyphAtlas::Type::kAlphaBitmap,
523 /*scale=*/Rational(1), atlas_context, frame);
524
525 // The glyph position in the atlas was not known when this value
526 // was recorded. It is marked as a placeholder.
527 EXPECT_TRUE(frame->IsFrameComplete());
528 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
529
530 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
531 GlyphAtlas::Type::kAlphaBitmap,
532 /*scale=*/Rational(1), atlas_context, frame);
533
534 // The second time the glyph is rendered, the bounds are correcly known.
535 EXPECT_TRUE(frame->IsFrameComplete());
536 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
537 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [549/549]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInvalidationWithScale |
| ) |  |

Definition at line 539 of file typographer_unittests.cc.

539 {
540 SkFont font = flutter::testing::CreateTestFontOfSize(12);
541 auto blob = SkTextBlob::MakeFromString(
542 "the quick brown fox jumped over the lazy dog.", font);
543 ASSERT_TRUE(blob);
544 auto frame = MakeTextFrameFromTextBlobSkia(blob);
545
546 EXPECT_FALSE(frame->IsFrameComplete());
547
548 auto context = TypographerContextSkia::Make();
549 auto atlas_context =
550 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
551 auto data_host_buffer = HostBuffer::Create(
552 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
553 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
554
555 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
556 GlyphAtlas::Type::kAlphaBitmap,
557 /*scale=*/Rational(1), atlas_context, frame);
558
559 // The glyph position in the atlas was not known when this value
560 // was recorded. It is marked as a placeholder.
561 EXPECT_TRUE(frame->IsFrameComplete());
562 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
563
564 // Change the scale and the glyph data will still be a placeholder, as the
565 // old data is no longer valid.
566 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *data_host_buffer,
567 GlyphAtlas::Type::kAlphaBitmap,
568 /*scale=*/Rational(2), atlas_context, frame);
569
570 // The second time the glyph is rendered, the bounds are correcly known.
571 EXPECT_TRUE(frame->IsFrameComplete());
572 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
573 }

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 376 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 586 of file aiks_dl_blur_unittests.cc.