| 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 | 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 | 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 (StringsTest, CanSPrintF)
| 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, 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, 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 (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)
| 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 (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)
| 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 &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 &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 43 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/11]

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

## ◆ CAPABILITY_TEST() [2/11]

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

## ◆ CAPABILITY_TEST() [3/11]

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

## ◆ CAPABILITY_TEST() [4/11]

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

## ◆ CAPABILITY_TEST() [5/11]

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

## ◆ CAPABILITY_TEST() [6/11]

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

## ◆ CAPABILITY_TEST() [7/11]

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

## ◆ CAPABILITY_TEST() [8/11]

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

## ◆ CAPABILITY_TEST() [9/11]

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

## ◆ CAPABILITY_TEST() [10/11]

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

## ◆ CAPABILITY_TEST() [11/11]

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

## ◆ CompareFunctionUI()

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

Definition at line 1220 of file renderer_unittests.cc.

1220 {
1221 static CompareFunctionUIData data;
1222 return data;
1223 }
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 1413 of file renderer_unittests.cc.

1414 {
1415 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1416 auto pipeline_desc =
1417 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1418 if (!pipeline_desc.has_value()) {
1419 return nullptr;
1420 }
1421 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1422 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1423 auto pipeline =
1424 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1425 if (!pipeline || !pipeline->IsValid()) {
1426 return nullptr;
1427 }
1428 return pipeline;
1429 }

References impeller::kCount4.

## ◆ CreateGlyphAtlas() [1/2]

static std::shared_ptr<GlyphAtlas> impeller::testing::CreateGlyphAtlas | ( | Context & | context,
|  | const TypographerContext * | typographer_context,
|  | HostBuffer & | 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, 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 & | 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, 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 25 of file canvas_unittests.cc.

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

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

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

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 | ) |
| inlinestaticconstexpr

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 | ) |
| inlinestaticconstexpr

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

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

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

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
| ) |  |
| inlinestaticconstexpr

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
| ) |  |
| inlinestaticconstexpr

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 264 of file base_unittests.cc.

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

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

Definition at line 255 of file base_unittests.cc.

255 {
256 auto wrapper = std::make_shared<NoExceptionPromise<int>>();
257 std::future future = wrapper->get_future();
258
259 // Destroy the empty promise with the future still pending. Verify that the
260 // process does not abort while destructing the promise.
261 wrapper.reset();
262 }

## ◆ TEST() [30/524]

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

Definition at line 248 of file base_unittests.cc.

248 {
249 NoExceptionPromise<int> wrapper;
250 std::future future = wrapper.get_future();
251 wrapper.set_value(123);
252 ASSERT_EQ(future.get(), 123);
253 }

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

## ◆ TEST() [31/524]

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:54
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() [32/524]

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

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

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

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

Definition at line 33 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [36/524]

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

Definition at line 51 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [37/524]

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

Definition at line 61 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [38/524]

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

Definition at line 42 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [39/524]

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

Definition at line 70 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [40/524]

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

Definition at line 79 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [41/524]

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

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

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

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

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

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

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

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

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

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

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

Definition at line 203 of file base_unittests.cc.

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

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

## ◆ TEST() [52/524]

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

Definition at line 158 of file base_unittests.cc.

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

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

## ◆ TEST() [53/524]

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

Definition at line 120 of file base_unittests.cc.

120 {
121 CVTest test;
122 // test.rando_ivar = 12; // <--- Static analysis error
123 for (size_t i = 0; i < 2; ++i) {
124 test.mutex.Lock(); // <--- Static analysis error without this.
125 auto result = test.cv.WaitFor(
126 test.mutex, std::chrono::milliseconds{10},
127 [&]() IPLR_REQUIRES(test.mutex) {
128 test.rando_ivar = 12; // <-- Static analysics error without the
129 // IPLR_REQUIRES on the pred.
130 return false;
131 });
132 test.mutex.Unlock();
133 ASSERT_FALSE(result);
134 }
135 Lock lock(test.mutex); // <--- Static analysis error without this.
136 // The predicate never returns true. So return has to be due to a non-spurious
137 // wake.
138 ASSERT_EQ(test.rando_ivar, 12u);
139 }
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() [54/524]

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

Definition at line 141 of file base_unittests.cc.

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

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

## ◆ TEST() [55/524]

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

Definition at line 97 of file base_unittests.cc.

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

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

## ◆ TEST() [56/524]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## ◆ TEST() [92/524]

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

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

## ◆ TEST() [93/524]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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:121
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() [505/524]

impeller::testing::TEST | ( | StringsTest | ,
|  | CanSPrintF |
| ) |  |

Definition at line 84 of file base_unittests.cc.

84 {
85 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
86 ASSERT_EQ(SPrintF(""), "");
87 ASSERT_EQ(SPrintF("Hello"), "Hello");
88 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
89 }
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12

References impeller::SPrintF().

## ◆ TEST() [506/524]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## ◆ TEST_P() [1/545]

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

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

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

Definition at line 175 of file canvas_unittests.cc.

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

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

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

Definition at line 215 of file canvas_unittests.cc.

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

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

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

Definition at line 140 of file canvas_unittests.cc.

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

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

Definition at line 252 of file canvas_unittests.cc.

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

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

## ◆ TEST_P() [7/545]

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

Definition at line 2080 of file aiks_dl_basic_unittests.cc.

2080 {
2081 DisplayListBuilder builder;
2082
2083 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
2084 builder.Save();
2085 {
2086 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
2087
2088 builder.Save();
2089 {
2090 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
2091 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
2092 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
2093 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
2094 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
2095 }
2096 builder.Restore();
2097
2098 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
2099 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
2100 }
2101 builder.Restore();
2102 builder.DrawCircle(DlPoint(100, 100), 100,
2103 DlPaint().setColor(DlColor::kAqua()));
2104
2105 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2106 }

## ◆ TEST_P() [8/545]

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

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

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

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

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

Definition at line 1344 of file aiks_dl_blur_unittests.cc.

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

References x.

## ◆ TEST_P() [13/545]

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

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

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

Definition at line 1197 of file aiks_dl_blur_unittests.cc.

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

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

## ◆ TEST_P() [16/545]

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

Definition at line 157 of file aiks_dl_vertices_unittests.cc.

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

## ◆ TEST_P() [17/545]

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

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

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

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

Definition at line 404 of file aiks_dl_basic_unittests.cc.

404 {
405 auto medium_turquoise =
406 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
407
408 DisplayListBuilder builder;
409 builder.Scale(0.2, 0.2);
410 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
411 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
412 }

## ◆ TEST_P() [21/545]

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

Definition at line 414 of file aiks_dl_basic_unittests.cc.

414 {
415 auto medium_turquoise =
416 DlColor::RGBA(72.0f / 255.0f, 209.0f / 255.0f, 204.0f / 255.0f, 1.0f);
417 auto orange_red =
418 DlColor::RGBA(255.0f / 255.0f, 69.0f / 255.0f, 0.0f / 255.0f, 1.0f);
419
420 DisplayListBuilder builder;
421 builder.Scale(0.2, 0.2);
422 builder.DrawPaint(DlPaint().setColor(medium_turquoise));
423 builder.DrawPaint(DlPaint().setColor(orange_red.modulateOpacity(0.5f)));
424 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
425 }

## ◆ TEST_P() [22/545]

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

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

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

Definition at line 1307 of file aiks_dl_basic_unittests.cc.

1307 {
1308 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
1309 int time = 0;
1310 auto callback = [&]() -> sk_sp<DisplayList> {
1311 DisplayListBuilder builder;
1312
1313 builder.Save();
1314 {
1315 builder.Translate(300, 300);
1316
1317 // 1. Draw/restore a clip before drawing the image, which will get drawn
1318 // to the depth buffer behind the image.
1319 builder.Save();
1320 {
1321 DlPaint paint;
1322 paint.setColor(DlColor::kGreen());
1323 builder.DrawPaint(paint);
1324 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
1325 DlClipOp::kDifference);
1326
1327 paint.setColor(DlColor::kBlack());
1328 builder.DrawPaint(paint);
1329 }
1330 builder.Restore(); // Restore rectangle difference clip.
1331
1332 builder.Save();
1333 {
1334 // 2. Draw an oval clip that applies to the image, which will get drawn
1335 // in front of the image on the depth buffer.
1336 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
1337
1338 Matrix result =
1339 Matrix(1.0, 0.0, 0.0, 0.0, //
1340 0.0, 1.0, 0.0, 0.0, //
1341 0.0, 0.0, 1.0, 0.003, //
1342 0.0, 0.0, 0.0, 1.0) *
1343 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
1344
1345 // 3. Draw the rotating image with a perspective transform.
1346 builder.Transform(result);
1347
1348 auto image =
1349 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1350 auto position =
1351 -DlPoint(image->GetSize().width, image->GetSize().height) * 0.5;
1352 builder.DrawImage(image, position, {});
1353 }
1354 builder.Restore(); // Restore oval intersect clip.
1355
1356 // 4. Draw a semi-translucent blue circle atop all previous draws.
1357 DlPaint paint;
1358 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
1359 builder.DrawCircle(DlPoint(), 230, paint);
1360 }
1361 builder.Restore(); // Restore translation.
1362
1363 return builder.Build();
1364 };
1365 ASSERT_TRUE(OpenPlaygroundHere(callback));
1366 }

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

## ◆ TEST_P() [25/545]

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

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

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

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

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

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

Definition at line 1648 of file aiks_dl_basic_unittests.cc.

1648 {
1649 DisplayListBuilder builder;
1650
1651 DlPaint paint;
1652 paint.setColor(DlColor::kRed());
1653 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1654
1655 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1656 }

## ◆ TEST_P() [31/545]

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

Definition at line 1669 of file aiks_dl_basic_unittests.cc.

1669 {
1670 DisplayListBuilder builder;
1671
1672 DlPaint save;
1673 save.setColor(DlColor::kBlack());
1674
1675 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1676 builder.SaveLayer(save_bounds, &save);
1677
1678 DlPaint paint;
1679 paint.setColor(DlColor::kRed());
1680 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1681 paint.setColor(DlColor::kGreen());
1682 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1683 paint.setColor(DlColor::kBlue());
1684 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1685
1686 builder.Restore();
1687
1688 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1689 }

## ◆ TEST_P() [32/545]

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

Definition at line 1570 of file aiks_dl_basic_unittests.cc.

1571 {
1572 DisplayListBuilder builder;
1573
1574 DlPaint red;
1575 red.setColor(DlColor::kRed());
1576
1577 DlPaint green;
1578 green.setColor(DlColor::kGreen());
1579
1580 DlPaint blue;
1581 blue.setColor(DlColor::kBlue());
1582
1583 DlPaint save;
1584 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1585
1586 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1587 builder.SaveLayer(huge_bounds, &save);
1588
1589 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1590 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1591 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1592
1593 builder.Restore();
1594
1595 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1596 }

## ◆ TEST_P() [33/545]

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

Definition at line 1658 of file aiks_dl_basic_unittests.cc.

1658 {
1659 DisplayListBuilder builder;
1660
1661 DlPaint red;
1662 red.setColor(DlColor::kRed());
1663 builder.Skew(2, 5);
1664 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1665
1666 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1667 }

## ◆ TEST_P() [34/545]

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

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

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

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

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

References impeller::saturated::b, impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [39/545]

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

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

Definition at line 1268 of file aiks_dl_basic_unittests.cc.

1268 {
1269 DisplayListBuilder builder;
1270
1271 builder.Scale(GetContentScale().x, GetContentScale().y);
1272
1273 // Draw something interesting in the background.
1274 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1275 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
1276 std::vector<Scalar> stops = {
1277 0.0,
1278 1.0,
1279 };
1280 DlPaint paint;
1281 paint.setColorSource(DlColorSource::MakeLinear(
1282 /*start_point=*/DlPoint(0, 0), //
1283 /*end_point=*/DlPoint(100, 100), //
1284 /*stop_count=*/2, //
1285 /*colors=*/colors.data(), //
1286 /*stops=*/stops.data(), //
1287 /*tile_mode=*/DlTileMode::kRepeat //
1288 ));
1289
1290 builder.DrawPaint(paint);
1291
1292 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
1293 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
1294
1295 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
1296 // the same.
1297 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
1298
1299 DlPaint save_paint;
1300 auto backdrop_filter = DlImageFilter::MakeColorFilter(
1301 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
1302 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
1303
1304 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1305 }

References x.

## ◆ TEST_P() [41/545]

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

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

Definition at line 1903 of file aiks_dl_basic_unittests.cc.

1903 {
1904 DisplayListBuilder builder;
1905
1906 DlPaint paint;
1907 paint.setColor(DlColor::kWhite());
1908 builder.DrawPaint(paint);
1909
1910 // Draw a green circle on the screen.
1911 {
1912 // Increase the clip depth for the savelayer to contend with.
1913 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
1914 builder.ClipPath(path);
1915
1916 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
1917 DlPaint save_paint;
1918 builder.SaveLayer(bounds, &save_paint);
1919
1920 // Fill the layer with white.
1921 paint.setColor(DlColor::kWhite());
1922 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1923 // Fill the layer with green, but do so with a color blend that can't be
1924 // collapsed into the parent pass.
1925 paint.setColor(DlColor::kGreen());
1926 paint.setBlendMode(DlBlendMode::kHardLight);
1927 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1928 }
1929
1930 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1931 }

## ◆ TEST_P() [43/545]

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

Definition at line 39 of file aiks_dl_runtime_effect_unittests.cc.

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

## ◆ TEST_P() [44/545]

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

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

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

Definition at line 62 of file aiks_dl_basic_unittests.cc.

62 {
63 DisplayListBuilder builder;
64 DlPaint paint;
65 paint.setColor(DlColor::kRed());
66 paint.setColorFilter(
67 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
68 paint.setInvertColors(true);
69
70 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
71 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
72 }

## ◆ TEST_P() [47/545]

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

Definition at line 74 of file aiks_dl_basic_unittests.cc.

74 {
75 DisplayListBuilder builder;
76 DlPaint paint;
77 paint.setColor(DlColor::kRed());
78 paint.setColorFilter(
79 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
80 paint.setInvertColors(true);
81
82 builder.DrawPaint(paint);
83 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
84 }

## ◆ TEST_P() [48/545]

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

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

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

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

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

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

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

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

Definition at line 351 of file aiks_dl_basic_unittests.cc.

351 {
352 DisplayListBuilder builder;
353 DlPaint paint;
354
355 DlColor colors[2] = {
356 DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
357 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0),
358 };
359 DlScalar stops[2] = {
360 0.0,
361 1.0,
362 };
363
364 paint.setColorSource(DlColorSource::MakeLinear(
365 /*start_point=*/DlPoint(0, 0), //
366 /*end_point=*/DlPoint(100, 100), //
367 /*stop_count=*/2, //
368 /*colors=*/colors, //
369 /*stops=*/stops, //
370 /*tile_mode=*/DlTileMode::kRepeat //
371 ));
372
373 builder.Save();
374 builder.Translate(100, 100);
375 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
376 builder.Restore();
377
378 builder.Save();
379 builder.Translate(100, 400);
380 builder.DrawCircle(DlPoint(100, 100), 100, paint);
381 builder.Restore();
382 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
383 }
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23

## ◆ TEST_P() [56/545]

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

Definition at line 382 of file aiks_dl_text_unittests.cc.

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

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [57/545]

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

Definition at line 410 of file aiks_dl_text_unittests.cc.

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

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [58/545]

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

Definition at line 394 of file aiks_dl_text_unittests.cc.

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

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

## ◆ TEST_P() [59/545]

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

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

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

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

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

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

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

Definition at line 38 of file aiks_dl_basic_unittests.cc.

38 {
39 DisplayListBuilder builder;
40 DlPaint paint;
41 paint.setColor(DlColor::kRed());
42 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
43 builder.DrawImage(image, DlPoint(100.0, 100.0),
44 DlImageSampling::kNearestNeighbor, &paint);
45 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
46 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [66/545]

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

Definition at line 211 of file aiks_dl_basic_unittests.cc.

211 {
212 DisplayListBuilder builder;
213 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
214
215 DlISize image_half_size =
216 DlISize(image->GetSize().width * 0.5f, image->GetSize().height * 0.5f);
217
218 // Render the bottom right quarter of the source image in a stretched rect.
219 auto source_rect = DlRect::MakeSize(image_half_size);
220 source_rect =
221 source_rect.Shift(image_half_size.width, image_half_size.height);
222
223 builder.DrawImageRect(image, source_rect,
224 DlRect::MakeXYWH(100, 100, 600, 600),
225 DlImageSampling::kNearestNeighbor);
226 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
227 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [67/545]

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

Definition at line 48 of file aiks_dl_basic_unittests.cc.

48 {
49 DisplayListBuilder builder;
50 DlPaint paint;
51 paint.setColor(DlColor::kRed());
52 paint.setColorFilter(
53 DlColorFilter::MakeBlend(DlColor::kYellow(), DlBlendMode::kSrcOver));
54 paint.setInvertColors(true);
55 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
56
57 builder.DrawImage(image, DlPoint(100.0, 100.0),
58 DlImageSampling::kNearestNeighbor, &paint);
59 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
60 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [68/545]

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

Definition at line 362 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [69/545]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1308 of file aiks_dl_blur_unittests.cc.

1309 {
1310 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1311
1312 DisplayListBuilder builder;
1313
1314 DlPaint paint;
1315 builder.DrawImage(image, DlPoint(50.0, 50.0),
1316 DlImageSampling::kNearestNeighbor, &paint);
1317
1318 for (int i = 0; i < 6; i++) {
1319 if (i != 0) {
1320 DlPaint paint;
1321 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1322 builder.SaveLayer(std::nullopt, &paint);
1323 }
1324 DlRoundRect rrect = DlRoundRect::MakeRectXY(
1325 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1326 builder.Save();
1327 builder.ClipRoundRect(rrect);
1328
1329 DlPaint save_paint;
1330 save_paint.setBlendMode(DlBlendMode::kSrc);
1331 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1332 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
1333 /*backdrop_id=*/1);
1334 builder.Restore();
1335 builder.Restore();
1336 if (i != 0) {
1337 builder.Restore();
1338 }
1339 }
1340
1341 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1342 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [88/545]

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

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

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

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

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

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

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

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

Definition at line 385 of file aiks_dl_basic_unittests.cc.

385 {
386 DisplayListBuilder builder;
387 DlPaint paint;
388 paint.setColor(DlColor::kRed());
389
390 RoundingRadii radii = {
391 .top_left = DlSize(50, 25),
392 .top_right = DlSize(25, 50),
393 .bottom_left = DlSize(25, 50),
394 .bottom_right = DlSize(50, 25),
395 };
396 DlRoundRect rrect =
397 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 500, 500), radii);
398
399 builder.DrawRoundRect(rrect, paint);
400
401 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
402 }

References impeller::RoundingRadii::top_left.

## ◆ TEST_P() [96/545]

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

Definition at line 84 of file aiks_dl_runtime_effect_unittests.cc.

84 {
85 auto runtime_stages =
86 OpenAssetAsRuntimeStage("runtime_stage_filter_example.frag.iplr");
87
88 std::shared_ptr<RuntimeStage> runtime_stage =
89 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
90 ASSERT_TRUE(runtime_stage);
91 ASSERT_TRUE(runtime_stage->IsDirty());
92
93 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
94 nullptr,
95 };
96 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
97 uniform_data->resize(sizeof(Vector2));
98
99 DlPaint paint;
100 paint.setColor(DlColor::kAqua());
101 paint.setImageFilter(DlImageFilter::MakeRuntimeEffect(
102 DlRuntimeEffect::MakeImpeller(runtime_stage), sampler_inputs,
103 uniform_data));
104
105 DisplayListBuilder builder;
106 builder.DrawRect(DlRect::MakeXYWH(0, 0, 400, 400), paint);
107
108 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
109 }
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:33

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [97/545]

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

Definition at line 249 of file aiks_dl_basic_unittests.cc.

249 {
250 DisplayListBuilder builder;
251 builder.Scale(GetContentScale().x, GetContentScale().y);
252 DlPaint paint;
253
254 paint.setColor(DlColor::kWhite());
255 builder.DrawPaint(paint);
256
257 auto draw = [&builder](const DlPaint& paint, Scalar x, Scalar y) {
258 builder.Save();
259 builder.Translate(x, y);
260 {
261 builder.Save();
262 builder.ClipRect(DlRect::MakeLTRB(50, 50, 150, 150));
263 builder.DrawPaint(paint);
264 builder.Restore();
265 }
266 {
267 builder.Save();
268 builder.ClipOval(DlRect::MakeLTRB(200, 50, 300, 150));
269 builder.DrawPaint(paint);
270 builder.Restore();
271 }
272 {
273 builder.Save();
274 builder.ClipRoundRect(
275 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(50, 200, 150, 300), 20, 20));
276 builder.DrawPaint(paint);
277 builder.Restore();
278 }
279 {
280 builder.Save();
281 builder.ClipRoundRect(DlRoundRect::MakeRectXY(
282 DlRect::MakeLTRB(200, 230, 300, 270), 20, 20));
283 builder.DrawPaint(paint);
284 builder.Restore();
285 }
286 {
287 builder.Save();
288 builder.ClipRoundRect(DlRoundRect::MakeRectXY(
289 DlRect::MakeLTRB(230, 200, 270, 300), 20, 20));
290 builder.DrawPaint(paint);
291 builder.Restore();
292 }
293 builder.Restore();
294 };
295
296 paint.setColor(DlColor::kBlue());
297 draw(paint, 0, 0);
298
299 DlColor gradient_colors[7] = {
300 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
301 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
302 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
303 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
304 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
305 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
306 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
307 };
308 Scalar stops[7] = {
309 0.0,
310 (1.0 / 6.0) * 1,
311 (1.0 / 6.0) * 2,
312 (1.0 / 6.0) * 3,
313 (1.0 / 6.0) * 4,
314 (1.0 / 6.0) * 5,
315 1.0,
316 };
317 auto texture = CreateTextureForFixture("airplane.jpg",
318 /*enable_mipmapping=*/true);
319 auto image = DlImageImpeller::Make(texture);
320
321 paint.setColorSource(DlColorSource::MakeRadial(
322 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
323 draw(paint, 0, 300);
324
325 paint.setColorSource(
326 DlColorSource::MakeImage(image, DlTileMode::kRepeat, DlTileMode::kRepeat,
327 DlImageSampling::kNearestNeighbor));
328 draw(paint, 300, 0);
329
330 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
331 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [98/545]

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

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

Definition at line 126 of file aiks_dl_text_unittests.cc.

126 {
127 DisplayListBuilder builder;
128
129 DlPaint paint;
130 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
131 builder.DrawPaint(paint);
132
133 ASSERT_TRUE(RenderTextInCanvasSkia(
134 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
135 "Roboto-Regular.ttf",
136 {
137 .stroke = true,
138 }));
139 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
140 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [100/545]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 97 of file aiks_dl_text_unittests.cc.

97 {
98 DisplayListBuilder builder;
99
100 DlPaint paint;
101 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
102 builder.DrawPaint(paint);
103 ASSERT_TRUE(RenderTextInCanvasSkia(
104 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
105 "Roboto-Regular.ttf"));
106
107 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
108 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [114/545]

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

Definition at line 251 of file aiks_dl_text_unittests.cc.

251 {
252 Scalar fine_scale = 0.f;
253 bool is_subpixel = false;
254 auto callback = [&]() -> sk_sp<DisplayList> {
255 if (AiksTest::ImGuiBegin("Controls", nullptr,
256 ImGuiWindowFlags_AlwaysAutoResize)) {
257 ImGui::SliderFloat("Fine Scale", &fine_scale, -1, 1);
258 ImGui::Checkbox("subpixel", &is_subpixel);
259 ImGui::End();
260 }
261
262 DisplayListBuilder builder;
263 DlPaint paint;
264 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
265 builder.DrawPaint(paint);
266 Scalar scale = 2.625 + fine_scale;
267 builder.Scale(scale, scale);
268 RenderTextInCanvasSkia(GetContext(), builder,
269 "the quick brown fox jumped over the lazy dog!.?",
270 "Roboto-Regular.ttf",
271 TextRenderOptions{.is_subpixel = is_subpixel});
272 return builder.Build();
273 };
274
275 ASSERT_TRUE(OpenPlaygroundHere(callback));
276 }
is_subpixel
bool is_subpixel
Definition: text_contents_unittests.cc:28

References impeller::testing::TextRenderOptions::is_subpixel, is_subpixel, and RenderTextInCanvasSkia().

## ◆ TEST_P() [115/545]

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

Definition at line 158 of file aiks_dl_text_unittests.cc.

158 {
159 DisplayListBuilder builder;
160
161 DlPaint paint;
162 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
163 builder.DrawPaint(paint);
164 builder.Scale(0.5, 0.5);
165
166 ASSERT_TRUE(RenderTextInCanvasSkia(
167 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
168 "Roboto-Regular.ttf"));
169 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
170 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [116/545]

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

Definition at line 110 of file aiks_dl_text_unittests.cc.

110 {
111 DisplayListBuilder builder;
112
113 DlPaint paint;
114 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
115 builder.DrawPaint(paint);
116 builder.Translate(1000, 0);
117 builder.Scale(-1, 1);
118
119 ASSERT_TRUE(RenderTextInCanvasSkia(
120 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
121 "Roboto-Regular.ttf"));
122
123 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
124 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [117/545]

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

Definition at line 222 of file aiks_dl_text_unittests.cc.

222 {
223 Scalar scale = 60.0;
224 Scalar offsetx = -500.0;
225 Scalar offsety = 700.0;
226 auto callback = [&]() -> sk_sp<DisplayList> {
227 if (AiksTest::ImGuiBegin("Controls", nullptr,
228 ImGuiWindowFlags_AlwaysAutoResize)) {
229 ImGui::SliderFloat("scale", &scale, 1.f, 300.f);
230 ImGui::SliderFloat("offsetx", &offsetx, -600.f, 100.f);
231 ImGui::SliderFloat("offsety", &offsety, 600.f, 2048.f);
232 ImGui::End();
233 }
234 DisplayListBuilder builder;
235 builder.Scale(GetContentScale().x, GetContentScale().y);
236 DlPaint paint;
237 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
238 builder.DrawPaint(paint);
239 builder.Scale(scale, scale);
240
241 RenderTextInCanvasSkia(
242 GetContext(), builder, "test", "Roboto-Regular.ttf",
243 TextRenderOptions{
244 .position = DlPoint(offsetx / scale, offsety / scale),
245 });
246 return builder.Build();
247 };
248 ASSERT_TRUE(OpenPlaygroundHere(callback));
249 }

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

## ◆ TEST_P() [118/545]

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

Definition at line 423 of file aiks_dl_text_unittests.cc.

423 {
424 DisplayListBuilder builder;
425
426 DlPaint paint;
427 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
428 builder.DrawPaint(paint);
429
430 builder.Translate(100, 100);
431 builder.Scale(0.5, 0.5);
432
433 // Blend the layer with the parent pass using kClear to expose the coverage.
434 paint.setBlendMode(DlBlendMode::kClear);
435 builder.SaveLayer(std::nullopt, &paint);
436 ASSERT_TRUE(RenderTextInCanvasSkia(
437 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
438 "Roboto-Regular.ttf"));
439 builder.Restore();
440
441 // Render the text again over the cleared coverage rect.
442 ASSERT_TRUE(RenderTextInCanvasSkia(
443 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
444 "Roboto-Regular.ttf"));
445
446 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
447 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [119/545]

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

Definition at line 449 of file aiks_dl_text_unittests.cc.

449 {
450 DisplayListBuilder builder;
451 builder.Translate(200, 150);
452
453 // Construct the text blob.
454 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
455 ASSERT_NE(mapping, nullptr);
456
457 Scalar font_size = 80;
458 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
459 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
460
461 DlPaint text_paint;
462 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
463
464 struct {
465 DlPoint position;
466 const char* text;
467 } text[] = {{DlPoint(0, 0), "0F0F0F0"},
468 {DlPoint(1, 2), "789"},
469 {DlPoint(1, 3), "456"},
470 {DlPoint(1, 4), "123"},
471 {DlPoint(0, 6), "0F0F0F0"}};
472 for (auto& t : text) {
473 builder.Save();
474 builder.Translate(t.position.x * font_size * 2,
475 t.position.y * font_size * 1.1);
476 {
477 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
478 ASSERT_NE(blob, nullptr);
479 auto frame = MakeTextFrameFromTextBlobSkia(blob);
480 builder.DrawTextFrame(frame, 0, 0, text_paint);
481 }
482 builder.Restore();
483 }
484
485 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
486 }
font_size
Scalar font_size
Definition: text_contents_unittests.cc:27

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [120/545]

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

Definition at line 142 of file aiks_dl_text_unittests.cc.

142 {
143 DisplayListBuilder builder;
144
145 DlPaint paint;
146 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
147 builder.DrawPaint(paint);
148
149 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
150 "Roboto-Medium.ttf",
151 {
152 .stroke = true,
153 .stroke_width = 4,
154 }));
155 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
156 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [121/545]

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

Definition at line 546 of file aiks_dl_text_unittests.cc.

546 {
547 // Verifies that text scales are clamped to work around
548 // https://github.com/flutter/flutter/issues/136112 .
549
550 DisplayListBuilder builder;
551
552 DlPaint save_paint;
553 builder.SaveLayer(std::nullopt, &save_paint);
554 builder.Transform(Matrix(2000, 0, 0, 0, //
555 0, 2000, 0, 0, //
556 0, 0, -1, 9000, //
557 0, 0, -1, 7000 //
558 ));
559
560 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
561 "Roboto-Regular.ttf"));
562 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
563 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [122/545]

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

Definition at line 565 of file aiks_dl_text_unittests.cc.

565 {
566 DisplayListBuilder text_builder;
567 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
568 "Roboto-Regular.ttf"));
569 auto text_display_list = text_builder.Build();
570
571 DisplayListBuilder builder;
572
573 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
574 0.0, 2.0, 0.0, 0.0, //
575 0.0, 0.0, 1.0, 0.0, //
576 0.0, 0.002, 0.0, 1.0);
577
578 DlPaint save_paint;
579 DlRect window_bounds =
580 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
581 builder.SaveLayer(window_bounds, &save_paint);
582 builder.Transform(matrix);
583 builder.DrawDisplayList(text_display_list, 1.0f);
584 builder.Restore();
585
586 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
587 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [123/545]

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

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

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

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

Definition at line 190 of file aiks_dl_basic_unittests.cc.

190 {
191 CanRenderTiledTexture(this, DlTileMode::kClamp);
192 }

## ◆ TEST_P() [127/545]

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

Definition at line 206 of file aiks_dl_basic_unittests.cc.

206 {
207 CanRenderTiledTexture(this, DlTileMode::kClamp,
208 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
209 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [128/545]

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

Definition at line 202 of file aiks_dl_basic_unittests.cc.

202 {
203 CanRenderTiledTexture(this, DlTileMode::kDecal);
204 }

## ◆ TEST_P() [129/545]

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

Definition at line 198 of file aiks_dl_basic_unittests.cc.

198 {
199 CanRenderTiledTexture(this, DlTileMode::kMirror);
200 }

## ◆ TEST_P() [130/545]

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

Definition at line 194 of file aiks_dl_basic_unittests.cc.

194 {
195 CanRenderTiledTexture(this, DlTileMode::kRepeat);
196 }

## ◆ TEST_P() [131/545]

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

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

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

Definition at line 333 of file aiks_dl_basic_unittests.cc.

333 {
334 DisplayListBuilder builder;
335
336 DlPaint red;
337 red.setColor(DlColor::kRed());
338
339 DlPaint alpha;
340 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
341
342 builder.SaveLayer(std::nullopt, &alpha);
343
344 builder.DrawCircle(DlPoint(125, 125), 125, red);
345
346 builder.Restore();
347
348 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
349 }

## ◆ TEST_P() [134/545]

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

Definition at line 111 of file canvas_unittests.cc.

111 {
112 ContentContext context(GetContext(), nullptr);
113 auto canvas = CreateTestCanvas(context);
114
115 ASSERT_EQ(canvas->GetSaveCount(), 1u);
116 ASSERT_EQ(canvas->Restore(), false);
117
118 canvas->Translate(Size{100, 100});
119 canvas->Save(10);
120 ASSERT_EQ(canvas->GetSaveCount(), 2u);
121 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
122 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
123 ASSERT_TRUE(canvas->Restore());
124 ASSERT_EQ(canvas->GetSaveCount(), 1u);
125 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
126 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
127 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [135/545]

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

Definition at line 129 of file canvas_unittests.cc.

129 {
130 ContentContext context(GetContext(), nullptr);
131 auto canvas = CreateTestCanvas(context);
132
133 Matrix identity;
134 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity);
135 canvas->Translate(Size{100, 100});
136 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(),
137 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
138 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [136/545]

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

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

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

Definition at line 1514 of file aiks_dl_basic_unittests.cc.

1514 {
1515 SetWindowSize({400, 400});
1516 DisplayListBuilder builder;
1517
1518 builder.Scale(GetContentScale().x, GetContentScale().y);
1519
1520 DlPaint paint;
1521 paint.setColor(DlColor::kRed());
1522 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1523
1524 paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1525 DlImageSampling::kLinear));
1526 builder.SaveLayer(std::nullopt, &paint);
1527 // Draw a rectangle that would fully cover the parent pass size, but not
1528 // the subpass that it is rendered in.
1529 paint.setColor(DlColor::kGreen());
1530 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1531 // Draw a bigger rectangle to force the subpass to be bigger.
1532
1533 paint.setColor(DlColor::kRed());
1534 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1535 builder.Restore();
1536
1537 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1538 }

References x.

## ◆ TEST_P() [139/545]

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

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

References impeller::DrawPlaygroundPoint(), impeller::Color::Green(), and impeller::Sigma::sigma.

## ◆ TEST_P() [141/545]

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

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

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

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

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

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

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

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

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

Definition at line 1612 of file aiks_dl_basic_unittests.cc.

1612 {
1613 DisplayListBuilder builder;
1614
1615 // Render a texture directly.
1616 {
1617 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1618
1619 builder.Save();
1620 builder.Translate(100, 200);
1621 builder.Scale(0.5, 0.5);
1622 builder.DrawImage(image, DlPoint(100.0, 100.0),
1623 DlImageSampling::kNearestNeighbor);
1624 builder.Restore();
1625 }
1626
1627 // Render an offscreen rendered texture.
1628 {
1629 DlPaint alpha;
1630 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1631
1632 builder.SaveLayer(std::nullopt, &alpha);
1633
1634 DlPaint paint;
1635 paint.setColor(DlColor::kRed());
1636 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1637 paint.setColor(DlColor::kGreen());
1638 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1639 paint.setColor(DlColor::kBlue());
1640 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1641
1642 builder.Restore();
1643 }
1644
1645 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1646 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [150/545]

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

Definition at line 1793 of file aiks_dl_basic_unittests.cc.

1793 {
1794 auto callback = [&]() -> sk_sp<DisplayList> {
1795 DisplayListBuilder builder;
1796 builder.Scale(GetContentScale().x, GetContentScale().y);
1797
1798 DlPaint alpha;
1799 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1800
1801 auto current = Point{25, 25};
1802 const auto offset = Point{25, 25};
1803 const auto size = Size(100, 100);
1804
1805 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1806 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1807 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1808 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1809
1810 DlPaint stroke_paint;
1811 stroke_paint.setColor(DlColor::kYellow());
1812 stroke_paint.setStrokeWidth(5);
1813 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1814 builder.DrawRect(bounds, stroke_paint);
1815
1816 builder.SaveLayer(bounds, &alpha);
1817
1818 DlPaint paint;
1819 paint.setColor(DlColor::kRed());
1820 builder.DrawRect(
1821 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1822
1823 paint.setColor(DlColor::kGreen());
1824 current += offset;
1825 builder.DrawRect(
1826 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1827
1828 paint.setColor(DlColor::kBlue());
1829 current += offset;
1830 builder.DrawRect(
1831 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1832
1833 builder.Restore();
1834
1835 return builder.Build();
1836 };
1837
1838 ASSERT_TRUE(OpenPlaygroundHere(callback));
1839 }

References impeller::DrawPlaygroundLine(), and impeller::Color::White().

## ◆ TEST_P() [151/545]

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

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

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

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

Definition at line 631 of file aiks_dl_text_unittests.cc.

631 {
632 DisplayListBuilder builder;
633
634 DlPaint paint;
635 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
636 paint.setColor(clear_color);
637 builder.DrawPaint(paint);
638
639 DlMatrix identity = {
640 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
641 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
642 };
643 builder.Save();
644 builder.Transform(identity);
645
646 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
647 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
648 paint.setColor(white);
649 builder.DrawRect(frame, paint);
650
651 builder.Save();
652 builder.ClipRect(frame, DlClipOp::kIntersect);
653
654 DlMatrix rect_xform = {
655 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
656 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
657 };
658 builder.Save();
659 builder.Transform(rect_xform);
660
661 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
662 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
663 paint.setColor(bluish);
664 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
665 builder.DrawRoundRect(rrect, paint);
666
667 builder.Save();
668 builder.ClipRect(rect, DlClipOp::kIntersect);
669 builder.Restore();
670
671 builder.Restore();
672
673 DlMatrix path_xform = {
674 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
675 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
676 };
677 builder.Save();
678 builder.Transform(path_xform);
679
680 DlPathBuilder path_builder;
681 path_builder.MoveTo(DlPoint(87.5, 349.5));
682 path_builder.LineTo(DlPoint(25.0, 29.5));
683 path_builder.LineTo(DlPoint(150.0, 118.0));
684 path_builder.LineTo(DlPoint(25.0, 118.0));
685 path_builder.LineTo(DlPoint(150.0, 29.5));
686 path_builder.Close();
687 DlPath path = path_builder.TakePath();
688
689 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
690 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
691 paint.setColor(fill_color);
692 paint.setDrawStyle(DlDrawStyle::kFill);
693 builder.DrawPath(path, paint);
694
695 paint.setColor(stroke_color);
696 paint.setStrokeWidth(2.0);
697 paint.setDrawStyle(DlDrawStyle::kStroke);
698 builder.DrawPath(path, paint);
699
700 builder.Restore();
701 builder.Restore();
702 builder.Restore();
703
704 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
705 }

## ◆ TEST_P() [155/545]

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

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

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

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

Definition at line 201 of file aiks_dl_atlas_unittests.cc.

201 {
202 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
203
204 std::vector<DlColor> colors;
205 colors.reserve(texture_coordinates.size());
206 for (auto i = 0u; i < texture_coordinates.size(); i++) {
207 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
208 }
209 DlAtlasGeometry geom(
210 atlas->impeller_texture(), transforms.data(), texture_coordinates.data(),
211 colors.data(), transforms.size(), BlendMode::kSrcOver, {}, std::nullopt);
212
213 EXPECT_TRUE(geom.ShouldUseBlend());
214 EXPECT_FALSE(geom.ShouldSkip());
215
216 ContentContext context(GetContext(), nullptr);
217 auto vertex_buffer =
218 geom.CreateBlendVertexBuffer(context.GetTransientsBuffer());
219
220 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
221 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
222 }

References impeller::DlAtlasGeometry::CreateBlendVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSrcOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [159/545]

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

Definition at line 224 of file aiks_dl_atlas_unittests.cc.

224 {
225 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
226
227 std::vector<DlColor> colors;
228 colors.reserve(texture_coordinates.size());
229 for (auto i = 0u; i < texture_coordinates.size(); i++) {
230 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
231 }
232 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
233 texture_coordinates.data(), colors.data(),
234 transforms.size(), BlendMode::kSrc, {}, std::nullopt);
235
236 // Src blend mode means that colors would be ignored, even if provided.
237 EXPECT_FALSE(geom.ShouldUseBlend());
238 EXPECT_FALSE(geom.ShouldSkip());
239 }

References impeller::kSrc, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [160/545]

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

Definition at line 183 of file aiks_dl_atlas_unittests.cc.

183 {
184 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
185
186 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
187 texture_coordinates.data(), nullptr, transforms.size(),
188 BlendMode::kSrcOver, {}, std::nullopt);
189
190 EXPECT_FALSE(geom.ShouldUseBlend());
191 EXPECT_FALSE(geom.ShouldSkip());
192
193 ContentContext context(GetContext(), nullptr);
194 auto vertex_buffer =
195 geom.CreateSimpleVertexBuffer(context.GetTransientsBuffer());
196
197 EXPECT_EQ(vertex_buffer.index_type, IndexType::kNone);
198 EXPECT_EQ(vertex_buffer.vertex_count, texture_coordinates.size() * 6);
199 }

References impeller::DlAtlasGeometry::CreateSimpleVertexBuffer(), impeller::ContentContext::GetTransientsBuffer(), impeller::kNone, impeller::kSrcOver, impeller::DlAtlasGeometry::ShouldSkip(), and impeller::DlAtlasGeometry::ShouldUseBlend().

## ◆ TEST_P() [161/545]

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

Definition at line 241 of file aiks_dl_atlas_unittests.cc.

241 {
242 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
243
244 std::vector<DlColor> colors;
245 colors.reserve(texture_coordinates.size());
246 for (auto i = 0u; i < texture_coordinates.size(); i++) {
247 colors.push_back(DlColor::ARGB(0.5, 1, 1, 1));
248 }
249 DlAtlasGeometry geom(atlas->impeller_texture(), transforms.data(),
250 texture_coordinates.data(), colors.data(),
251 transforms.size(), BlendMode::kClear, {}, std::nullopt);
252 EXPECT_TRUE(geom.ShouldSkip());
253 }

References impeller::kClear, and impeller::DlAtlasGeometry::ShouldSkip().

## ◆ TEST_P() [162/545]

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

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

Definition at line 137 of file aiks_dl_atlas_unittests.cc.

137 {
138 DisplayListBuilder builder;
139 // Draws the image as four squares stiched together.
140 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
141
142 builder.Scale(0.25, 0.25);
143 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
144 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
145 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
146
147 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
148 }

## ◆ TEST_P() [164/545]

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

Definition at line 60 of file aiks_dl_atlas_unittests.cc.

60 {
61 DisplayListBuilder builder;
62 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
63
64 builder.Scale(GetContentScale().x, GetContentScale().y);
65 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
66 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
67 DlImageSampling::kNearestNeighbor, nullptr);
68
69 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
70 }

References x.

## ◆ TEST_P() [165/545]

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

Definition at line 120 of file aiks_dl_atlas_unittests.cc.

120 {
121 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
122 auto size = atlas->impeller_texture()->GetSize();
123 std::vector<DlRect> texture_coordinates = {
124 DlRect::MakeLTRB(0, 0, size.width, size.height)};
125 std::vector<RSTransform> transforms = {MakeTranslation(0, 0)};
126
127 DisplayListBuilder builder;
128 builder.Scale(GetContentScale().x, GetContentScale().y);
129 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
130 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
131 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
132
133 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
134 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [166/545]

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

Definition at line 166 of file aiks_dl_atlas_unittests.cc.

166 {
167 DisplayListBuilder builder;
168 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
169 PixelFormat::kB10G10R10A10XR);
170
171 // Draws the image as four squares stiched together.
172 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
173 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
174 DlColor::kBlue(), DlColor::kYellow()};
175
176 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
177 colors.data(), /*count=*/4, DlBlendMode::kPlus,
178 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
179
180 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
181 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [167/545]

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

Definition at line 72 of file aiks_dl_atlas_unittests.cc.

72 {
73 DisplayListBuilder builder;
74 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
75
76 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
77 DlColor::kBlue(), DlColor::kYellow()};
78
79 builder.Scale(GetContentScale().x, GetContentScale().y);
80 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
81 colors.data(), /*count=*/4, DlBlendMode::kModulate,
82 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
83
84 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
85 }

References x.

## ◆ TEST_P() [168/545]

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

Definition at line 151 of file aiks_dl_atlas_unittests.cc.

151 {
152 DisplayListBuilder builder;
153 // Draws the image as four squares stiched together.
154 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
155 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
156 DlColor::kBlue(), DlColor::kYellow()};
157
158 builder.Scale(0.25, 0.25);
159 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
160 colors.data(), /*count=*/4, DlBlendMode::kModulate,
161 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
162
163 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
164 }

## ◆ TEST_P() [169/545]

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

Definition at line 320 of file aiks_dl_atlas_unittests.cc.

320 {
321 DisplayListBuilder builder;
322 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
323
324 std::vector<DlColor> colors = {DlColor::kDarkGrey(), DlColor::kBlack(),
325 DlColor::kLightGrey(), DlColor::kWhite()};
326
327 builder.Scale(GetContentScale().x, GetContentScale().y);
328 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
329 colors.data(), /*count=*/4, DlBlendMode::kColorBurn,
330 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
331
332 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
333 }

References x.

## ◆ TEST_P() [170/545]

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

Definition at line 87 of file aiks_dl_atlas_unittests.cc.

87 {
88 DisplayListBuilder builder;
89 // Draws the image as four squares stiched together.
90 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
91
92 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
93 DlColor::kBlue(), DlColor::kYellow()};
94
95 builder.Scale(GetContentScale().x, GetContentScale().y);
96 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
97 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
98 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
99
100 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
101 }

References x.

## ◆ TEST_P() [171/545]

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

Definition at line 103 of file aiks_dl_atlas_unittests.cc.

103 {
104 DisplayListBuilder builder;
105 // Draws the image as four squares stiched together slightly
106 // opaque
107 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
108
109 DlPaint paint;
110 paint.setAlpha(128);
111 builder.Scale(GetContentScale().x, GetContentScale().y);
112 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
113 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
114 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
115 &paint);
116
117 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
118 }

References x.

## ◆ TEST_P() [172/545]

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

Definition at line 229 of file aiks_dl_basic_unittests.cc.

229 {
230 DisplayListBuilder builder;
231 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
232
233 // Use a source rect that is partially outside the bounds of the image.
234 auto source_rect = DlRect::MakeXYWH(
235 image->GetSize().width * 0.25f, image->GetSize().height * 0.4f,
236 image->GetSize().width, image->GetSize().height);
237
238 auto dest_rect = DlRect::MakeXYWH(100, 100, 600, 600);
239
240 DlPaint paint;
241 paint.setColor(DlColor::kMidGrey());
242 builder.DrawRect(dest_rect, paint);
243
244 builder.DrawImageRect(image, source_rect, dest_rect,
245 DlImageSampling::kNearestNeighbor);
246 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
247 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [173/545]

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

Definition at line 255 of file aiks_dl_atlas_unittests.cc.

255 {
256 sk_sp<DlImageImpeller> texture =
257 DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
258
259 DisplayListBuilder builder;
260 DlPaint paint = DlPaint().setColorFilter(DlColorFilter::MakeBlend(
261 DlColor::kRed().withAlphaF(0.4), DlBlendMode::kSrcOver));
262
263 DlMatrix filter_matrix = DlMatrix();
264 auto filter = flutter::DlMatrixImageFilter(filter_matrix,
265 flutter::DlImageSampling::kLinear);
266 DlPaint paint_with_filter = paint;
267 paint_with_filter.setImageFilter(&filter);
268
269 // Compare porter-duff blend modes.
270 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
271 // Uses image filter to disable atlas conversion.
272 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
273 DlRect::MakeLTRB(0, 0, 500, 500), {},
274 &paint_with_filter);
275
276 // Uses atlas conversion.
277 builder.Translate(600, 0);
278 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
279 DlRect::MakeLTRB(0, 0, 500, 500), {}, &paint);
280
281 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
282 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [174/545]

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

Definition at line 284 of file aiks_dl_atlas_unittests.cc.

284 {
285 sk_sp<DlImageImpeller> texture =
286 DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
287
288 DisplayListBuilder builder;
289 static const constexpr ColorMatrix kColorInversion = {
290 .array = {
291 -1.0, 0, 0, 1.0, 0, //
292 0, -1.0, 0, 1.0, 0, //
293 0, 0, -1.0, 1.0, 0, //
294 1.0, 1.0, 1.0, 1.0, 0 //
295 }};
296 DlPaint paint = DlPaint().setColorFilter(
297 DlColorFilter::MakeMatrix(kColorInversion.array));
298
299 DlMatrix filter_matrix = DlMatrix();
300 auto filter = flutter::DlMatrixImageFilter(filter_matrix,
301 flutter::DlImageSampling::kLinear);
302 DlPaint paint_with_filter = paint;
303 paint_with_filter.setImageFilter(&filter);
304
305 // Compare inverting color matrix filter.
306 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
307 // Uses image filter to disable atlas conversion.
308 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
309 DlRect::MakeLTRB(0, 0, 500, 500), {},
310 &paint_with_filter);
311
312 // Uses atlas conversion.
313 builder.Translate(600, 0);
314 builder.DrawImageRect(texture, DlRect::MakeSize(texture->GetSize()),
315 DlRect::MakeLTRB(0, 0, 500, 500), {}, &paint);
316
317 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
318 }
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() [175/545]

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

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

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

Definition at line 63 of file aiks_dl_runtime_effect_unittests.cc.

63 {
64 struct FragUniforms {
65 Size size;
66 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
67 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
68 uniform_data->resize(sizeof(FragUniforms));
69 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
70
71 DlPaint paint;
72 paint.setColorSource(
73 MakeRuntimeEffect(this, "gradient.frag.iplr", uniform_data));
74
75 DisplayListBuilder builder;
76 builder.Save();
77 builder.Scale(GetContentScale().x, GetContentScale().y);
78 builder.DrawPaint(paint);
79 builder.Restore();
80
81 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
82 }

References impeller::TSize< Scalar >::MakeWH(), and x.

## ◆ TEST_P() [178/545]

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

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

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

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

Definition at line 507 of file aiks_dl_text_unittests.cc.

507 {
508 DisplayListBuilder builder;
509
510 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
511 0.0, 1.0, 0.0, 0.0, //
512 0.0, 0.0, 1.0, 0.01, //
513 0.0, 0.0, 0.0, 1.0) * //
514 Matrix::MakeRotationY({Degrees{10}});
515
516 builder.Transform(matrix);
517
518 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
519 "Roboto-Regular.ttf"));
520 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
521 }

References RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [182/545]

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

Definition at line 523 of file aiks_dl_text_unittests.cc.

523 {
524 DisplayListBuilder builder;
525
526 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
527 0.0, 1.0, 0.0, 0.0, //
528 0.0, 0.0, 1.0, 0.01, //
529 0.0, 0.0, 0.0, 1.0) * //
530 Matrix::MakeRotationY({Degrees{10}});
531
532 DlPaint save_paint;
533 DlRect window_bounds =
534 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
535 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
536 builder.SaveLayer(window_bounds, &save_paint);
537 builder.Transform(matrix);
538
539 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
540 "Roboto-Regular.ttf"));
541
542 builder.Restore();
543 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
544 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [183/545]

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

Definition at line 271 of file aiks_dl_vertices_unittests.cc.

271 {
272 auto texture = CreateTextureForFixture("embarcadero.jpg");
273 auto dl_image = DlImageImpeller::Make(texture);
274 std::vector<DlPoint> positions = {
275 DlPoint(100, 300),
276 DlPoint(200, 100),
277 DlPoint(300, 300),
278 };
279 std::vector<DlPoint> texture_coordinates = {
280 DlPoint(0, 0),
281 DlPoint(100, 200),
282 DlPoint(200, 100),
283 };
284
285 auto vertices = flutter::DlVertices::Make(
286 flutter::DlVertexMode::kTriangles, 3, positions.data(),
287 texture_coordinates.data(), /*colors=*/nullptr);
288
289 flutter::DisplayListBuilder builder;
290 flutter::DlPaint paint;
291
292 auto image_source = flutter::DlColorSource::MakeImage(
293 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
294
295 paint.setColorSource(image_source);
296 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
297
298 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
299 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [184/545]

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

Definition at line 301 of file aiks_dl_vertices_unittests.cc.

302 {
303 auto texture = CreateTextureForFixture("embarcadero.jpg");
304 auto dl_image = DlImageImpeller::Make(texture);
305 std::vector<DlPoint> positions = {
306 DlPoint(100, 300),
307 DlPoint(200, 100),
308 DlPoint(300, 300),
309 };
310 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
311 flutter::DlColor::kGreen(),
312 flutter::DlColor::kWhite()};
313 std::vector<DlPoint> texture_coordinates = {
314 DlPoint(0, 0),
315 DlPoint(100, 200),
316 DlPoint(200, 100),
317 };
318
319 auto vertices = flutter::DlVertices::Make(
320 flutter::DlVertexMode::kTriangles, 3, positions.data(),
321 texture_coordinates.data(), colors.data());
322
323 flutter::DisplayListBuilder builder;
324 flutter::DlPaint paint;
325
326 auto image_source = flutter::DlColorSource::MakeImage(
327 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
328
329 paint.setColorSource(image_source);
330 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
331
332 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
333 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [185/545]

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

Definition at line 284 of file canvas_unittests.cc.

284 {
285 RenderCallback callback = [&](RenderTarget& render_target) {
286 ContentContext context(GetContext(), nullptr);
287 Canvas canvas(context, render_target, true, false);
288
289 std::vector<flutter::DlPoint> vertex_coordinates = {
290 flutter::DlPoint(0, 0),
291 flutter::DlPoint(600, 0),
292 flutter::DlPoint(0, 600),
293 };
294 std::vector<flutter::DlPoint> texture_coordinates = {
295 flutter::DlPoint(0, 0),
296 flutter::DlPoint(500, 0),
297 flutter::DlPoint(0, 500),
298 };
299 std::vector<uint16_t> indices = {0, 1, 2};
300 flutter::DlVertices::Builder vertices_builder(
301 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
302 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
303 vertices_builder.store_vertices(vertex_coordinates.data());
304 vertices_builder.store_indices(indices.data());
305 vertices_builder.store_texture_coordinates(texture_coordinates.data());
306 auto vertices = vertices_builder.build();
307
308 // The start and end points of the gradient form an empty rectangle.
309 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
310 flutter::DlColor::kRed()};
311 std::vector<Scalar> stops = {0.0, 1.0};
312 auto gradient = flutter::DlColorSource::MakeLinear(
313 {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
314 flutter::DlTileMode::kClamp);
315
316 Paint paint;
317 paint.color_source = gradient.get();
318 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
319 BlendMode::kSrcOver, paint);
320
321 canvas.EndReplay();
322 return true;
323 };
324
325 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
326 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, and impeller::Playground::OpenPlaygroundHere().

## ◆ TEST_P() [186/545]

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

Definition at line 210 of file aiks_dl_vertices_unittests.cc.

210 {
211 std::vector<DlPoint> positions = {
212 DlPoint(100, 300),
213 DlPoint(200, 100),
214 DlPoint(300, 300),
215 };
216
217 auto vertices = flutter::DlVertices::Make(
218 flutter::DlVertexMode::kTriangles, 3, positions.data(),
219 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
220
221 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
222 flutter::DlColor::kRed()};
223 const float stops[2] = {0.0, 1.0};
224
225 auto linear = flutter::DlColorSource::MakeLinear(
226 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
227 flutter::DlTileMode::kRepeat);
228
229 flutter::DisplayListBuilder builder;
230 flutter::DlPaint paint;
231
232 paint.setColorSource(linear);
233 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
234
235 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
236 }

## ◆ TEST_P() [187/545]

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

Definition at line 238 of file aiks_dl_vertices_unittests.cc.

238 {
239 std::vector<DlPoint> positions = {
240 DlPoint(100, 300),
241 DlPoint(200, 100),
242 DlPoint(300, 300),
243 };
244 std::vector<DlPoint> texture_coordinates = {
245 DlPoint(300, 100),
246 DlPoint(100, 200),
247 DlPoint(300, 300),
248 };
249
250 auto vertices = flutter::DlVertices::Make(
251 flutter::DlVertexMode::kTriangles, 3, positions.data(),
252 texture_coordinates.data(), /*colors=*/nullptr);
253
254 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
255 flutter::DlColor::kRed()};
256 const float stops[2] = {0.0, 1.0};
257
258 auto linear = flutter::DlColorSource::MakeLinear(
259 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
260 flutter::DlTileMode::kRepeat);
261
262 flutter::DisplayListBuilder builder;
263 flutter::DlPaint paint;
264
265 paint.setColorSource(linear);
266 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
267
268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
269 }

## ◆ TEST_P() [188/545]

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

Definition at line 358 of file aiks_dl_vertices_unittests.cc.

358 {
359 std::vector<DlPoint> positions = {
360 DlPoint(100, 300),
361 DlPoint(200, 100),
362 DlPoint(300, 300),
363 DlPoint(200, 500),
364 };
365 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
366 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
367 std::vector<flutter::DlColor> colors = {color, color, color, color};
368
369 auto vertices = flutter::DlVertices::Make(
370 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
371 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
372 indices.data());
373
374 flutter::DisplayListBuilder builder;
375 flutter::DlPaint paint;
376 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
377 paint.setColor(flutter::DlColor::kRed());
378
379 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
380 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
381
382 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
383 }

## ◆ TEST_P() [189/545]

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

Definition at line 335 of file aiks_dl_vertices_unittests.cc.

335 {
336 std::vector<DlPoint> positions = {
337 DlPoint(100, 300),
338 DlPoint(200, 100),
339 DlPoint(300, 300),
340 DlPoint(200, 500),
341 };
342 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
343
344 auto vertices = flutter::DlVertices::Make(
345 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
346 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
347 indices.data());
348
349 flutter::DisplayListBuilder builder;
350 flutter::DlPaint paint;
351
352 paint.setColor(flutter::DlColor::kRed());
353 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
354
355 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
356 }

## ◆ TEST_P() [190/545]

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

Definition at line 184 of file aiks_dl_vertices_unittests.cc.

184 {
185 // Use negative coordinates and then scale the transform by -1, -1 to make
186 // sure coverage is taking the transform into account.
187 std::vector<DlPoint> positions = {
188 DlPoint(-100, -300),
189 DlPoint(-200, -100),
190 DlPoint(-300, -300),
191 };
192 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
193 flutter::DlColor::kGreen(),
194 flutter::DlColor::kWhite()};
195
196 auto vertices = flutter::DlVertices::Make(
197 flutter::DlVertexMode::kTriangles, 3, positions.data(),
198 /*texture_coordinates=*/nullptr, colors.data());
199
200 flutter::DisplayListBuilder builder;
201 flutter::DlPaint paint;
202
203 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
204 builder.Scale(-1, -1);
205 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
206
207 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
208 }

## ◆ TEST_P() [191/545]

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

Definition at line 417 of file aiks_dl_vertices_unittests.cc.

417 {
418 std::vector<DlPoint> positions_lt = {
419 DlPoint(0, 0), //
420 DlPoint(50, 0), //
421 DlPoint(0, 50), //
422 DlPoint(50, 50), //
423 };
424
425 auto vertices_lt = flutter::DlVertices::Make(
426 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
427 positions_lt.data(),
428 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
429 /*index_count=*/0,
430 /*indices=*/nullptr);
431
432 std::vector<DlPoint> positions_rt = {
433 DlPoint(50, 0), //
434 DlPoint(100, 0), //
435 DlPoint(50, 50), //
436 DlPoint(100, 50), //
437 };
438
439 auto vertices_rt = flutter::DlVertices::Make(
440 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
441 positions_rt.data(),
442 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
443 /*index_count=*/0,
444 /*indices=*/nullptr);
445
446 std::vector<DlPoint> positions_lb = {
447 DlPoint(0, 50), //
448 DlPoint(50, 50), //
449 DlPoint(0, 100), //
450 DlPoint(50, 100), //
451 };
452
453 auto vertices_lb = flutter::DlVertices::Make(
454 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
455 positions_lb.data(),
456 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
457 /*index_count=*/0,
458 /*indices=*/nullptr);
459
460 std::vector<DlPoint> positions_rb = {
461 DlPoint(50, 50), //
462 DlPoint(100, 50), //
463 DlPoint(50, 100), //
464 DlPoint(100, 100), //
465 };
466
467 auto vertices_rb = flutter::DlVertices::Make(
468 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
469 positions_rb.data(),
470 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
471 /*index_count=*/0,
472 /*indices=*/nullptr);
473
474 flutter::DisplayListBuilder builder;
475 flutter::DlPaint paint;
476 flutter::DlPaint rect_paint;
477 rect_paint.setColor(DlColor::kBlue());
478
479 auto runtime_stages =
480 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
481
482 auto runtime_stage =
483 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
484 ASSERT_TRUE(runtime_stage);
485
486 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
487 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
488 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
489 runtime_effect, {}, uniform_data);
490
491 paint.setColorSource(color_source);
492
493 builder.Scale(GetContentScale().x, GetContentScale().y);
494 builder.Save();
495 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), rect_paint);
496 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
497 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
498 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
499 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
500 builder.Restore();
501
502 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
503 }

References impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [192/545]

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

Definition at line 507 of file aiks_dl_vertices_unittests.cc.

508 {
509 std::vector<DlPoint> positions_lt = {
510 DlPoint(200, 200), //
511 DlPoint(250, 200), //
512 DlPoint(200, 250), //
513 DlPoint(250, 250), //
514 };
515
516 auto vertices = flutter::DlVertices::Make(
517 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
518 positions_lt.data(),
519 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
520 /*index_count=*/0,
521 /*indices=*/nullptr);
522
523 flutter::DisplayListBuilder builder;
524 flutter::DlPaint paint;
525 flutter::DlPaint rect_paint;
526 rect_paint.setColor(DlColor::kBlue());
527
528 auto runtime_stages =
529 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
530
531 auto runtime_stage =
532 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
533 ASSERT_TRUE(runtime_stage);
534
535 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
536 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
537
538 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
539 uniform_data->resize(rect_data.size() * sizeof(Rect));
540 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
541
542 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
543 runtime_effect, {}, uniform_data);
544
545 paint.setColorSource(color_source);
546
547 builder.Scale(GetContentScale().x, GetContentScale().y);
548 builder.DrawRect(DlRect::MakeLTRB(200, 200, 250, 250), rect_paint);
549 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
550
551 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
552 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [193/545]

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

Definition at line 328 of file canvas_unittests.cc.

328 {
329 auto runtime_stages =
330 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
331
332 auto runtime_stage =
333 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
334 ASSERT_TRUE(runtime_stage);
335
336 auto runtime_effect = flutter::DlRuntimeEffect::MakeImpeller(runtime_stage);
337 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
338 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
339 runtime_effect, {}, uniform_data);
340
341 RenderCallback callback = [&](RenderTarget& render_target) {
342 ContentContext context(GetContext(), nullptr);
343 Canvas canvas(context, render_target, true, false);
344
345 std::vector<flutter::DlPoint> vertex_coordinates = {
346 flutter::DlPoint(100, 100),
347 flutter::DlPoint(300, 100),
348 flutter::DlPoint(100, 300),
349 };
350 // The bounding box of the texture coordinates is empty.
351 std::vector<flutter::DlPoint> texture_coordinates = {
352 flutter::DlPoint(0, 0),
353 flutter::DlPoint(0, 100),
354 flutter::DlPoint(0, 0),
355 };
356 std::vector<uint16_t> indices = {0, 1, 2};
357 flutter::DlVertices::Builder vertices_builder(
358 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
359 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
360 vertices_builder.store_vertices(vertex_coordinates.data());
361 vertices_builder.store_indices(indices.data());
362 vertices_builder.store_texture_coordinates(texture_coordinates.data());
363 auto vertices = vertices_builder.build();
364
365 Paint paint;
366 paint.color_source = color_source.get();
367 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
368 BlendMode::kSrcOver, paint);
369
370 canvas.EndReplay();
371 return true;
372 };
373
374 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
375 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, impeller::Playground::OpenPlaygroundHere(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [194/545]

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

Definition at line 385 of file aiks_dl_vertices_unittests.cc.

385 {
386 std::vector<DlPoint> positions = {
387 DlPoint(100, 300),
388 DlPoint(200, 100),
389 DlPoint(300, 300),
390 DlPoint(200, 500),
391 };
392 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
393
394 auto vertices = flutter::DlVertices::Make(
395 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
396 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
397 indices.data());
398
399 EXPECT_EQ(vertices->GetBounds(), DlRect::MakeLTRB(100, 100, 300, 500));
400
401 flutter::DisplayListBuilder builder;
402 flutter::DlPaint paint;
403 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
404 paint.setColor(flutter::DlColor::kRed());
405
406 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
407 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
408
409 AiksContext renderer(GetContext(), nullptr);
410 std::shared_ptr<Texture> image =
411 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
412 EXPECT_TRUE(image);
413 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [195/545]

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

Definition at line 1540 of file aiks_dl_basic_unittests.cc.

1540 {
1541 DisplayListBuilder builder;
1542 builder.Scale(GetContentScale().x, GetContentScale().y);
1543
1544 DlPaint paint;
1545 paint.setColor(DlColor::kRed());
1546 builder.DrawPaint(paint);
1547 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1548 paint.setColor(DlColor::kBlue());
1549 builder.SaveLayer(std::nullopt, &paint);
1550 builder.Restore();
1551
1552 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1553 }

References x.

## ◆ TEST_P() [196/545]

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

Definition at line 1555 of file aiks_dl_basic_unittests.cc.

1555 {
1556 DisplayListBuilder builder;
1557 builder.Scale(GetContentScale().x, GetContentScale().y);
1558 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1559 builder.DrawImage(image, DlPoint(10, 10), {});
1560 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1561
1562 DlPaint paint;
1563 paint.setBlendMode(DlBlendMode::kClear);
1564 builder.SaveLayer(std::nullopt, &paint);
1565 builder.Restore();
1566
1567 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1568 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [197/545]

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

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

Definition at line 1957 of file aiks_dl_basic_unittests.cc.

1957 {
1958 DisplayListBuilder builder;
1959
1960 builder.Scale(GetContentScale().x, GetContentScale().y);
1961 DlPaint paint;
1962 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1963
1964 DlPaint save_paint;
1965 save_paint.setColor(DlColor::kWhite());
1966 builder.DrawPaint(save_paint);
1967
1968 paint.setColor(DlColor::kBlue());
1969 for (int i = 0; i < 5; i++) {
1970 Scalar y = i * 125;
1971 Scalar y_radius = i * 15;
1972 for (int j = 0; j < 5; j++) {
1973 Scalar x = j * 125;
1974 Scalar x_radius = j * 15;
1975 builder.DrawRoundRect(
1976 DlRoundRect::MakeRectXY(
1977 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
1978 x_radius, y_radius),
1979 paint);
1980 }
1981 }
1982
1983 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1984 }

References x.

## ◆ TEST_P() [199/545]

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

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

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

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

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

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

Definition at line 791 of file aiks_dl_basic_unittests.cc.

791 {
792 DisplayListBuilder builder;
793 builder.Scale(GetContentScale().x, GetContentScale().y);
794 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
795
796 DlPaint paint;
797 paint.setColor(DlColor::kBlue());
798
799 RenderArcFarm(builder, paint,
800 {
801 .use_center = false,
802 .full_circles = false,
803 });
804
805 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
806 }

References x.

## ◆ TEST_P() [205/545]

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

Definition at line 808 of file aiks_dl_basic_unittests.cc.

808 {
809 DisplayListBuilder builder;
810 builder.Scale(GetContentScale().x, GetContentScale().y);
811 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
812
813 DlPaint paint;
814 paint.setColor(DlColor::kBlue());
815
816 RenderArcFarm(builder, paint,
817 {
818 .use_center = true,
819 .full_circles = false,
820 });
821
822 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
823 }

References x.

## ◆ TEST_P() [206/545]

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

Definition at line 562 of file aiks_dl_basic_unittests.cc.

562 {
563 DisplayListBuilder builder;
564 builder.Scale(GetContentScale().x, GetContentScale().y);
565 DlPaint paint;
566 const int color_count = 3;
567 DlColor colors[color_count] = {
568 DlColor::kBlue(),
569 DlColor::kGreen(),
570 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
571 };
572
573 paint.setColor(DlColor::kWhite());
574 builder.DrawPaint(paint);
575
576 int c_index = 0;
577 int radius = 600;
578 while (radius > 0) {
579 paint.setColor(colors[(c_index++) % color_count]);
580 builder.DrawCircle(DlPoint(10, 10), radius, paint);
581 if (radius > 30) {
582 radius -= 10;
583 } else {
584 radius -= 2;
585 }
586 }
587
588 DlColor gradient_colors[7] = {
589 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
590 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
591 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
592 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
593 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
594 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
595 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
596 };
597 DlScalar stops[7] = {
598 0.0,
599 (1.0 / 6.0) * 1,
600 (1.0 / 6.0) * 2,
601 (1.0 / 6.0) * 3,
602 (1.0 / 6.0) * 4,
603 (1.0 / 6.0) * 5,
604 1.0,
605 };
606 auto texture = CreateTextureForFixture("airplane.jpg",
607 /*enable_mipmapping=*/true);
608 auto image = DlImageImpeller::Make(texture);
609
610 paint.setColorSource(DlColorSource::MakeRadial(
611 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
612 builder.DrawCircle(DlPoint(500, 600), 100, paint);
613
614 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
615 paint.setColorSource(DlColorSource::MakeImage(
616 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
617 DlImageSampling::kNearestNeighbor, &local_matrix));
618 builder.DrawCircle(DlPoint(800, 300), 100, paint);
619
620 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
621 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [207/545]

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

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 int long_radius = 600;
705 int short_radius = 600;
706 while (long_radius > 0 && short_radius > 0) {
707 paint.setColor(colors[(c_index++) % color_count]);
708 builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
709 long_radius * 2, short_radius * 2),
710 paint);
711 builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
712 short_radius * 2, long_radius * 2),
713 paint);
714 if (short_radius > 30) {
715 short_radius -= 10;
716 long_radius -= 5;
717 } else {
718 short_radius -= 2;
719 long_radius -= 1;
720 }
721 }
722
723 DlColor gradient_colors[7] = {
724 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
725 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
726 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
727 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
728 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
729 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
730 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
731 };
732 DlScalar stops[7] = {
733 0.0,
734 (1.0 / 6.0) * 1,
735 (1.0 / 6.0) * 2,
736 (1.0 / 6.0) * 3,
737 (1.0 / 6.0) * 4,
738 (1.0 / 6.0) * 5,
739 1.0,
740 };
741 auto texture = CreateTextureForFixture("airplane.jpg",
742 /*enable_mipmapping=*/true);
743 auto image = DlImageImpeller::Make(texture);
744
745 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
746
747 paint.setColorSource(DlColorSource::MakeRadial(
748 DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
749 builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
750 builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
751
752 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
753 paint.setColorSource(DlColorSource::MakeImage(
754 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
755 DlImageSampling::kNearestNeighbor, &local_matrix));
756 builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
757 builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
758
759 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
760 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [208/545]

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

Definition at line 1691 of file aiks_dl_basic_unittests.cc.

1691 {
1692 DisplayListBuilder builder;
1693 builder.Scale(GetContentScale().x, GetContentScale().y);
1694
1695 DlPaint paint;
1696 const int color_count = 3;
1697 DlColor colors[color_count] = {
1698 DlColor::kBlue(),
1699 DlColor::kGreen(),
1700 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1701 };
1702
1703 paint.setColor(DlColor::kWhite());
1704 builder.DrawPaint(paint);
1705
1706 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1707 const DlPaint& paint) {
1708 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1709 };
1710
1711 int c_index = 0;
1712 for (int i = 0; i < 4; i++) {
1713 for (int j = 0; j < 4; j++) {
1714 paint.setColor(colors[(c_index++) % color_count]);
1715 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1716 i * 5 + 10, j * 5 + 10, paint);
1717 }
1718 }
1719 paint.setColor(colors[(c_index++) % color_count]);
1720 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1721 paint.setColor(colors[(c_index++) % color_count]);
1722 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1723
1724 std::vector<DlColor> gradient_colors = {
1725 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1726 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1727 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1728 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1729 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1730 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1731 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1732 std::vector<Scalar> stops = {
1733 0.0,
1734 (1.0 / 6.0) * 1,
1735 (1.0 / 6.0) * 2,
1736 (1.0 / 6.0) * 3,
1737 (1.0 / 6.0) * 4,
1738 (1.0 / 6.0) * 5,
1739 1.0,
1740 };
1741 auto texture = DlImageImpeller::Make(
1742 CreateTextureForFixture("airplane.jpg",
1743 /*enable_mipmapping=*/true));
1744
1745 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1746 paint.setColorSource(DlColorSource::MakeRadial(
1747 /*center=*/DlPoint(550, 550),
1748 /*radius=*/75,
1749 /*stop_count=*/gradient_colors.size(),
1750 /*colors=*/gradient_colors.data(),
1751 /*stops=*/stops.data(),
1752 /*tile_mode=*/DlTileMode::kMirror));
1753 for (int i = 1; i <= 10; i++) {
1754 int j = 11 - i;
1755 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1756 550 + i * 20, 550 + j * 20),
1757 i * 10, j * 10, paint);
1758 }
1759 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1760 paint.setColorSource(DlColorSource::MakeRadial(
1761 /*center=*/DlPoint(200, 650),
1762 /*radius=*/75,
1763 /*stop_count=*/gradient_colors.size(),
1764 /*colors=*/gradient_colors.data(),
1765 /*stops=*/stops.data(),
1766 /*tile_mode=*/DlTileMode::kMirror));
1767 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1768 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1769
1770 auto matrix = DlMatrix::MakeTranslation({520, 20});
1771 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1772 paint.setColorSource(DlColorSource::MakeImage(
1773 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1774 DlImageSampling::kMipmapLinear, &matrix));
1775 for (int i = 1; i <= 10; i++) {
1776 int j = 11 - i;
1777 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1778 720 + i * 20, 220 + j * 20),
1779 i * 10, j * 10, paint);
1780 }
1781 matrix = DlMatrix::MakeTranslation({800, 300});
1782 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1783 paint.setColorSource(DlColorSource::MakeImage(
1784 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1785 DlImageSampling::kMipmapLinear, &matrix));
1786
1787 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1788 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1789
1790 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1791 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [209/545]

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

Definition at line 1095 of file aiks_dl_basic_unittests.cc.

1095 {
1096 DisplayListBuilder builder;
1097 builder.Scale(GetContentScale().x, GetContentScale().y);
1098 DlPaint paint;
1099 const int color_count = 3;
1100 DlColor colors[color_count] = {
1101 DlColor::kBlue(),
1102 DlColor::kGreen(),
1103 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
1104 };
1105
1106 paint.setColor(DlColor::kWhite());
1107 builder.DrawPaint(paint);
1108
1109 int c_index = 0;
1110 for (int i = 0; i < 4; i++) {
1111 for (int j = 0; j < 4; j++) {
1112 paint.setColor(colors[(c_index++) % color_count]);
1113 builder.DrawRoundRect(
1114 DlRoundRect::MakeRectXY(
1115 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
1116 i * 5 + 10, j * 5 + 10),
1117 paint);
1118 }
1119 }
1120 paint.setColor(colors[(c_index++) % color_count]);
1121 builder.DrawRoundRect(
1122 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
1123 paint);
1124 paint.setColor(colors[(c_index++) % color_count]);
1125 builder.DrawRoundRect(
1126 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
1127 paint);
1128
1129 DlColor gradient_colors[7] = {
1130 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1131 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1132 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1133 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1134 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1135 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1136 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
1137 };
1138 DlScalar stops[7] = {
1139 0.0,
1140 (1.0 / 6.0) * 1,
1141 (1.0 / 6.0) * 2,
1142 (1.0 / 6.0) * 3,
1143 (1.0 / 6.0) * 4,
1144 (1.0 / 6.0) * 5,
1145 1.0,
1146 };
1147 auto texture = CreateTextureForFixture("airplane.jpg",
1148 /*enable_mipmapping=*/true);
1149 auto image = DlImageImpeller::Make(texture);
1150
1151 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1152 paint.setColorSource(DlColorSource::MakeRadial(
1153 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1154 for (int i = 1; i <= 10; i++) {
1155 int j = 11 - i;
1156 builder.DrawRoundRect(
1157 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1158 550 + i * 20, 550 + j * 20),
1159 i * 10, j * 10),
1160 paint);
1161 }
1162
1163 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1164 paint.setColorSource(DlColorSource::MakeRadial(
1165 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
1166 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1167 builder.DrawRoundRect(
1168 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
1169 paint);
1170 builder.DrawRoundRect(
1171 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
1172 paint);
1173
1174 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1175 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
1176 paint.setColorSource(DlColorSource::MakeImage(
1177 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1178 DlImageSampling::kNearestNeighbor, &local_matrix));
1179 for (int i = 1; i <= 10; i++) {
1180 int j = 11 - i;
1181 builder.DrawRoundRect(
1182 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1183 720 + i * 20, 220 + j * 20),
1184 i * 10, j * 10),
1185 paint);
1186 }
1187
1188 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1189 local_matrix = DlMatrix::MakeTranslation({800, 300});
1190 paint.setColorSource(DlColorSource::MakeImage(
1191 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
1192 DlImageSampling::kNearestNeighbor, &local_matrix));
1193 builder.DrawRoundRect(
1194 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
1195 paint);
1196 builder.DrawRoundRect(
1197 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
1198 paint);
1199
1200 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1201 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [210/545]

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

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

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

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

Definition at line 1604 of file aiks_dl_basic_unittests.cc.

1604 {
1605 PixelFormat pixel_format =
1606 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1607 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1608 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1609 << "pixel format: " << PixelFormatToString(pixel_format);
1610 }
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() [214/545]

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

Definition at line 1599 of file aiks_dl_basic_unittests.cc.

1599 {
1600 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1601 PixelFormat::kB10G10R10A10XR);
1602 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [215/545]

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

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

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAnimatedBackdrop |
| ) |  |

Definition at line 851 of file aiks_dl_blur_unittests.cc.

851 {
852 // This test is for checking out how stable rendering is when content is
853 // translated underneath a blur. Animating under a blur can cause
854 // *shimmering* to happen as a result of pixel alignment.
855 // See also: https://github.com/flutter/flutter/issues/140193
856 auto boston =
857 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
858 ASSERT_TRUE(boston);
859 int64_t count = 0;
860 Scalar sigma = 20.0;
861 Scalar freq = 0.1;
862 Scalar amp = 50.0;
863 auto callback = [&]() -> sk_sp<DisplayList> {
864 if (AiksTest::ImGuiBegin("Controls", nullptr,
865 ImGuiWindowFlags_AlwaysAutoResize)) {
866 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
867 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
868 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
869 ImGui::End();
870 }
871
872 DisplayListBuilder builder;
873 builder.Scale(GetContentScale().x, GetContentScale().y);
874 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
875 builder.DrawImage(DlImageImpeller::Make(boston),
876 DlPoint(1024 / 2 - boston->GetSize().width / 2,
877 (768 / 2 - boston->GetSize().height / 2) + y),
878 DlImageSampling::kMipmapLinear);
879 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
880 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
881 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
882
883 builder.ClipRect(
884 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
885 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
886
887 DlPaint paint;
888 paint.setBlendMode(DlBlendMode::kSrc);
889
890 auto backdrop_filter =
891 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
892 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
893 count += 1;
894 return builder.Build();
895 };
896 ASSERT_TRUE(OpenPlaygroundHere(callback));
897 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), and x.

## ◆ TEST_P() [218/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryHorizontal |
| ) |  |

Definition at line 822 of file aiks_dl_blur_unittests.cc.

822 {
823 DisplayListBuilder builder;
824
825 builder.Scale(GetContentScale().x, GetContentScale().y);
826 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
827 builder.DrawImageRect(
828 DlImageImpeller::Make(boston),
829 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
830 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
831 DlImageSampling::kNearestNeighbor);
832
833 DlPaint paint;
834 paint.setColor(DlColor::kMagenta());
835
836 DlRoundRect rrect = DlRoundRect::MakeRectXY(
837 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
838 builder.DrawRoundRect(rrect, paint);
839 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
840
841 DlPaint save_paint;
842 save_paint.setBlendMode(DlBlendMode::kSrc);
843
844 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
845 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
846
847 builder.Restore();
848 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
849 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [219/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurAtPeripheryVertical |
| ) |  |

Definition at line 794 of file aiks_dl_blur_unittests.cc.

794 {
795 DisplayListBuilder builder;
796
797 DlPaint paint;
798 builder.Scale(GetContentScale().x, GetContentScale().y);
799
800 paint.setColor(DlColor::kLimeGreen());
801 DlRoundRect rrect = DlRoundRect::MakeRectXY(
802 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
803 builder.DrawRoundRect(rrect, paint);
804
805 paint.setColor(DlColor::kMagenta());
806 rrect = DlRoundRect::MakeRectXY(
807 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
808 builder.DrawRoundRect(rrect, paint);
809 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
810
811 DlPaint save_paint;
812 save_paint.setBlendMode(DlBlendMode::kSrc);
813
814 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
815
816 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
817 builder.Restore();
818
819 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
820 }

References x.

## ◆ TEST_P() [220/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurBackdropTinyMipMap |
| ) |  |

Definition at line 1285 of file aiks_dl_blur_unittests.cc.

1285 {
1286 AiksContext renderer(GetContext(), nullptr);
1287 for (int32_t i = 1; i < 5; ++i) {
1288 DisplayListBuilder builder;
1289
1290 ISize clip_size = ISize(i, i);
1291 builder.Save();
1292 builder.ClipRect(
1293 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1294
1295 DlPaint paint;
1296 paint.setColor(DlColor::kGreen());
1297 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1298 paint.setImageFilter(blur_filter);
1299
1300 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1301 builder.Restore();
1302
1303 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1304 EXPECT_TRUE(image) << " length " << i;
1305 }
1306 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [221/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurOneDimension |
| ) |  |

Definition at line 1097 of file aiks_dl_blur_unittests.cc.

1097 {
1098 DisplayListBuilder builder;
1099
1100 builder.Scale(GetContentScale().x, GetContentScale().y);
1101 builder.Scale(0.5, 0.5);
1102
1103 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1104 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1105
1106 DlPaint paint;
1107 paint.setBlendMode(DlBlendMode::kSrc);
1108
1109 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1110 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1111 builder.Restore();
1112 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1113 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [222/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClipped |
| ) |  |

Definition at line 1119 of file aiks_dl_blur_unittests.cc.

1119 {
1120 DisplayListBuilder builder;
1121
1122 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1123 Rect bounds =
1124 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1125
1126 DlPaint paint;
1127 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1128
1129 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1130 Vector2 clip_size = {150, 75};
1131 Vector2 center = Vector2(1024, 768) / 2;
1132 builder.Scale(GetContentScale().x, GetContentScale().y);
1133
1134 auto clip_bounds =
1135 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1136 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1137 clip_bounds.GetRight(),
1138 clip_bounds.GetBottom()));
1139 builder.Translate(center.x, center.y);
1140 builder.Scale(0.6, 0.6);
1141 builder.Rotate(25);
1142
1143 auto dst_rect = bounds.Shift(-image_center);
1144 builder.DrawImageRect(
1145 DlImageImpeller::Make(boston), /*src=*/
1146 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1147 bounds.GetBottom()),
1148 /*dst=*/
1149 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1150 dst_rect.GetRight(), dst_rect.GetBottom()),
1151 DlImageSampling::kMipmapLinear, &paint);
1152
1153 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1154 }
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() [223/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedAndClippedInteractive |
| ) |  |

Definition at line 1042 of file aiks_dl_blur_unittests.cc.

1042 {
1043 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1044
1045 auto callback = [&]() -> sk_sp<DisplayList> {
1046 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1047 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1048 DlTileMode::kMirror, DlTileMode::kDecal};
1049
1050 static float rotation = 0;
1051 static float scale = 0.6;
1052 static int selected_tile_mode = 3;
1053
1054 if (AiksTest::ImGuiBegin("Controls", nullptr,
1055 ImGuiWindowFlags_AlwaysAutoResize)) {
1056 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1057 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1058 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1059 sizeof(tile_mode_names) / sizeof(char*));
1060 ImGui::End();
1061 }
1062
1063 DisplayListBuilder builder;
1064 Rect bounds =
1065 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1066 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1067 DlPaint paint;
1068 paint.setImageFilter(
1069 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1070
1071 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1072 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1073 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1074 Vector2 center = Vector2(1024, 768) / 2;
1075
1076 builder.Scale(GetContentScale().x, GetContentScale().y);
1077 builder.ClipRect(
1078 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1079 builder.Translate(center.x, center.y);
1080 builder.Scale(scale, scale);
1081 builder.Rotate(rotation);
1082
1083 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1084 bounds.GetRight(), bounds.GetBottom());
1085 Rect dest = bounds.Shift(-image_center);
1086 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1087 dest.GetRight(), dest.GetBottom());
1088 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1089 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1090 &paint);
1091 return builder.Build();
1092 };
1093
1094 ASSERT_TRUE(OpenPlaygroundHere(callback));
1095 }
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() [224/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurRotatedNonUniform |
| ) |  |

Definition at line 1156 of file aiks_dl_blur_unittests.cc.

1156 {
1157 auto callback = [&]() -> sk_sp<DisplayList> {
1158 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1159 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1160 DlTileMode::kMirror, DlTileMode::kDecal};
1161
1162 static float rotation = 45;
1163 static float scale = 0.6;
1164 static int selected_tile_mode = 3;
1165
1166 if (AiksTest::ImGuiBegin("Controls", nullptr,
1167 ImGuiWindowFlags_AlwaysAutoResize)) {
1168 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1169 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1170 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1171 sizeof(tile_mode_names) / sizeof(char*));
1172 ImGui::End();
1173 }
1174
1175 DisplayListBuilder builder;
1176
1177 DlPaint paint;
1178 paint.setColor(DlColor::kGreen());
1179 paint.setImageFilter(
1180 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1181
1182 Vector2 center = Vector2(1024, 768) / 2;
1183 builder.Scale(GetContentScale().x, GetContentScale().y);
1184 builder.Translate(center.x, center.y);
1185 builder.Scale(scale, scale);
1186 builder.Rotate(rotation);
1187
1188 DlRoundRect rrect =
1189 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1190 builder.DrawRoundRect(rrect, paint);
1191 return builder.Build();
1192 };
1193
1194 ASSERT_TRUE(OpenPlaygroundHere(callback));
1195 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [225/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurScaledAndClipped |
| ) |  |

Definition at line 1009 of file aiks_dl_blur_unittests.cc.

1009 {
1010 DisplayListBuilder builder;
1011 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1012 Rect bounds =
1013 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1014 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1015
1016 DlPaint paint;
1017 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1018
1019 Vector2 clip_size = {150, 75};
1020 Vector2 center = Vector2(1024, 768) / 2;
1021 builder.Scale(GetContentScale().x, GetContentScale().y);
1022
1023 auto rect =
1024 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1025 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1026 rect.GetRight(), rect.GetBottom()));
1027 builder.Translate(center.x, center.y);
1028 builder.Scale(0.6, 0.6);
1029
1030 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1031 bounds.GetRight(), bounds.GetBottom());
1032 Rect dest = bounds.Shift(-image_center);
1033 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1034 dest.GetRight(), dest.GetBottom());
1035 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1036 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1037 &paint);
1038
1039 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1040 }

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/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurSolidColorTinyMipMap |
| ) |  |

Definition at line 1260 of file aiks_dl_blur_unittests.cc.

1260 {
1261 AiksContext renderer(GetContext(), nullptr);
1262
1263 for (int32_t i = 1; i < 5; ++i) {
1264 DisplayListBuilder builder;
1265 Scalar fi = i;
1266 DlPathBuilder path_builder;
1267 path_builder.MoveTo(DlPoint(100, 100));
1268 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1269
1270 DlPaint paint;
1271 paint.setColor(DlColor::kChartreuse());
1272 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1273 paint.setImageFilter(blur_filter);
1274
1275 builder.DrawPath(path_builder.TakePath(), paint);
1276
1277 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1278 EXPECT_TRUE(image) << " length " << i;
1279 }
1280 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [227/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInner |
| ) |  |

Definition at line 649 of file aiks_dl_blur_unittests.cc.

649 {
650 DisplayListBuilder builder;
651 builder.Scale(GetContentScale().x, GetContentScale().y);
652
653 DlPaint paint;
654 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
655 builder.DrawPaint(paint);
656
657 paint.setColor(DlColor::kGreen());
658 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
659
660 DlPathBuilder path_builder;
661 path_builder.MoveTo(DlPoint(200, 200));
662 path_builder.LineTo(DlPoint(300, 400));
663 path_builder.LineTo(DlPoint(100, 400));
664 path_builder.Close();
665
666 builder.DrawPath(path_builder.TakePath(), paint);
667
668 // Draw another thing to make sure the clip area is reset.
669 DlPaint red;
670 red.setColor(DlColor::kRed());
671 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
672
673 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
674 }

References x.

## ◆ TEST_P() [228/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInnerGradient |
| ) |  |

Definition at line 899 of file aiks_dl_blur_unittests.cc.

899 {
900 DisplayListBuilder builder;
901
902 builder.Scale(GetContentScale().x, GetContentScale().y);
903
904 DlPaint paint;
905 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
906 builder.DrawPaint(paint);
907
908 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
909 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
910 std::vector<Scalar> stops = {0.0, 1.0};
911
912 paint = DlPaint{};
913 paint.setColorSource(DlColorSource::MakeLinear(
914 /*start_point=*/{0, 0},
915 /*end_point=*/{200, 200},
916 /*stop_count=*/colors.size(),
917 /*colors=*/colors.data(),
918 /*stops=*/stops.data(),
919 /*tile_mode=*/DlTileMode::kMirror));
920 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
921
922 DlPathBuilder path_builder;
923 path_builder.MoveTo(DlPoint(200, 200));
924 path_builder.LineTo(DlPoint(300, 400));
925 path_builder.LineTo(DlPoint(100, 400));
926 path_builder.Close();
927 builder.DrawPath(path_builder.TakePath(), paint);
928
929 // Draw another thing to make sure the clip area is reset.
930 DlPaint red;
931 red.setColor(DlColor::kRed());
932 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
933
934 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
935 }

References x.

## ◆ TEST_P() [229/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuter |
| ) |  |

Definition at line 676 of file aiks_dl_blur_unittests.cc.

676 {
677 DisplayListBuilder builder;
678 builder.Scale(GetContentScale().x, GetContentScale().y);
679
680 DlPaint paint;
681 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
682 builder.DrawPaint(paint);
683
684 paint.setColor(DlColor::kGreen());
685 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
686
687 DlPathBuilder path_builder;
688 path_builder.MoveTo(DlPoint(200, 200));
689 path_builder.LineTo(DlPoint(300, 400));
690 path_builder.LineTo(DlPoint(100, 400));
691 path_builder.Close();
692
693 builder.DrawPath(path_builder.TakePath(), paint);
694
695 // Draw another thing to make sure the clip area is reset.
696 DlPaint red;
697 red.setColor(DlColor::kRed());
698 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
699
700 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
701 }

References x.

## ◆ TEST_P() [230/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuterGradient |
| ) |  |

Definition at line 973 of file aiks_dl_blur_unittests.cc.

973 {
974 DisplayListBuilder builder;
975 builder.Scale(GetContentScale().x, GetContentScale().y);
976
977 DlPaint paint;
978 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
979 builder.DrawPaint(paint);
980
981 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
982 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
983 std::vector<Scalar> stops = {0.0, 1.0};
984
985 paint = DlPaint{};
986 paint.setColorSource(DlColorSource::MakeLinear(
987 /*start_point=*/{0, 0},
988 /*end_point=*/{200, 200},
989 /*stop_count=*/colors.size(),
990 /*colors=*/colors.data(),
991 /*stops=*/stops.data(),
992 /*tile_mode=*/DlTileMode::kMirror));
993 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
994
995 DlPathBuilder path_builder;
996 path_builder.MoveTo(DlPoint(200, 200));
997 path_builder.LineTo(DlPoint(300, 400));
998 path_builder.LineTo(DlPoint(100, 400));
999 path_builder.Close();
1000 builder.DrawPath(path_builder.TakePath(), paint);
1001
1002 // Draw another thing to make sure the clip area is reset.
1003 DlPaint red;
1004 red.setColor(DlColor::kRed());
1005 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1006 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1007 }

References x.

## ◆ TEST_P() [231/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolid |
| ) |  |

Definition at line 703 of file aiks_dl_blur_unittests.cc.

703 {
704 DisplayListBuilder builder;
705 builder.Scale(GetContentScale().x, GetContentScale().y);
706
707 DlPaint paint;
708 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
709 builder.DrawPaint(paint);
710
711 paint.setColor(DlColor::kGreen());
712 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
713
714 DlPathBuilder path_builder;
715 path_builder.MoveTo(DlPoint(200, 200));
716 path_builder.LineTo(DlPoint(300, 400));
717 path_builder.LineTo(DlPoint(100, 400));
718 path_builder.Close();
719
720 builder.DrawPath(path_builder.TakePath(), paint);
721
722 // Draw another thing to make sure the clip area is reset.
723 DlPaint red;
724 red.setColor(DlColor::kRed());
725 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
726
727 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
728 }

References x.

## ◆ TEST_P() [232/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolidGradient |
| ) |  |

Definition at line 937 of file aiks_dl_blur_unittests.cc.

937 {
938 DisplayListBuilder builder;
939 builder.Scale(GetContentScale().x, GetContentScale().y);
940
941 DlPaint paint;
942 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
943 builder.DrawPaint(paint);
944
945 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
946 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
947 std::vector<Scalar> stops = {0.0, 1.0};
948
949 paint = DlPaint{};
950 paint.setColorSource(DlColorSource::MakeLinear(
951 /*start_point=*/{0, 0},
952 /*end_point=*/{200, 200},
953 /*stop_count=*/colors.size(),
954 /*colors=*/colors.data(),
955 /*stops=*/stops.data(),
956 /*tile_mode=*/DlTileMode::kMirror));
957 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
958
959 DlPathBuilder path_builder;
960 path_builder.MoveTo(DlPoint(200, 200));
961 path_builder.LineTo(DlPoint(300, 400));
962 path_builder.LineTo(DlPoint(100, 400));
963 path_builder.Close();
964 builder.DrawPath(path_builder.TakePath(), paint);
965
966 // Draw another thing to make sure the clip area is reset.
967 DlPaint red;
968 red.setColor(DlColor::kRed());
969 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
970 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
971 }

References x.

## ◆ TEST_P() [233/545]

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() [234/545]

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() [235/545]

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() [236/545]

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() [237/545]

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() [238/545]

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() [239/545]

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() [240/545]

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() [241/545]

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() [242/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageColorSourceEffectTransform |
| ) |  |

Definition at line 1368 of file aiks_dl_basic_unittests.cc.

1368 {
1369 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
1370
1371 DisplayListBuilder builder;
1372 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
1373
1374 DlPaint paint;
1375 paint.setColor(DlColor::kWhite());
1376 builder.DrawPaint(paint);
1377
1378 // Translation
1379 {
1380 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
1381 DlPaint paint;
1382 paint.setColorSource(DlColorSource::MakeImage(
1383 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1384 DlImageSampling::kNearestNeighbor, &matrix));
1385
1386 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
1387 }
1388
1389 // Rotation/skew
1390 {
1391 builder.Save();
1392 builder.Rotate(45);
1393 DlPaint paint;
1394
1395 Matrix matrix(1, -1, 0, 0, //
1396 1, 1, 0, 0, //
1397 0, 0, 1, 0, //
1398 0, 0, 0, 1);
1399 paint.setColorSource(DlColorSource::MakeImage(
1400 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1401 DlImageSampling::kNearestNeighbor, &matrix));
1402 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
1403 builder.Restore();
1404 }
1405
1406 // Scale
1407 {
1408 builder.Save();
1409 builder.Translate(100, 0);
1410 builder.Scale(100, 100);
1411 DlPaint paint;
1412
1413 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
1414 paint.setColorSource(DlColorSource::MakeImage(
1415 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1416 DlImageSampling::kNearestNeighbor, &matrix));
1417
1418 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
1419 builder.Restore();
1420 }
1421
1422 // Perspective
1423 {
1424 builder.Save();
1425 builder.Translate(150, 150);
1426 DlPaint paint;
1427
1428 DlMatrix matrix =
1429 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
1430 paint.setColorSource(DlColorSource::MakeImage(
1431 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1432 DlImageSampling::kNearestNeighbor, &matrix));
1433
1434 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
1435 builder.Restore();
1436 }
1437
1438 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1439 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [243/545]

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() [244/545]

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() [245/545]

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() [246/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurDoesntStretchContents |
| ) |  |

Definition at line 759 of file aiks_dl_blur_unittests.cc.

759 {
760 Scalar sigma = 70;
761 auto callback = [&]() -> sk_sp<DisplayList> {
762 if (AiksTest::ImGuiBegin("Controls", nullptr,
763 ImGuiWindowFlags_AlwaysAutoResize)) {
764 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
765 ImGui::End();
766 }
767
768 DisplayListBuilder builder;
769 builder.Scale(GetContentScale().x, GetContentScale().y);
770
771 DlPaint paint;
772 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
773 builder.DrawPaint(paint);
774
775 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
776
777 builder.Transform(Matrix::MakeTranslation({100, 100}) *
778 Matrix::MakeScale({0.5, 0.5, 1.0f}));
779
780 paint.setColorSource(DlColorSource::MakeImage(
781 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
782 DlImageSampling::kMipmapLinear));
783 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
784
785 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
786 boston->GetSize().height),
787 paint);
788
789 return builder.Build();
790 };
791 ASSERT_TRUE(OpenPlaygroundHere(callback));
792 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and x.

## ◆ TEST_P() [247/545]

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() [248/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurTexture |
| ) |  |

Definition at line 730 of file aiks_dl_blur_unittests.cc.

730 {
731 Scalar sigma = 30;
732 auto callback = [&]() -> sk_sp<DisplayList> {
733 if (AiksTest::ImGuiBegin("Controls", nullptr,
734 ImGuiWindowFlags_AlwaysAutoResize)) {
735 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
736 ImGui::End();
737 }
738
739 DisplayListBuilder builder;
740 builder.Scale(GetContentScale().x, GetContentScale().y);
741
742 DlPaint paint;
743 paint.setColor(DlColor::kGreen());
744 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
745
746 builder.DrawImage(
747 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
748 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
749
750 DlPaint red;
751 red.setColor(DlColor::kRed());
752 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
753
754 return builder.Build();
755 };
756 ASSERT_TRUE(OpenPlaygroundHere(callback));
757 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [249/545]

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() [250/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScaleConvertToPath |
| ) |  |

Definition at line 195 of file aiks_dl_text_unittests.cc.

195 {
196 Scalar scale = 16.0;
197 auto callback = [&]() -> sk_sp<DisplayList> {
198 if (AiksTest::ImGuiBegin("Controls", nullptr,
199 ImGuiWindowFlags_AlwaysAutoResize)) {
200 ImGui::SliderFloat("Scale", &scale, 4, 20);
201 ImGui::End();
202 }
203
204 DisplayListBuilder builder;
205 DlPaint paint;
206 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
207 builder.DrawPaint(paint);
208
209 builder.Scale(scale, scale);
210 RenderTextInCanvasSkia(
211 GetContext(), builder, "HELLO", "Roboto-Regular.ttf",
212 TextRenderOptions{.font_size = 16,
213 .color = (16 * scale >= 250) ? DlColor::kYellow()
214 : DlColor::kOrange(),
215 .position = DlPoint(0, 20)});
216 return builder.Build();
217 };
218
219 ASSERT_TRUE(OpenPlaygroundHere(callback));
220 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [251/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScalingMatrixImageFilter |
| ) |  |

Definition at line 2012 of file aiks_dl_basic_unittests.cc.

2012 {
2013 if (GetBackend() == PlaygroundBackend::kVulkan) {
2014 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
2015 }
2016 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
2017
2018 auto filter = DlImageFilter::MakeMatrix(
2019 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
2020
2021 DlPaint paint;
2022 paint.setImageFilter(filter);
2023 builder.SaveLayer(std::nullopt, &paint);
2024 {
2025 DlPaint paint;
2026 paint.setColor(DlColor::kRed());
2027 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
2028 }
2029 builder.Restore();
2030
2031 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2032 }

References impeller::kVulkan.

## ◆ TEST_P() [252/545]

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() [253/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen |
| ) |  |

Definition at line 1491 of file aiks_dl_basic_unittests.cc.

1492 {
1493 DisplayListBuilder builder;
1494 builder.Scale(GetContentScale().x, GetContentScale().y);
1495 builder.Translate(100, 100);
1496 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1497 // +300 translation applied by a SaveLayer image filter.
1498
1499 DlPaint paint;
1500 paint.setImageFilter(DlImageFilter::MakeMatrix(
1501 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1502 DlImageSampling::kNearestNeighbor));
1503 builder.SaveLayer(std::nullopt, &paint);
1504
1505 DlPaint circle_paint;
1506 circle_paint.setColor(DlColor::kGreen());
1507 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1508 builder.Restore();
1509
1510 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1511 }

References x.

## ◆ TEST_P() [254/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen |
| ) |  |

Definition at line 1470 of file aiks_dl_basic_unittests.cc.

1470 {
1471 DisplayListBuilder builder;
1472 builder.Scale(GetContentScale().x, GetContentScale().y);
1473 builder.Translate(100, 100);
1474 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1475 // +300 translation applied by a SaveLayer image filter.
1476 DlPaint paint;
1477 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1478 paint.setImageFilter(
1479 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1480 builder.SaveLayer(std::nullopt, &paint);
1481
1482 DlPaint circle_paint;
1483 circle_paint.setColor(DlColor::kGreen());
1484 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1485 builder.Restore();
1486
1487 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1488 }

References x.

## ◆ TEST_P() [255/545]

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() [256/545]

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() [257/545]

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() [258/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MultipleTextWithShadowCache |
| ) |  |

Definition at line 803 of file aiks_dl_text_unittests.cc.

803 {
804 DisplayListBuilder builder;
805 builder.Scale(GetContentScale().x, GetContentScale().y);
806 DlPaint paint;
807 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
808 builder.DrawPaint(paint);
809
810 AiksContext aiks_context(GetContext(),
811 std::make_shared<TypographerContextSkia>());
812 // Cache empty
813 EXPECT_EQ(aiks_context.GetContentContext()
814 .GetTextShadowCache()
815 .GetCacheSizeForTesting(),
816 0u);
817
818 for (auto i = 0; i < 5; i++) {
819 ASSERT_TRUE(RenderTextInCanvasSkia(
820 GetContext(), builder, "Hello World", kFontFixture,
821 TextRenderOptions{
822 .color = DlColor::kBlue(),
823 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
824 }
825
826 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
827
828 // Text should be cached. Each text gets its own entry as we don't analyze the
829 // strings.
830 EXPECT_EQ(aiks_context.GetContentContext()
831 .GetTextShadowCache()
832 .GetCacheSizeForTesting(),
833 5u);
834 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [259/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NoDimplesInRRectPath |
| ) |  |

Definition at line 2034 of file aiks_dl_basic_unittests.cc.

2034 {
2035 Scalar width = 200.f;
2036 Scalar height = 60.f;
2037 Scalar corner = 1.f;
2038 auto callback = [&]() -> sk_sp<DisplayList> {
2039 if (AiksTest::ImGuiBegin("Controls", nullptr,
2040 ImGuiWindowFlags_AlwaysAutoResize)) {
2041 ImGui::SliderFloat("width", &width, 0, 200);
2042 ImGui::SliderFloat("height", &height, 0, 200);
2043 ImGui::SliderFloat("corner", &corner, 0, 1);
2044 ImGui::End();
2045 }
2046
2047 DisplayListBuilder builder;
2048 builder.Scale(GetContentScale().x, GetContentScale().y);
2049
2050 DlPaint background_paint;
2051 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
2052 builder.DrawPaint(background_paint);
2053
2054 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
2055 std::vector<Scalar> stops = {0.0, 1.0};
2056
2057 DlPaint paint;
2058 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
2059 2, colors.data(), stops.data(),
2060 DlTileMode::kClamp);
2061 paint.setColorSource(gradient);
2062 paint.setColor(DlColor::kWhite());
2063 paint.setDrawStyle(DlDrawStyle::kStroke);
2064 paint.setStrokeWidth(20);
2065
2066 builder.Save();
2067 builder.Translate(100, 100);
2068
2069 Scalar corner_x = ((1 - corner) * 50) + 50;
2070 Scalar corner_y = corner * 50 + 50;
2071 DlRoundRect rrect = DlRoundRect::MakeRectXY(
2072 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
2073 builder.DrawRoundRect(rrect, paint);
2074 builder.Restore();
2075 return builder.Build();
2076 };
2077 ASSERT_TRUE(OpenPlaygroundHere(callback));
2078 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [260/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectly |
| ) |  |

Definition at line 825 of file aiks_dl_basic_unittests.cc.

825 {
826 DisplayListBuilder builder;
827 builder.Scale(GetContentScale().x, GetContentScale().y);
828 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
829
830 DlPaint paint;
831 paint.setColor(DlColor::kBlue());
832
833 RenderArcFarm(builder, paint,
834 {
835 .use_center = false,
836 .full_circles = false,
837 .vertical_scale = 0.8f,
838 });
839
840 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
841 }

References x.

## ◆ TEST_P() [261/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NonSquareFilledArcsRenderCorrectlyWithCenter |
| ) |  |

Definition at line 843 of file aiks_dl_basic_unittests.cc.

843 {
844 DisplayListBuilder builder;
845 builder.Scale(GetContentScale().x, GetContentScale().y);
846 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
847
848 DlPaint paint;
849 paint.setColor(DlColor::kBlue());
850
851 RenderArcFarm(builder, paint,
852 {
853 .use_center = true,
854 .full_circles = false,
855 .vertical_scale = 0.8f,
856 });
857
858 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
859 }

References x.

## ◆ TEST_P() [262/545]

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() [263/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PipelineBlendSingleParameter |
| ) |  |

Definition at line 1986 of file aiks_dl_basic_unittests.cc.

1986 {
1987 DisplayListBuilder builder;
1988
1989 // Should render a green square in the middle of a blue circle.
1990 DlPaint paint;
1991 builder.SaveLayer(std::nullopt, &paint);
1992 {
1993 builder.Translate(100, 100);
1994 paint.setColor(DlColor::kBlue());
1995 builder.DrawCircle(DlPoint(200, 200), 200, paint);
1996 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1997
1998 paint.setColor(DlColor::kGreen());
1999 paint.setBlendMode(DlBlendMode::kSrcOver);
2000 paint.setImageFilter(DlImageFilter::MakeColorFilter(
2001 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
2002 builder.DrawCircle(DlPoint(200, 200), 200, paint);
2003 builder.Restore();
2004 }
2005
2006 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
2007 }

## ◆ TEST_P() [264/545]

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() [265/545]

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() [266/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RoundSuperellipseShadowComparison |
| ) |  |

Definition at line 389 of file canvas_unittests.cc.

389 {
390 // Config
391 Size default_size(600, 400);
392 Point left_center(400, 700);
393 Point right_center(1300, 700);
394 Color color = Color::Red();
395
396 // Convert `color` to a `color_source`. This forces
397 // `canvas.DrawRoundSuperellipse` to use the regular shadow algorithm
398 // (blurring) instead of the fast shadow algorithm.
399 std::shared_ptr<flutter::DlColorSource> color_source;
400 {
401 flutter::DlColor dl_color = flutter::DlColor(color.ToARGB());
402 std::vector<flutter::DlColor> colors = {dl_color, dl_color};
403 std::vector<Scalar> stops = {0.0, 1.0};
404 color_source = flutter::DlColorSource::MakeLinear(
405 {0, 0}, {1000, 1000}, 2, colors.data(), stops.data(),
406 flutter::DlTileMode::kClamp);
407 }
408
409 auto RectMakeCenterHalfSize = [](Point center, Point half_size) {
410 Size size(half_size.x * 2, half_size.y * 2);
411 return Rect::MakeOriginSize(center - half_size, size);
412 };
413
414 RenderCallback callback = [&](RenderTarget& render_target) {
415 ContentContext context(GetContext(), nullptr);
416 Canvas canvas(context, render_target, true, false);
417 // Somehow there's a scaling factor between PlaygroundPoint and Canvas.
418 Matrix ctm = Matrix::MakeScale(Vector2(1, 1) * 0.5);
419 Matrix i_ctm = ctm.Invert();
420
421 static Scalar sigma = 0.05;
422 static Scalar radius = 200;
423
424 // Define the ImGui
425 ImGui::Begin("Shadow", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
426 {
427 ImGui::SliderFloat("Sigma", &sigma, 0, 100);
428 ImGui::SliderFloat("Radius", &radius, 0, 1000);
429 }
430 ImGui::End();
431
432 static PlaygroundPoint right_reference_var(
433 ctm * (right_center + default_size / 2), 30, Color::White());
434 Point right_reference = i_ctm * DrawPlaygroundPoint(right_reference_var);
435 Point half_size = (right_reference - right_center).Abs();
436 Rect left_bounds = RectMakeCenterHalfSize(left_center, half_size);
437 Rect right_bounds = RectMakeCenterHalfSize(right_center, half_size);
438
439 Paint paint{
440 .color = color,
441 .mask_blur_descriptor =
442 Paint::MaskBlurDescriptor{
443 .sigma = Sigma(sigma),
444 },
445 };
446
447 // Left: Draw with canvas
448 canvas.DrawRoundSuperellipse(
449 RoundSuperellipse::MakeRectRadius(left_bounds, radius), paint);
450
451 // Right: Direct draw
452 paint.color_source = color_source.get();
453 canvas.DrawRoundSuperellipse(
454 RoundSuperellipse::MakeRectRadius(right_bounds, radius), paint);
455
456 canvas.EndReplay();
457 return true;
458 };
459
460 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
461 }

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() [267/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RuntimeEffectWithInvalidSamplerDoesNotCrash |
| ) |  |

Definition at line 111 of file aiks_dl_runtime_effect_unittests.cc.

111 {
112 ScopedValidationDisable disable_validation;
113
114 // Create a sampler that is not usable as an input to the runtime effect.
115 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
116 flutter::DlColor::kRed()};
117 const float stops[2] = {0.0, 1.0};
118 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
119 2, colors.data(), stops,
120 flutter::DlTileMode::kClamp);
121 std::vector<std::shared_ptr<DlColorSource>> sampler_inputs = {
122 linear,
123 };
124
125 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
126 uniform_data->resize(sizeof(Vector2));
127
128 DlPaint paint;
129 paint.setColorSource(
130 MakeRuntimeEffect(this, "runtime_stage_filter_example.frag.iplr",
131 uniform_data, sampler_inputs));
132
133 DisplayListBuilder builder;
134 builder.DrawPaint(paint);
135
136 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
137 }

## ◆ TEST_P() [268/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerDrawsBehindSubsequentEntities |
| ) |  |

Definition at line 1841 of file aiks_dl_basic_unittests.cc.

1841 {
1842 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1843 DisplayListBuilder builder;
1844 DlPaint paint;
1845
1846 paint.setColor(DlColor::kBlack());
1847 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1848 builder.DrawRect(rect, paint);
1849
1850 builder.Translate(10, 10);
1851
1852 DlPaint save_paint;
1853 builder.SaveLayer(std::nullopt, &save_paint);
1854
1855 paint.setColor(DlColor::kGreen());
1856 builder.DrawRect(rect, paint);
1857
1858 builder.Restore();
1859
1860 builder.Translate(10, 10);
1861 paint.setColor(DlColor::kRed());
1862 builder.DrawRect(rect, paint);
1863
1864 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1865 }

## ◆ TEST_P() [269/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerFiltersScaleWithTransform |
| ) |  |

Definition at line 1933 of file aiks_dl_basic_unittests.cc.

1933 {
1934 DisplayListBuilder builder;
1935
1936 builder.Scale(GetContentScale().x, GetContentScale().y);
1937 builder.Translate(100, 100);
1938
1939 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1940 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
1941 builder.SaveLayer(std::nullopt, &paint);
1942 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
1943 builder.Restore();
1944 };
1945
1946 DlPaint effect_paint;
1947 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
1948 draw_image_layer(effect_paint);
1949
1950 builder.Translate(300, 300);
1951 builder.Scale(3, 3);
1952 draw_image_layer(effect_paint);
1953
1954 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1955 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [270/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaledK |
| ) |  |

Definition at line 173 of file aiks_dl_text_unittests.cc.

173 {
174 DisplayListBuilder builder;
175 DlPaint paint;
176 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
177 builder.DrawPaint(paint);
178 for (int i = 0; i < 6; ++i) {
179 builder.Save();
180 builder.Translate(300 * i, 0);
181 Scalar scale = 0.445 - (i / 1000.f);
182 builder.Scale(scale, scale);
183 RenderTextInCanvasSkia(
184 GetContext(), builder, "k", "Roboto-Regular.ttf",
185 TextRenderOptions{.font_size = 600, .position = DlPoint(10, 500)});
186 RenderTextInCanvasSkia(
187 GetContext(), builder, "k", "Roboto-Regular.ttf",
188 TextRenderOptions{.font_size = 300, .position = DlPoint(10, 800)});
189 builder.Restore();
190 }
191 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
192 }

References impeller::testing::TextRenderOptions::font_size, and RenderTextInCanvasSkia().

## ◆ TEST_P() [271/545]

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() [272/545]

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() [273/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SiblingSaveLayerBoundsAreRespected |
| ) |  |

Definition at line 1867 of file aiks_dl_basic_unittests.cc.

1867 {
1868 DisplayListBuilder builder;
1869 DlPaint paint;
1870 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
1871
1872 // Black, green, and red squares offset by [10, 10].
1873 {
1874 DlPaint save_paint;
1875 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
1876 builder.SaveLayer(bounds, &save_paint);
1877 paint.setColor(DlColor::kBlack());
1878 builder.DrawRect(rect, paint);
1879 builder.Restore();
1880 }
1881
1882 {
1883 DlPaint save_paint;
1884 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
1885 builder.SaveLayer(bounds, &save_paint);
1886 paint.setColor(DlColor::kGreen());
1887 builder.DrawRect(rect, paint);
1888 builder.Restore();
1889 }
1890
1891 {
1892 DlPaint save_paint;
1893 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
1894 builder.SaveLayer(bounds, &save_paint);
1895 paint.setColor(DlColor::kRed());
1896 builder.DrawRect(rect, paint);
1897 builder.Restore();
1898 }
1899
1900 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1901 }

## ◆ TEST_P() [274/545]

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() [275/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SingleIconShadowTest |
| ) |  |

Definition at line 836 of file aiks_dl_text_unittests.cc.

836 {
837 DisplayListBuilder builder;
838 builder.Scale(GetContentScale().x, GetContentScale().y);
839 DlPaint paint;
840 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
841 builder.DrawPaint(paint);
842
843 AiksContext aiks_context(GetContext(),
844 std::make_shared<TypographerContextSkia>());
845 // Cache empty
846 EXPECT_EQ(aiks_context.GetContentContext()
847 .GetTextShadowCache()
848 .GetCacheSizeForTesting(),
849 0u);
850
851 // Create font instance outside loop so all draws use identical font instance.
852 auto c_font_fixture = std::string(kFontFixture);
853 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
854 ASSERT_TRUE(mapping);
855 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
856 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
857
858 for (auto i = 0; i < 10; i++) {
859 ASSERT_TRUE(RenderTextInCanvasSkia(
860 GetContext(), builder, "A", kFontFixture,
861 TextRenderOptions{
862 .color = DlColor::kBlue(),
863 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
864 sk_font));
865 }
866
867 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
868
869 // Text should be cached. All 10 glyphs use the same cache entry.
870 EXPECT_EQ(aiks_context.GetContentContext()
871 .GetTextShadowCache()
872 .GetCacheSizeForTesting(),
873 1u);
874 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [276/545]

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() [277/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCirclesOvalsRRectsMaskBlurCorrectly |
| ) |  |

Definition at line 1203 of file aiks_dl_basic_unittests.cc.

1203 {
1204 DisplayListBuilder builder;
1205 builder.Scale(GetContentScale().x, GetContentScale().y);
1206 DlPaint paint;
1207 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
1208
1209 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1210
1211 paint.setColor(
1212 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
1213 Scalar y = 100.0f;
1214 for (int i = 0; i < 5; i++) {
1215 Scalar x = (i + 1) * 100;
1216 Scalar radius = x / 10.0f;
1217 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1218 radius, 60.0f - radius),
1219 paint);
1220 }
1221
1222 paint.setColor(DlColor::kBlue());
1223 y += 100.0f;
1224 for (int i = 0; i < 5; i++) {
1225 Scalar x = (i + 1) * 100;
1226 Scalar radius = x / 10.0f;
1227 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
1228 }
1229
1230 paint.setColor(DlColor::kGreen());
1231 y += 100.0f;
1232 for (int i = 0; i < 5; i++) {
1233 Scalar x = (i + 1) * 100;
1234 Scalar radius = x / 10.0f;
1235 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1236 radius, 60.0f - radius),
1237 paint);
1238 }
1239
1240 paint.setColor(
1241 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
1242 y += 100.0f;
1243 for (int i = 0; i < 5; i++) {
1244 Scalar x = (i + 1) * 100;
1245 Scalar radius = x / 20.0f;
1246 builder.DrawRoundRect(
1247 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1248 radius, radius),
1249 paint);
1250 }
1251
1252 paint.setColor(
1253 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
1254 y += 100.0f;
1255 for (int i = 0; i < 5; i++) {
1256 Scalar x = (i + 1) * 100;
1257 Scalar radius = x / 20.0f;
1258 builder.DrawRoundRect(
1259 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
1260 radius, 5.0f),
1261 paint);
1262 }
1263
1264 auto dl = builder.Build();
1265 ASSERT_TRUE(OpenPlaygroundHere(dl));
1266 }

References x.

## ◆ TEST_P() [278/545]

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() [279/545]

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() [280/545]

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() [281/545]

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() [282/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsCoverFullArcWithButtEnds |
| ) |  |

Definition at line 1054 of file aiks_dl_basic_unittests.cc.

1054 {
1055 // This test compares the rendering of a full circle arc against a partial
1056 // arc by drawing a one over the other in high contrast. If the partial
1057 // arc misses any pixels that were drawn by the full arc, there will be
1058 // some "pixel dirt" around the missing "erased" parts of the arcs. This
1059 // case arises while rendering a CircularProgressIndicator with a background
1060 // color where we want the rendering of the background full arc to hit the
1061 // same pixels around the edges as the partial arc that covers it.
1062 //
1063 // In this case we draw a full blue circle and then draw a partial arc
1064 // over it in the background color (white).
1065
1066 DisplayListBuilder builder;
1067 builder.Scale(GetContentScale().x, GetContentScale().y);
1068 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1069
1070 DlPaint paint;
1071 paint.setDrawStyle(DlDrawStyle::kStroke);
1072 paint.setStrokeWidth(6.0f);
1073 paint.setStrokeCap(DlStrokeCap::kButt);
1074 paint.setColor(DlColor::kBlue());
1075
1076 // First draw full circles in blue to establish the pixels to be erased
1077 RenderArcFarm(builder, paint,
1078 {
1079 .use_center = false,
1080 .full_circles = true,
1081 });
1082
1083 paint.setColor(DlColor::kWhite());
1084
1085 // Then draw partial arcs in white over the circles to "erase" them
1086 RenderArcFarm(builder, paint,
1087 {
1088 .use_center = false,
1089 .full_circles = false,
1090 });
1091
1092 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1093 }

References x.

## ◆ TEST_P() [283/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithBevelJoinsAndCenter |
| ) |  |

Definition at line 921 of file aiks_dl_basic_unittests.cc.

921 {
922 DisplayListBuilder builder;
923 builder.Scale(GetContentScale().x, GetContentScale().y);
924 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
925
926 DlPaint paint;
927 paint.setDrawStyle(DlDrawStyle::kStroke);
928 paint.setStrokeWidth(6.0f);
929 paint.setStrokeJoin(DlStrokeJoin::kBevel);
930 paint.setColor(DlColor::kBlue());
931
932 RenderArcFarm(builder, paint,
933 {
934 .use_center = true,
935 .full_circles = false,
936 .sweeps_over_360 = true,
937 });
938
939 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
940 }

References x.

## ◆ TEST_P() [284/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithButtEnds |
| ) |  |

Definition at line 861 of file aiks_dl_basic_unittests.cc.

861 {
862 DisplayListBuilder builder;
863 builder.Scale(GetContentScale().x, GetContentScale().y);
864 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
865
866 DlPaint paint;
867 paint.setDrawStyle(DlDrawStyle::kStroke);
868 paint.setStrokeWidth(6.0f);
869 paint.setStrokeCap(DlStrokeCap::kButt);
870 paint.setColor(DlColor::kBlue());
871
872 RenderArcFarm(builder, paint,
873 {
874 .use_center = false,
875 .full_circles = false,
876 });
877
878 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
879 }

References x.

## ◆ TEST_P() [285/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithMiterJoinsAndCenter |
| ) |  |

Definition at line 942 of file aiks_dl_basic_unittests.cc.

942 {
943 DisplayListBuilder builder;
944 builder.Scale(GetContentScale().x, GetContentScale().y);
945 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
946
947 DlPaint paint;
948 paint.setDrawStyle(DlDrawStyle::kStroke);
949 paint.setStrokeWidth(6.0f);
950 paint.setStrokeJoin(DlStrokeJoin::kMiter);
951 // Default miter of 4.0 does a miter on all of the centers, but
952 // using 3.0 will show some bevels on the widest interior angles...
953 paint.setStrokeMiter(3.0f);
954 paint.setColor(DlColor::kBlue());
955
956 RenderArcFarm(builder, paint,
957 {
958 .use_center = true,
959 .full_circles = false,
960 .sweeps_over_360 = true,
961 });
962
963 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
964 }

References x.

## ◆ TEST_P() [286/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundEnds |
| ) |  |

Definition at line 901 of file aiks_dl_basic_unittests.cc.

901 {
902 DisplayListBuilder builder;
903 builder.Scale(GetContentScale().x, GetContentScale().y);
904 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
905
906 DlPaint paint;
907 paint.setDrawStyle(DlDrawStyle::kStroke);
908 paint.setStrokeWidth(6.0f);
909 paint.setStrokeCap(DlStrokeCap::kRound);
910 paint.setColor(DlColor::kBlue());
911
912 RenderArcFarm(builder, paint,
913 {
914 .use_center = false,
915 .full_circles = false,
916 });
917
918 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
919 }

References x.

## ◆ TEST_P() [287/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithRoundJoinsAndCenter |
| ) |  |

Definition at line 966 of file aiks_dl_basic_unittests.cc.

966 {
967 DisplayListBuilder builder;
968 builder.Scale(GetContentScale().x, GetContentScale().y);
969 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
970
971 DlPaint paint;
972 paint.setDrawStyle(DlDrawStyle::kStroke);
973 paint.setStrokeWidth(6.0f);
974 paint.setStrokeJoin(DlStrokeJoin::kRound);
975 paint.setColor(DlColor::kBlue());
976
977 RenderArcFarm(builder, paint,
978 {
979 .use_center = true,
980 .full_circles = false,
981 .sweeps_over_360 = true,
982 });
983
984 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
985 }

References x.

## ◆ TEST_P() [288/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtAndRoundEnds |
| ) |  |

Definition at line 1016 of file aiks_dl_basic_unittests.cc.

1016 {
1017 DisplayListBuilder builder;
1018 builder.Scale(GetContentScale().x, GetContentScale().y);
1019 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1020
1021 DlPaint paint;
1022 paint.setDrawStyle(DlDrawStyle::kStroke);
1023 paint.setStrokeWidth(8.0f);
1024 paint.setStrokeCap(DlStrokeCap::kSquare);
1025 paint.setColor(DlColor::kRed());
1026
1027 RenderArcFarm(builder, paint,
1028 {
1029 .use_center = false,
1030 .full_circles = false,
1031 });
1032
1033 paint.setStrokeCap(DlStrokeCap::kRound);
1034 paint.setColor(DlColor::kGreen());
1035
1036 RenderArcFarm(builder, paint,
1037 {
1038 .use_center = false,
1039 .full_circles = false,
1040 });
1041
1042 paint.setStrokeCap(DlStrokeCap::kButt);
1043 paint.setColor(DlColor::kBlue());
1044
1045 RenderArcFarm(builder, paint,
1046 {
1047 .use_center = false,
1048 .full_circles = false,
1049 });
1050
1051 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1052 }

References x.

## ◆ TEST_P() [289/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareAndButtEnds |
| ) |  |

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(8.0f);
995 paint.setStrokeCap(DlStrokeCap::kSquare);
996 paint.setColor(DlColor::kRed());
997
998 RenderArcFarm(builder, paint,
999 {
1000 .use_center = false,
1001 .full_circles = false,
1002 });
1003
1004 paint.setStrokeCap(DlStrokeCap::kButt);
1005 paint.setColor(DlColor::kBlue());
1006
1007 RenderArcFarm(builder, paint,
1008 {
1009 .use_center = false,
1010 .full_circles = false,
1011 });
1012
1013 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1014 }

References x.

## ◆ TEST_P() [290/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedArcsRenderCorrectlyWithSquareEnds |
| ) |  |

Definition at line 881 of file aiks_dl_basic_unittests.cc.

881 {
882 DisplayListBuilder builder;
883 builder.Scale(GetContentScale().x, GetContentScale().y);
884 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
885
886 DlPaint paint;
887 paint.setDrawStyle(DlDrawStyle::kStroke);
888 paint.setStrokeWidth(6.0f);
889 paint.setStrokeCap(DlStrokeCap::kSquare);
890 paint.setColor(DlColor::kBlue());
891
892 RenderArcFarm(builder, paint,
893 {
894 .use_center = false,
895 .full_circles = false,
896 });
897
898 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
899 }

References x.

## ◆ TEST_P() [291/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedCirclesRenderCorrectly |
| ) |  |

Definition at line 623 of file aiks_dl_basic_unittests.cc.

623 {
624 DisplayListBuilder builder;
625 builder.Scale(GetContentScale().x, GetContentScale().y);
626 DlPaint paint;
627 const int color_count = 3;
628 DlColor colors[color_count] = {
629 DlColor::kBlue(),
630 DlColor::kGreen(),
631 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
632 };
633
634 paint.setColor(DlColor::kWhite());
635 builder.DrawPaint(paint);
636
637 int c_index = 0;
638
639 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, DlPoint center,
640 Scalar r, Scalar dr, int n) {
641 for (int i = 0; i < n; i++) {
642 paint.setColor(colors[(c_index++) % color_count]);
643 canvas.DrawCircle(center, r, paint);
644 r += dr;
645 }
646 };
647
648 paint.setDrawStyle(DlDrawStyle::kStroke);
649 paint.setStrokeWidth(1);
650 draw(builder, DlPoint(10, 10), 2, 2, 14); // r = [2, 28], covers [1,29]
651 paint.setStrokeWidth(5);
652 draw(builder, DlPoint(10, 10), 35, 10, 56); // r = [35, 585], covers [30,590]
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 draw(builder, DlPoint(500, 600), 5, 10, 10);
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 draw(builder, DlPoint(800, 300), 5, 10, 10);
685
686 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
687 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [292/545]

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() [293/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedRectsRenderCorrectly |
| ) |  |

Definition at line 427 of file aiks_dl_basic_unittests.cc.

427 {
428 DisplayListBuilder builder;
429 builder.Scale(GetContentScale().x, GetContentScale().y);
430
431 DlPaint paint;
432 paint.setColor(DlColor::kPurple());
433 paint.setDrawStyle(DlDrawStyle::kStroke);
434 paint.setStrokeWidth(20.0f);
435
436 DlPaint thin_paint = paint;
437 thin_paint.setColor(DlColor::kYellow());
438 thin_paint.setStrokeWidth(0.0f);
439
440 DlRect rect = DlRect::MakeLTRB(10, 10, 90, 90);
441 DlRect thin_tall_rect = DlRect::MakeLTRB(120, 10, 120, 90);
442 DlRect thin_wide_rect = DlRect::MakeLTRB(10, 120, 90, 120);
443 DlRect empty_rect = DlRect::MakeLTRB(120, 120, 120, 120);
444
445 // We draw the following sets of rectangles:
446 //
447 // A E X
448 // X
449 // B F X
450 // X
451 // C D G H X
452 //
453 // Purple A,B,C,D are all drawn with stroke width 20 (non-overflowing).
454 // Each of those sets has 4 rectangles of dimension 80x80, 80x0, 0x80,
455 // and 0,0 to demonstrate the basic behavior and also the behavior of
456 // empty dimensions.
457 //
458 // Blue E,F,G,H are the same 80x80 rectangles, but with an overflowing
459 // stroke width of 120 to show the behavior with degenerately large
460 // stroke widths.
461 //
462 // A,E are drawn with Bevel joins.
463 // B,F are drawn with Round joins.
464 // C,G are drawn with Miter joins and a large enough miter limit.
465 // D,H are drawn with Miter joins and a too small miter limit (== Bevel).
466 //
467 // All orange X rectangles are drawn with round joins and increasing stroke
468 // widths to demonstrate fidelity of the rounding code at various arc sizes.
469 // These X rectangles also help test that the variable sizing estimates in
470 // the round join code are accurate.
471
472 // rects (A)
473 paint.setStrokeJoin(DlStrokeJoin::kBevel);
474 builder.DrawRect(rect.Shift({100, 100}), paint);
475 builder.DrawRect(rect.Shift({100, 100}), thin_paint);
476 builder.DrawRect(thin_tall_rect.Shift({100, 100}), paint);
477 builder.DrawRect(thin_tall_rect.Shift({100, 100}), thin_paint);
478 builder.DrawRect(thin_wide_rect.Shift({100, 100}), paint);
479 builder.DrawRect(thin_wide_rect.Shift({100, 100}), thin_paint);
480 builder.DrawRect(empty_rect.Shift({100, 100}), paint);
481 builder.DrawRect(empty_rect.Shift({100, 100}), thin_paint);
482
483 // rects (B)
484 paint.setStrokeJoin(DlStrokeJoin::kRound);
485 builder.DrawRect(rect.Shift({100, 300}), paint);
486 builder.DrawRect(rect.Shift({100, 300}), thin_paint);
487 builder.DrawRect(thin_tall_rect.Shift({100, 300}), paint);
488 builder.DrawRect(thin_tall_rect.Shift({100, 300}), thin_paint);
489 builder.DrawRect(thin_wide_rect.Shift({100, 300}), paint);
490 builder.DrawRect(thin_wide_rect.Shift({100, 300}), thin_paint);
491 builder.DrawRect(empty_rect.Shift({100, 300}), paint);
492 builder.DrawRect(empty_rect.Shift({100, 300}), thin_paint);
493
494 // rects (C)
495 paint.setStrokeJoin(DlStrokeJoin::kMiter);
496 paint.setStrokeMiter(kSqrt2 + flutter::kEhCloseEnough);
497 builder.DrawRect(rect.Shift({100, 500}), paint);
498 builder.DrawRect(rect.Shift({100, 500}), thin_paint);
499 builder.DrawRect(thin_tall_rect.Shift({100, 500}), paint);
500 builder.DrawRect(thin_tall_rect.Shift({100, 500}), thin_paint);
501 builder.DrawRect(thin_wide_rect.Shift({100, 500}), paint);
502 builder.DrawRect(thin_wide_rect.Shift({100, 500}), thin_paint);
503 builder.DrawRect(empty_rect.Shift({100, 500}), paint);
504 builder.DrawRect(empty_rect.Shift({100, 500}), thin_paint);
505
506 // rects (D)
507 paint.setStrokeJoin(DlStrokeJoin::kMiter);
508 paint.setStrokeMiter(kSqrt2 - flutter::kEhCloseEnough);
509 builder.DrawRect(rect.Shift({300, 500}), paint);
510 builder.DrawRect(rect.Shift({300, 500}), thin_paint);
511 builder.DrawRect(thin_tall_rect.Shift({300, 500}), paint);
512 builder.DrawRect(thin_tall_rect.Shift({300, 500}), thin_paint);
513 builder.DrawRect(thin_wide_rect.Shift({300, 500}), paint);
514 builder.DrawRect(thin_wide_rect.Shift({300, 500}), thin_paint);
515 builder.DrawRect(empty_rect.Shift({300, 500}), paint);
516 builder.DrawRect(empty_rect.Shift({300, 500}), thin_paint);
517
518 paint.setStrokeWidth(120.0f);
519 paint.setColor(DlColor::kBlue());
520 rect = rect.Expand(-20);
521
522 // rect (E)
523 paint.setStrokeJoin(DlStrokeJoin::kBevel);
524 builder.DrawRect(rect.Shift({500, 100}), paint);
525 builder.DrawRect(rect.Shift({500, 100}), thin_paint);
526
527 // rect (F)
528 paint.setStrokeJoin(DlStrokeJoin::kRound);
529 builder.DrawRect(rect.Shift({500, 300}), paint);
530 builder.DrawRect(rect.Shift({500, 300}), thin_paint);
531
532 // rect (G)
533 paint.setStrokeJoin(DlStrokeJoin::kMiter);
534 paint.setStrokeMiter(kSqrt2 + flutter::kEhCloseEnough);
535 builder.DrawRect(rect.Shift({500, 500}), paint);
536 builder.DrawRect(rect.Shift({500, 500}), thin_paint);
537
538 // rect (H)
539 paint.setStrokeJoin(DlStrokeJoin::kMiter);
540 paint.setStrokeMiter(kSqrt2 - flutter::kEhCloseEnough);
541 builder.DrawRect(rect.Shift({700, 500}), paint);
542 builder.DrawRect(rect.Shift({700, 500}), thin_paint);
543
544 DlPaint round_mock_paint;
545 round_mock_paint.setColor(DlColor::kGreen());
546 round_mock_paint.setDrawStyle(DlDrawStyle::kFill);
547
548 // array of rects (X)
549 Scalar x = 900;
550 Scalar y = 50;
551 for (int i = 0; i < 15; i++) {
552 paint.setStrokeWidth(i);
553 paint.setColor(DlColor::kOrange());
554 paint.setStrokeJoin(DlStrokeJoin::kRound);
555 builder.DrawRect(DlRect::MakeXYWH(x, y, 30, 30), paint);
556 y += 32 + i;
557 }
558
559 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
560 }

References impeller::kEhCloseEnough, impeller::kSqrt2, and x.

## ◆ TEST_P() [294/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SubpassWithClearColorOptimization |
| ) |  |

Definition at line 1441 of file aiks_dl_basic_unittests.cc.

1441 {
1442 DisplayListBuilder builder;
1443
1444 // Use a non-srcOver blend mode to ensure that we don't detect this as an
1445 // opacity peephole optimization.
1446 DlPaint paint;
1447 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
1448 paint.setBlendMode(DlBlendMode::kSrc);
1449
1450 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
1451 builder.SaveLayer(bounds, &paint);
1452
1453 paint.setColor(DlColor::kTransparent());
1454 paint.setBlendMode(DlBlendMode::kSrc);
1455 builder.DrawPaint(paint);
1456 builder.Restore();
1457
1458 paint.setColor(DlColor::kBlue());
1459 paint.setBlendMode(DlBlendMode::kDstOver);
1460 builder.SaveLayer(std::nullopt, &paint);
1461 builder.Restore();
1462
1463 // This playground should appear blank on CI since we are only drawing
1464 // transparent black. If the clear color optimization is broken, the texture
1465 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
1466 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1467 }

## ◆ TEST_P() [295/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SupportsBlitToOnscreen |
| ) |  |

Definition at line 377 of file canvas_unittests.cc.

377 {
378 ContentContext context(GetContext(), nullptr);
379 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
380 /*requires_readback=*/true);
381
382 if (GetBackend() != PlaygroundBackend::kMetal) {
383 EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
384 } else {
385 EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
386 }
387 }

References CreateTestCanvas(), impeller::kMetal, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [296/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextContentsMismatchedTransformTest |
| ) |  |

Definition at line 707 of file aiks_dl_text_unittests.cc.

707 {
708 AiksContext aiks_context(GetContext(),
709 std::make_shared<TypographerContextSkia>());
710
711 // Verifies that TextContents only use the scale/transform that is
712 // computed during preroll.
713 constexpr const char* font_fixture = "Roboto-Regular.ttf";
714
715 // Construct the text blob.
716 auto c_font_fixture = std::string(font_fixture);
717 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
718 ASSERT_TRUE(mapping);
719
720 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
721 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
722
723 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
724 ASSERT_TRUE(blob);
725
726 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
727
728 // Simulate recording the text frame during preroll.
729 Matrix preroll_matrix =
730 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
731 Point preroll_point = Point{23, 45};
732 {
733 auto scale = TextFrame::RoundScaledFontSize(
734 (preroll_matrix * Matrix::MakeTranslation(preroll_point))
735 .GetMaxBasisLengthXY());
736
737 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
738 text_frame, //
739 scale, //
740 preroll_point, //
741 preroll_matrix,
742 std::nullopt //
743 );
744 }
745
746 // Now simulate rendering with a slightly different scale factor.
747 RenderTarget render_target =
748 aiks_context.GetContentContext()
749 .GetRenderTargetCache()
750 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
751
752 TextContents text_contents;
753 text_contents.SetTextFrame(text_frame);
754 text_contents.SetOffset(preroll_point);
755 text_contents.SetScale(1.6);
756 text_contents.SetColor(Color::Aqua());
757
758 Matrix not_preroll_matrix =
759 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
760
761 Entity entity;
762 entity.SetTransform(not_preroll_matrix);
763
764 std::shared_ptr<CommandBuffer> command_buffer =
765 aiks_context.GetContext()->CreateCommandBuffer();
766 std::shared_ptr<RenderPass> render_pass =
767 command_buffer->CreateRenderPass(render_target);
768
769 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
770 *render_pass));
771 }

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() [297/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextForegroundShaderWithTransform |
| ) |  |

Definition at line 592 of file aiks_dl_text_unittests.cc.

592 {
593 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
594 ASSERT_NE(mapping, nullptr);
595
596 Scalar font_size = 100;
597 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
598 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
599
600 DlPaint text_paint;
601 text_paint.setColor(DlColor::kBlue());
602
603 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
604 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
605 std::vector<Scalar> stops = {
606 0.0,
607 1.0,
608 };
609 text_paint.setColorSource(DlColorSource::MakeLinear(
610 /*start_point=*/DlPoint(0, 0), //
611 /*end_point=*/DlPoint(100, 100), //
612 /*stop_count=*/2, //
613 /*colors=*/colors.data(), //
614 /*stops=*/stops.data(), //
615 /*tile_mode=*/DlTileMode::kRepeat //
616 ));
617
618 DisplayListBuilder builder;
619 builder.Translate(100, 100);
620 builder.Rotate(45);
621
622 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
623 ASSERT_NE(blob, nullptr);
624 auto frame = MakeTextFrameFromTextBlobSkia(blob);
625 builder.DrawTextFrame(frame, 0, 0, text_paint);
626
627 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
628 }

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [298/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextFrameSubpixelAlignment |
| ) |  |

Definition at line 316 of file aiks_dl_text_unittests.cc.

316 {
317 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
318 std::array<Scalar, 20> phase_offsets = {
319 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
320 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
321 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
322 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
323 auto callback = [&]() -> sk_sp<DisplayList> {
324 static float font_size = 20;
325 static float phase_variation = 0.2;
326 static float speed = 0.5;
327 static float magnitude = 100;
328 if (AiksTest::ImGuiBegin("Controls", nullptr,
329 ImGuiWindowFlags_AlwaysAutoResize)) {
330 ImGui::SliderFloat("Font size", &font_size, 5, 50);
331 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
332 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
333 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
334 ImGui::End();
335 }
336
337 DisplayListBuilder builder;
338 builder.Scale(GetContentScale().x, GetContentScale().y);
339
340 for (size_t i = 0; i < phase_offsets.size(); i++) {
341 DlPoint position = DlPoint(
342 200 +
343 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
344 GetSecondsElapsed() * speed)), //
345 200 + i * font_size * 1.1 //
346 );
347 if (!RenderTextInCanvasSkia(
348 GetContext(), builder,
349 "the quick brown fox jumped over "
350 "the lazy dog!.?",
351 "Roboto-Regular.ttf",
352 {.font_size = font_size, .position = position})) {
353 return nullptr;
354 }
355 }
356 return builder.Build();
357 };
358
359 ASSERT_TRUE(OpenPlaygroundHere(callback));
360 }

References font_size, impeller::k2Pi, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [299/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated |
| ) |  |

Definition at line 488 of file aiks_dl_text_unittests.cc.

488 {
489 DisplayListBuilder builder;
490
491 builder.Scale(GetContentScale().x, GetContentScale().y);
492 DlPaint paint;
493 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
494 builder.DrawPaint(paint);
495
496 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
497 0, 0.5, 0, 0, //
498 0, 0, 0.3, 0, //
499 100, 100, 0, 1.3));
500 ASSERT_TRUE(RenderTextInCanvasSkia(
501 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
502 "Roboto-Regular.ttf"));
503
504 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
505 }

References RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [300/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated180Degrees |
| ) |  |

Definition at line 279 of file aiks_dl_text_unittests.cc.

279 {
280 float fpivot[2] = {200 + 30, 200 - 20};
281 float rotation = 180;
282 float foffset[2] = {200, 200};
283
284 auto callback = [&]() -> sk_sp<DisplayList> {
285 if (AiksTest::ImGuiBegin("Controls", nullptr,
286 ImGuiWindowFlags_AlwaysAutoResize)) {
287 ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
288 ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
289 ImGui::SliderFloat("rotation", &rotation, 0, 360);
290 ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
291 ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
292 ImGui::End();
293 }
294 DisplayListBuilder builder;
295 builder.Scale(GetContentScale().x, GetContentScale().y);
296 builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
297
298 builder.Save();
299 DlPoint pivot = Point(fpivot[0], fpivot[1]);
300 builder.Translate(pivot.x, pivot.y);
301 builder.Rotate(rotation);
302 builder.Translate(-pivot.x, -pivot.y);
303
304 RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
305 TextRenderOptions{
306 .color = DlColor::kBlack(),
307 .position = DlPoint(foffset[0], foffset[1]),
308 });
309
310 builder.Restore();
311 return builder.Build();
312 };
313 ASSERT_TRUE(OpenPlaygroundHere(callback));
314 }

References impeller::testing::TextRenderOptions::color, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [301/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextWithShadowCache |
| ) |  |

Definition at line 773 of file aiks_dl_text_unittests.cc.

773 {
774 DisplayListBuilder builder;
775 builder.Scale(GetContentScale().x, GetContentScale().y);
776 DlPaint paint;
777 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
778 builder.DrawPaint(paint);
779
780 AiksContext aiks_context(GetContext(),
781 std::make_shared<TypographerContextSkia>());
782 // Cache empty
783 EXPECT_EQ(aiks_context.GetContentContext()
784 .GetTextShadowCache()
785 .GetCacheSizeForTesting(),
786 0u);
787
788 ASSERT_TRUE(RenderTextInCanvasSkia(
789 GetContext(), builder, "Hello World", kFontFixture,
790 TextRenderOptions{
791 .color = DlColor::kBlue(),
792 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
793
794 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
795
796 // Text should be cached.
797 EXPECT_EQ(aiks_context.GetContentContext()
798 .GetTextShadowCache()
799 .GetCacheSizeForTesting(),
800 1u);
801 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [302/545]

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() [303/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransformMultipliesCorrectly |
| ) |  |

Definition at line 70 of file canvas_unittests.cc.

70 {
71 ContentContext context(GetContext(), nullptr);
72 auto canvas = CreateTestCanvas(context);
73
74 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
75
76 // clang-format off
77 canvas->Translate(Vector3(100, 200));
78 ASSERT_MATRIX_NEAR(
79 canvas->GetCurrentTransform(),
80 Matrix( 1, 0, 0, 0,
81 0, 1, 0, 0,
82 0, 0, 1, 0,
83 100, 200, 0, 1));
84
85 canvas->Rotate(Radians(kPiOver2));
86 ASSERT_MATRIX_NEAR(
87 canvas->GetCurrentTransform(),
88 Matrix( 0, 1, 0, 0,
89 -1, 0, 0, 0,
90 0, 0, 1, 0,
91 100, 200, 0, 1));
92
93 canvas->Scale(Vector3(2, 3));
94 ASSERT_MATRIX_NEAR(
95 canvas->GetCurrentTransform(),
96 Matrix( 0, 2, 0, 0,
97 -3, 0, 0, 0,
98 0, 0, 0, 0,
99 100, 200, 0, 1));
100
101 canvas->Translate(Vector3(100, 200));
102 ASSERT_MATRIX_NEAR(
103 canvas->GetCurrentTransform(),
104 Matrix( 0, 2, 0, 0,
105 -3, 0, 0, 0,
106 0, 0, 0, 0,
107 -500, 400, 0, 1));
108 // clang-format on
109 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [304/545]

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() [305/545]

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() [306/545]

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() [307/545]

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() [308/545]

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() [309/545]

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() [310/545]

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() [311/545]

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() [312/545]

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() [313/545]

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() [314/545]

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() [315/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VarietyOfTextScalesShowingRasterAndPath |
| ) |  |

Definition at line 876 of file aiks_dl_text_unittests.cc.

876 {
877 DisplayListBuilder builder;
878 DlPaint paint;
879 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
880 builder.DrawPaint(paint);
881 builder.Scale(GetContentScale().x, GetContentScale().y);
882
883 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
884 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
885 Scalar space = 16;
886 Scalar x = 0;
887 for (auto i = 0u; i < scales.size(); i++) {
888 builder.Save();
889 builder.Scale(scales[i], scales[i]);
890 RenderTextInCanvasSkia(
891 GetContext(), builder, "lo", "Roboto-Regular.ttf",
892 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
893 space += spacing[i];
894 if (i == 3) {
895 x = 10;
896 space = 16;
897 }
898 builder.Restore();
899 }
900 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
901 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [316/545]

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() [317/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionData |
| ) |  |

Definition at line 97 of file aiks_dl_vertices_unittests.cc.

97 {
98 DisplayListBuilder builder;
99 DlPaint paint;
100 auto image =
101 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
102 auto size = image->impeller_texture()->GetSize();
103
104 paint.setColorSource(
105 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
106
107 std::vector<DlPoint> positions = {
108 DlPoint(0, 0), DlPoint(size.width, 0),
109 DlPoint(0, size.height), DlPoint(size.width, 0),
110 DlPoint(0, 0), DlPoint(size.width, size.height),
111 };
112 std::vector<DlColor> colors = {
113 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
114 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
115 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
116 };
117
118 auto vertices =
119 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
120
121 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
122 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
123 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [318/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionDataAdvancedBlend |
| ) |  |

Definition at line 125 of file aiks_dl_vertices_unittests.cc.

125 {
126 DisplayListBuilder builder;
127 DlPaint paint;
128 auto image =
129 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
130 auto size = image->impeller_texture()->GetSize();
131
132 paint.setColorSource(
133 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
134
135 std::vector<DlPoint> positions = {
136 DlPoint(0, 0), DlPoint(size.width, 0),
137 DlPoint(0, size.height), DlPoint(size.width, 0),
138 DlPoint(0, 0), DlPoint(size.width, size.height),
139 };
140 std::vector<DlColor> colors = {
141 DlColor::kRed().modulateOpacity(0.5),
142 DlColor::kBlue().modulateOpacity(0.5),
143 DlColor::kGreen().modulateOpacity(0.5),
144 DlColor::kRed().modulateOpacity(0.5),
145 DlColor::kBlue().modulateOpacity(0.5),
146 DlColor::kGreen().modulateOpacity(0.5),
147 };
148
149 auto vertices =
150 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
151
152 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
153 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
154 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [319/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionData |
| ) |  |

Definition at line 49 of file aiks_dl_vertices_unittests.cc.

49 {
50 DisplayListBuilder builder;
51 DlPaint paint;
52 auto image =
53 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
54 auto size = image->impeller_texture()->GetSize();
55
56 paint.setColorSource(
57 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
58
59 std::vector<DlPoint> vertex_coordinates = {
60 DlPoint(0, 0),
61 DlPoint(size.width, 0),
62 DlPoint(0, size.height),
63 };
64 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
65 {0, 1, 2}, {}, {});
66
67 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
68 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
69 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [320/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionDataWithTranslate |
| ) |  |

Definition at line 72 of file aiks_dl_vertices_unittests.cc.

72 {
73 DisplayListBuilder builder;
74 DlPaint paint;
75 auto image =
76 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
77 auto size = image->impeller_texture()->GetSize();
78
79 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
80 paint.setColorSource(
81 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp,
82 DlImageSampling::kLinear, &matrix));
83
84 std::vector<DlPoint> positions = {
85 DlPoint(0, 0),
86 DlPoint(size.width, 0),
87 DlPoint(0, size.height),
88 };
89 auto vertices =
90 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
91
92 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
93 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
94 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [321/545]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryWithMaskFilter |
| ) |  |

Definition at line 555 of file aiks_dl_vertices_unittests.cc.

555 {
556 DisplayListBuilder builder;
557 DlPaint paint;
558 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
559
560 std::vector<DlPoint> vertex_coordinates = {
561 DlPoint(0, 0),
562 DlPoint(400, 0),
563 DlPoint(0, 400),
564 };
565 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
566 {0, 1, 2}, {}, {});
567
568 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
569 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
570 }

## ◆ TEST_P() [322/545]

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() [323/545]

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() [324/545]

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 =
56 renderer->GetTransientsBuffer().Emplace(&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() [325/545]

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() [326/545]

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() [327/545]

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() [328/545]

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() [329/545]

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() [330/545]

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() [331/545]

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() [332/545]

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() [333/545]

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() [334/545]

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() [335/545]

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() [336/545]

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() [337/545]

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() [338/545]

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() [339/545]

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() [340/545]

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() [341/545]

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() [342/545]

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() [343/545]

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() [344/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1176 of file dl_unittests.cc.

1176 {
1177 flutter::DisplayListBuilder builder;
1178
1179 {
1180 builder.SaveLayer(std::nullopt, nullptr);
1181 builder.Translate(100, 100);
1182 flutter::DlPaint paint;
1183 paint.setColor(flutter::DlColor::kRed());
1184 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1185 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1186 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1187 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1188 builder.Restore();
1189 }
1190 {
1191 builder.SaveLayer(std::nullopt, nullptr);
1192 builder.Translate(300, 100);
1193 flutter::DlPaint paint;
1194 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1195 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1196 paint.setColor(flutter::DlColor::kRed());
1197 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1198 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1199 builder.Restore();
1200 }
1201 {
1202 builder.SaveLayer(std::nullopt, nullptr);
1203 builder.Translate(100, 300);
1204 flutter::DlPaint paint;
1205 paint.setColor(flutter::DlColor::kRed());
1206 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1207 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1208 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1209 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1210 builder.Restore();
1211 }
1212 {
1213 builder.SaveLayer(std::nullopt, nullptr);
1214 builder.Translate(300, 300);
1215 flutter::DlPaint paint;
1216 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1217 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1218 paint.setColor(flutter::DlColor::kRed());
1219 paint.setBlendMode(flutter::DlBlendMode::kDst);
1220 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1221 builder.Restore();
1222 }
1223
1224 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1225 }

## ◆ TEST_P() [345/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 622 of file dl_unittests.cc.

622 {
623 auto texture = CreateTextureForFixture("boston.jpg");
624 const float inner_color_matrix[20] = {
625 1, 0, 0, 0, 0, //
626 0, 1, 0, 0, 0, //
627 0, 0, 1, 0, 0, //
628 0, 0, 0, 2, 0, //
629 };
630 const float outer_color_matrix[20] = {
631 1, 0, 0, 0, 0, //
632 0, 1, 0, 0, 0, //
633 0, 0, 1, 0, 0, //
634 0, 0, 0, 0.5, 0, //
635 };
636 auto inner_color_filter =
637 flutter::DlColorFilter::MakeMatrix(inner_color_matrix);
638 auto outer_color_filter =
639 flutter::DlColorFilter::MakeMatrix(outer_color_matrix);
640 auto inner = flutter::DlImageFilter::MakeColorFilter(inner_color_filter);
641 auto outer = flutter::DlImageFilter::MakeColorFilter(outer_color_filter);
642 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
643
644 flutter::DisplayListBuilder builder;
645 flutter::DlPaint paint;
646 paint.setImageFilter(compose.get());
647 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
648 flutter::DlImageSampling::kNearestNeighbor, &paint);
649 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
650 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [346/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 414 of file dl_unittests.cc.

414 {
415 flutter::DisplayListBuilder builder;
416 flutter::DlPaint paint;
417
418 paint.setColor(flutter::DlColor::kRed());
419 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
420 paint.setStrokeWidth(10);
421
422 builder.Translate(300, 300);
423
424 // Move to (50, 50) and draw lines from:
425 // 1. (50, height)
426 // 2. (width, height)
427 // 3. (width, 50)
428 flutter::DlPathBuilder path_builder;
429 path_builder.MoveTo(DlPoint(50, 50));
430 path_builder.LineTo(DlPoint(50, 100));
431 path_builder.LineTo(DlPoint(100, 100));
432 path_builder.LineTo(DlPoint(100, 50));
433 builder.DrawPath(path_builder.TakePath(), paint);
434
435 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
436 }

## ◆ TEST_P() [347/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 152 of file dl_unittests.cc.

152 {
153 auto callback = [&]() {
154 static float start_angle = 45;
155 static float sweep_angle = 270;
156 static float stroke_width = 10;
157 static bool use_center = true;
158
159 static int selected_cap = 0;
160 const char* cap_names[] = {"Butt", "Round", "Square"};
161 flutter::DlStrokeCap cap;
162
163 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
164 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
165 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
166 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
167 ImGui::Combo("Cap", &selected_cap, cap_names,
168 sizeof(cap_names) / sizeof(char*));
169 ImGui::Checkbox("Use center", &use_center);
170 ImGui::End();
171
172 switch (selected_cap) {
173 case 0:
174 cap = flutter::DlStrokeCap::kButt;
175 break;
176 case 1:
177 cap = flutter::DlStrokeCap::kRound;
178 break;
179 case 2:
180 cap = flutter::DlStrokeCap::kSquare;
181 break;
182 default:
183 cap = flutter::DlStrokeCap::kButt;
184 break;
185 }
186
187 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
188 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
189 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
190
191 flutter::DisplayListBuilder builder;
192 flutter::DlPaint paint;
193
194 Vector2 scale = GetContentScale();
195 builder.Scale(scale.x, scale.y);
196 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
197 paint.setStrokeCap(cap);
198 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
199 paint.setStrokeMiter(10);
200 auto rect = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
201 paint.setColor(flutter::DlColor::kGreen());
202 paint.setStrokeWidth(2);
203 builder.DrawRect(rect, paint);
204 paint.setColor(flutter::DlColor::kRed());
205 paint.setStrokeWidth(stroke_width);
206 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
207
208 return builder.Build();
209 };
210 ASSERT_TRUE(OpenPlaygroundHere(callback));
211 }
use_center
bool use_center
Definition: aiks_dl_basic_unittests.cc:764

References impeller::DrawPlaygroundLine(), use_center, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [348/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 652 of file dl_unittests.cc.

652 {
653 auto texture = CreateTextureForFixture("embarcadero.jpg");
654
655 auto callback = [&]() {
656 static float sigma[] = {10, 10};
657 static float ctm_scale = 1;
658 static bool use_bounds = true;
659 static bool draw_circle = true;
660 static bool add_clip = true;
661
662 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
663 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
664 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
665 ImGui::NewLine();
666 ImGui::TextWrapped(
667 "If everything is working correctly, none of the options below should "
668 "impact the filter's appearance.");
669 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
670 ImGui::Checkbox("Draw child element", &draw_circle);
671 ImGui::Checkbox("Add pre-clip", &add_clip);
672 ImGui::End();
673
674 flutter::DisplayListBuilder builder;
675
676 Vector2 scale = ctm_scale * GetContentScale();
677 builder.Scale(scale.x, scale.y);
678
679 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
680 flutter::DlTileMode::kClamp);
681
682 std::optional<DlRect> bounds;
683 if (use_bounds) {
684 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
685 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
686 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
687 bounds = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
688 }
689
690 // Insert a clip to test that the backdrop filter handles stencil depths > 0
691 // correctly.
692 if (add_clip) {
693 builder.ClipRect(DlRect::MakeLTRB(0, 0, 99999, 99999),
694 flutter::DlClipOp::kIntersect, true);
695 }
696
697 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
698 flutter::DlImageSampling::kNearestNeighbor, nullptr);
699 builder.SaveLayer(bounds, nullptr, &filter);
700
701 if (draw_circle) {
702 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
703 auto circle_center = DrawPlaygroundPoint(center_point);
704
705 flutter::DlPaint paint;
706 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
707 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
708 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
709 paint.setStrokeWidth(10);
710 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
711 builder.DrawCircle(DlPoint(circle_center.x, circle_center.y), 100, paint);
712 }
713
714 return builder.Build();
715 };
716
717 ASSERT_TRUE(OpenPlaygroundHere(callback));
718 }

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() [349/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 103 of file dl_unittests.cc.

103 {
104 flutter::DisplayListBuilder builder;
105 flutter::DlPaint paint;
106
107 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
108 paint.setStrokeWidth(30);
109 paint.setColor(flutter::DlColor::kRed());
110
111 flutter::DlPathBuilder path_builder;
112 path_builder.MoveTo(DlPoint(-50, 0));
113 path_builder.LineTo(DlPoint(0, -50));
114 path_builder.LineTo(DlPoint(50, 0));
115 flutter::DlPath path = path_builder.TakePath();
116
117 builder.Translate(100, 100);
118 {
119 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
120 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
121 paint.setStrokeMiter(4);
122 builder.DrawPath(path, paint);
123 }
124
125 {
126 builder.Save();
127 builder.Translate(0, 100);
128 // The joint in the path is 45 degrees. A miter length of 1 convert to a
129 // bevel in this case.
130 paint.setStrokeMiter(1);
131 builder.DrawPath(path, paint);
132 builder.Restore();
133 }
134
135 builder.Translate(150, 0);
136 {
137 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
138 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
139 builder.DrawPath(path, paint);
140 }
141
142 builder.Translate(150, 0);
143 {
144 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
145 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
146 builder.DrawPath(path, paint);
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

## ◆ TEST_P() [350/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1227 of file dl_unittests.cc.

1227 {
1228 flutter::DisplayListBuilder builder;
1229 const float green_color_matrix[20] = {
1230 0, 0, 0, 0, 0, //
1231 0, 0, 0, 0, 1, //
1232 0, 0, 0, 0, 0, //
1233 0, 0, 0, 1, 0, //
1234 };
1235 const float blue_color_matrix[20] = {
1236 0, 0, 0, 0, 0, //
1237 0, 0, 0, 0, 0, //
1238 0, 0, 0, 0, 1, //
1239 0, 0, 0, 1, 0, //
1240 };
1241 auto green_color_filter =
1242 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1243 auto blue_color_filter =
1244 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1245 auto blue_image_filter =
1246 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1247
1248 flutter::DlPaint paint;
1249 paint.setColor(flutter::DlColor::kRed());
1250 paint.setColorFilter(green_color_filter);
1251 paint.setImageFilter(blue_image_filter);
1252 builder.DrawRect(DlRect::MakeLTRB(100, 100, 500, 500), paint);
1253 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1254 }

## ◆ TEST_P() [351/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 95 of file dl_unittests.cc.

95 {
96 auto texture = CreateTextureForFixture("embarcadero.jpg");
97 flutter::DisplayListBuilder builder;
98 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
99 flutter::DlImageSampling::kNearestNeighbor, nullptr);
100 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
101 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [352/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 720 of file dl_unittests.cc.

720 {
721 // Image is drawn with corners to scale and center pieces stretched to fit.
722 auto texture = CreateTextureForFixture("embarcadero.jpg");
723 flutter::DisplayListBuilder builder;
724 auto size = texture->GetSize();
725 builder.DrawImageNine(
726 DlImageImpeller::Make(texture),
727 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
728 size.height * 3 / 4),
729 DlRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
730 flutter::DlFilterMode::kNearest, nullptr);
731 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
732 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [353/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 766 of file dl_unittests.cc.

766 {
767 // Edge case, the width and height of the corners does not leave any
768 // room for the center slices. Only the corners are displayed.
769 auto texture = CreateTextureForFixture("embarcadero.jpg");
770 flutter::DisplayListBuilder builder;
771 auto size = texture->GetSize();
772 builder.DrawImageNine(
773 DlImageImpeller::Make(texture),
774 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
775 size.height * 3 / 4),
776 DlRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
777 flutter::DlFilterMode::kNearest, nullptr);
778 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
779 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [354/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 750 of file dl_unittests.cc.

750 {
751 // Edge case, the height of the corners does not leave any room for the
752 // center slice. The center (across the horizontal axis) is folded out of the
753 // resulting image.
754 auto texture = CreateTextureForFixture("embarcadero.jpg");
755 flutter::DisplayListBuilder builder;
756 auto size = texture->GetSize();
757 builder.DrawImageNine(
758 DlImageImpeller::Make(texture),
759 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
760 size.height * 3 / 4),
761 DlRect::MakeLTRB(0, 0, size.width, size.height / 2),
762 flutter::DlFilterMode::kNearest, nullptr);
763 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
764 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [355/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 734 of file dl_unittests.cc.

734 {
735 // Edge case, the width of the corners does not leave any room for the
736 // center slice. The center (across the vertical axis) is folded out of the
737 // resulting image.
738 auto texture = CreateTextureForFixture("embarcadero.jpg");
739 flutter::DisplayListBuilder builder;
740 auto size = texture->GetSize();
741 builder.DrawImageNine(
742 DlImageImpeller::Make(texture),
743 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
744 size.height * 3 / 4),
745 DlRect::MakeLTRB(0, 0, size.width / 2, size.height),
746 flutter::DlFilterMode::kNearest, nullptr);
747 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
748 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [356/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 781 of file dl_unittests.cc.

781 {
782 // Edge case, there is not enough room for the corners to be drawn
783 // without scaling them down.
784 auto texture = CreateTextureForFixture("embarcadero.jpg");
785 flutter::DisplayListBuilder builder;
786 auto size = texture->GetSize();
787 builder.DrawImageNine(
788 DlImageImpeller::Make(texture),
789 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
790 size.height * 3 / 4),
791 DlRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
792 flutter::DlFilterMode::kNearest, nullptr);
793 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
794 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [357/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1124 of file dl_unittests.cc.

1124 {
1125 const flutter::DlColor colors[2] = {
1126 flutter::DlColor(0xFFF44336),
1127 flutter::DlColor(0xFF2196F3),
1128 };
1129 const float stops[2] = {0.0, 1.0};
1130 flutter::DlPaint paint;
1131 flutter::DisplayListBuilder builder;
1132 auto clip_bounds = DlRect::MakeWH(300.0, 300.0);
1133 builder.Save();
1134 builder.Translate(100, 100);
1135 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1136 auto linear =
1137 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1138 stops, flutter::DlTileMode::kRepeat);
1139 paint.setColorSource(linear);
1140 builder.DrawPaint(paint);
1141 builder.Restore();
1142
1143 builder.Save();
1144 builder.Translate(500, 100);
1145 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1146 auto radial = flutter::DlColorSource::MakeRadial(
1147 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1148 paint.setColorSource(radial);
1149 builder.DrawPaint(paint);
1150 builder.Restore();
1151
1152 builder.Save();
1153 builder.Translate(100, 500);
1154 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1155 auto sweep =
1156 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1157 stops, flutter::DlTileMode::kRepeat);
1158 paint.setColorSource(sweep);
1159 builder.DrawPaint(paint);
1160 builder.Restore();
1161
1162 builder.Save();
1163 builder.Translate(500, 500);
1164 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1165 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1166 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1167 flutter::DlTileMode::kRepeat,
1168 flutter::DlTileMode::kRepeat);
1169 paint.setColorSource(image);
1170 builder.DrawPaint(paint);
1171 builder.Restore();
1172
1173 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1174 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [358/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 808 of file dl_unittests.cc.

808 {
809 flutter::DisplayListBuilder builder;
810 DlPoint points[7] = {
811 {0, 0}, //
812 {100, 100}, //
813 {100, 0}, //
814 {0, 100}, //
815 {0, 0}, //
816 {48, 48}, //
817 {52, 52}, //
818 };
819 std::vector<flutter::DlStrokeCap> caps = {
820 flutter::DlStrokeCap::kButt,
821 flutter::DlStrokeCap::kRound,
822 flutter::DlStrokeCap::kSquare,
823 };
824 flutter::DlPaint paint =
825 flutter::DlPaint() //
826 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
827 .setStrokeWidth(20);
828 builder.Translate(50, 50);
829 for (auto cap : caps) {
830 paint.setStrokeCap(cap);
831 builder.Save();
832 builder.DrawPoints(flutter::DlPointMode::kPoints, 7, points, paint);
833 builder.Translate(150, 0);
834 builder.DrawPoints(flutter::DlPointMode::kLines, 5, points, paint);
835 builder.Translate(150, 0);
836 builder.DrawPoints(flutter::DlPointMode::kPolygon, 5, points, paint);
837 builder.Restore();
838 builder.Translate(0, 150);
839 }
840 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
841 }

References points.

## ◆ TEST_P() [359/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 46 of file dl_unittests.cc.

46 {
47 flutter::DisplayListBuilder builder;
48 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100),
49 flutter::DlPaint(flutter::DlColor::kBlue()));
50 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
51 }

## ◆ TEST_P() [360/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1110 of file dl_unittests.cc.

1110 {
1111 flutter::DlPaint paint;
1112 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1113 flutter::DisplayListBuilder builder;
1114 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1115 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1116 builder.Translate(0, 200);
1117
1118 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1119 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1120
1121 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1122 }

## ◆ TEST_P() [361/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 866 of file dl_unittests.cc.

866 {
867 flutter::DisplayListBuilder builder;
868 flutter::DlPaint paint;
869
870 auto content_scale = GetContentScale() * 0.8;
871 builder.Scale(content_scale.x, content_scale.y);
872
873 constexpr size_t star_spikes = 5;
874 constexpr DlScalar half_spike_rotation = kPi / star_spikes;
875 constexpr DlScalar radius = 40;
876 constexpr DlScalar spike_size = 10;
877 constexpr DlScalar outer_radius = radius + spike_size;
878 constexpr DlScalar inner_radius = radius - spike_size;
879 std::array<DlPoint, star_spikes * 2> star;
880 for (size_t i = 0; i < star_spikes; i++) {
881 const DlScalar rotation = half_spike_rotation * i * 2;
882 star[i * 2] = DlPoint(50 + std::sin(rotation) * outer_radius,
883 50 - std::cos(rotation) * outer_radius);
884 star[i * 2 + 1] =
885 DlPoint(50 + std::sin(rotation + half_spike_rotation) * inner_radius,
886 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
887 }
888
889 std::array<DlPath, 4> paths = {
890 DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100)),
891 DlPath::MakeRoundRectXY(DlRect::MakeXYWH(20, 0, 200, 100), 30, 30),
892 DlPath::MakeCircle(DlPoint(100, 50), 50),
893 DlPath::MakePoly(star.data(), star.size(), true),
894 };
895 paint.setColor(flutter::DlColor::kWhite());
896 builder.DrawPaint(paint);
897 paint.setColor(flutter::DlColor::kCyan());
898 builder.Translate(100, 50);
899 for (size_t x = 0; x < paths.size(); x++) {
900 builder.Save();
901 for (size_t y = 0; y < 6; y++) {
902 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
903 1);
904 builder.DrawPath(paths[x], paint);
905 builder.Translate(0, 150);
906 }
907 builder.Restore();
908 builder.Translate(250, 0);
909 }
910
911 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
912 }

References impeller::kPi, and x.

## ◆ TEST_P() [362/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 474 of file dl_unittests.cc.

474 {
475 flutter::DisplayListBuilder builder;
476 flutter::DlPaint paint;
477
478 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
479 paint.setColor(flutter::DlColor::kRed());
480 builder.DrawTextBlob(
481 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
482 250, 250, paint);
483
484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
485 }

## ◆ TEST_P() [363/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 53 of file dl_unittests.cc.

53 {
54 flutter::DisplayListBuilder builder;
55 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
56 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
57 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
58 }

## ◆ TEST_P() [364/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 60 of file dl_unittests.cc.

60 {
61 flutter::DisplayListBuilder builder;
62
63 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
64 flutter::DlColor::kRed()};
65 const float stops[2] = {0.0, 1.0};
66
67 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
68 2, colors.data(), stops,
69 flutter::DlTileMode::kClamp);
70 flutter::DlPaint paint;
71 paint.setColorSource(linear);
72
73 builder.DrawTextBlob(
74 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
75 paint);
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77 }

## ◆ TEST_P() [365/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 79 of file dl_unittests.cc.

79 {
80 flutter::DisplayListBuilder builder;
81 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
82 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
83
84 flutter::DlPaint save_paint;
85 float alpha = 0.5;
86 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
87 builder.SaveLayer(std::nullopt, &save_paint);
88 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
89 CreateTestFontOfSize(100)),
90 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
91 builder.Restore();
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

## ◆ TEST_P() [366/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 526 of file dl_unittests.cc.

526 {
527 auto texture = CreateTextureForFixture("embarcadero.jpg");
528 flutter::DisplayListBuilder builder;
529 flutter::DlPaint paint;
530
531 // Pipeline blended image.
532 {
533 auto filter = flutter::DlColorFilter::MakeBlend(
534 flutter::DlColor::kYellow(), flutter::DlBlendMode::kModulate);
535 paint.setColorFilter(filter);
536 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
537 flutter::DlImageSampling::kNearestNeighbor, &paint);
538 }
539
540 // Advanced blended image.
541 {
542 auto filter = flutter::DlColorFilter::MakeBlend(
543 flutter::DlColor::kRed(), flutter::DlBlendMode::kScreen);
544 paint.setColorFilter(filter);
545 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(250, 250),
546 flutter::DlImageSampling::kNearestNeighbor, &paint);
547 }
548
549 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
550 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [367/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 552 of file dl_unittests.cc.

552 {
553 const float invert_color_matrix[20] = {
554 -1, 0, 0, 0, 1, //
555 0, -1, 0, 0, 1, //
556 0, 0, -1, 0, 1, //
557 0, 0, 0, 1, 0, //
558 };
559 auto texture = CreateTextureForFixture("boston.jpg");
560 flutter::DisplayListBuilder builder;
561 flutter::DlPaint paint;
562
563 auto color_filter = flutter::DlColorFilter::MakeMatrix(invert_color_matrix);
564 auto image_filter = flutter::DlImageFilter::MakeColorFilter(color_filter);
565
566 paint.setImageFilter(image_filter);
567 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
568 flutter::DlImageSampling::kNearestNeighbor, &paint);
569
570 builder.Translate(0, 700);
571 paint.setColorFilter(color_filter);
572 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
573 flutter::DlImageSampling::kNearestNeighbor, &paint);
574 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
575 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [368/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 602 of file dl_unittests.cc.

602 {
603 auto texture = CreateTextureForFixture("boston.jpg");
604 flutter::DisplayListBuilder builder;
605 flutter::DlPaint paint;
606
607 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
608 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
609 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
610 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
611
612 paint.setImageFilter(open.get());
613 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
614 flutter::DlImageSampling::kNearestNeighbor, &paint);
615 builder.Translate(0, 700);
616 paint.setImageFilter(close.get());
617 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
618 flutter::DlImageSampling::kNearestNeighbor, &paint);
619 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
620 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [369/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 577 of file dl_unittests.cc.

577 {
578 auto texture = CreateTextureForFixture("embarcadero.jpg");
579
580 auto callback = [&]() {
581 static float sigma[] = {10, 10};
582
583 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
584 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
585 ImGui::End();
586
587 flutter::DisplayListBuilder builder;
588 flutter::DlPaint paint;
589
590 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
591 flutter::DlTileMode::kClamp);
592 paint.setImageFilter(&filter);
593 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
594 flutter::DlImageSampling::kNearestNeighbor, &paint);
595
596 return builder.Build();
597 };
598
599 ASSERT_TRUE(OpenPlaygroundHere(callback));
600 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [370/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 438 of file dl_unittests.cc.

438 {
439 auto texture = CreateTextureForFixture("embarcadero.jpg");
440 flutter::DisplayListBuilder builder;
441 flutter::DlPaint paint;
442
443 // Mask blurred image.
444 {
445 auto filter =
446 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
447 paint.setMaskFilter(&filter);
448 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
449 flutter::DlImageSampling::kNearestNeighbor, &paint);
450 }
451
452 // Mask blurred filled path.
453 {
454 paint.setColor(flutter::DlColor::kYellow());
455 auto filter =
456 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
457 paint.setMaskFilter(&filter);
458 builder.DrawArc(DlRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
459 }
460
461 // Mask blurred text.
462 {
463 auto filter =
464 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
465 paint.setMaskFilter(&filter);
466 builder.DrawTextBlob(
467 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
468 paint);
469 }
470
471 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
472 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [371/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 948 of file dl_unittests.cc.

948 {
949 auto boston = CreateTextureForFixture("boston.jpg");
950
951 auto callback = [&]() {
952 static int selected_matrix_type = 0;
953 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
954
955 static float ctm_translation[2] = {200, 200};
956 static float ctm_scale[2] = {0.65, 0.65};
957 static float ctm_skew[2] = {0, 0};
958
959 static bool enable = true;
960 static float translation[2] = {100, 100};
961 static float scale[2] = {0.8, 0.8};
962 static float skew[2] = {0.2, 0.2};
963
964 static bool enable_savelayer = true;
965
966 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
967 {
968 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
969 sizeof(matrix_type_names) / sizeof(char*));
970
971 ImGui::TextWrapped("Current Transform");
972 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
973 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
974 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
975
976 ImGui::TextWrapped(
977 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
978 "The only difference is that MatrixFilter doesn't affect the effect "
979 "transform, whereas LocalMatrixFilter does.");
980 // Note: See this behavior in:
981 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
982 ImGui::Checkbox("Enable", &enable);
983 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
984 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
985 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
986
987 ImGui::TextWrapped(
988 "Rendering the filtered image within a layer can expose bounds "
989 "issues. If the rendered image gets cut off when this setting is "
990 "enabled, there's a coverage bug in the filter.");
991 ImGui::Checkbox("Render in layer", &enable_savelayer);
992 }
993 ImGui::End();
994
995 flutter::DisplayListBuilder builder;
996 flutter::DlPaint paint;
997
998 if (enable_savelayer) {
999 builder.SaveLayer(std::nullopt, nullptr);
1000 }
1001 {
1002 auto content_scale = GetContentScale();
1003 builder.Scale(content_scale.x, content_scale.y);
1004
1005 // Set the current transform
1006 auto ctm_matrix = Matrix::MakeRow(
1007 ctm_scale[0], ctm_skew[0], 0.0f, ctm_translation[0], //
1008 ctm_skew[1], ctm_scale[1], 0.0f, ctm_translation[1], //
1009 0, 0, 1, 0, //
1010 0, 0, 0, 1);
1011 builder.Transform(ctm_matrix);
1012
1013 // Set the matrix filter
1014 auto filter_matrix =
1015 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1016 skew[1], scale[1], 0.0f, translation[1], //
1017 0.0f, 0.0f, 1.0f, 0.0f, //
1018 0.0f, 0.0f, 0.0f, 1.0f);
1019
1020 if (enable) {
1021 switch (selected_matrix_type) {
1022 case 0: {
1023 auto filter = flutter::DlMatrixImageFilter(
1024 filter_matrix, flutter::DlImageSampling::kLinear);
1025 paint.setImageFilter(&filter);
1026 break;
1027 }
1028 case 1: {
1029 auto internal_filter =
1030 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1031 .shared();
1032 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1033 internal_filter);
1034 paint.setImageFilter(&filter);
1035 break;
1036 }
1037 }
1038 }
1039
1040 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(),
1041 flutter::DlImageSampling::kLinear, &paint);
1042 }
1043 if (enable_savelayer) {
1044 builder.Restore();
1045 }
1046
1047 return builder.Build();
1048 };
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(callback));
1051 }

References impeller::DlImageImpeller::Make(), and impeller::Matrix::MakeRow().

## ◆ TEST_P() [372/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1053 of file dl_unittests.cc.

1053 {
1054 auto callback = [&]() {
1055 static float translation[2] = {0, 0};
1056 static bool enable_save_layer = true;
1057
1058 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1059 ImGui::SliderFloat2("Translation", translation, -130, 130);
1060 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1061 ImGui::End();
1062
1063 flutter::DisplayListBuilder builder;
1064 builder.Save();
1065 builder.Scale(2.0, 2.0);
1066 flutter::DlPaint paint;
1067 paint.setColor(flutter::DlColor::kYellow());
1068 builder.DrawRect(DlRect::MakeWH(300, 300), paint);
1069 paint.setStrokeWidth(1.0);
1070 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1071 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1072 builder.DrawLine(DlPoint(150, 0), DlPoint(150, 300), paint);
1073 builder.DrawLine(DlPoint(0, 150), DlPoint(300, 150), paint);
1074
1075 flutter::DlPaint save_paint;
1076 DlRect bounds = DlRect::MakeXYWH(100, 100, 100, 100);
1077 Matrix translate_matrix =
1078 Matrix::MakeTranslation({translation[0], translation[1]});
1079 if (enable_save_layer) {
1080 auto filter = flutter::DlMatrixImageFilter(
1081 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1082 save_paint.setImageFilter(filter.shared());
1083 builder.SaveLayer(bounds, &save_paint);
1084 } else {
1085 builder.Save();
1086 builder.Transform(translate_matrix);
1087 }
1088
1089 Matrix filter_matrix;
1090 filter_matrix.Translate({150, 150});
1091 filter_matrix.Scale({0.2f, 0.2f});
1092 filter_matrix.Translate({-150, -150});
1093 auto filter = flutter::DlMatrixImageFilter(
1094 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1095
1096 save_paint.setImageFilter(filter.shared());
1097
1098 builder.SaveLayer(bounds, &save_paint);
1099 flutter::DlPaint paint2;
1100 paint2.setColor(flutter::DlColor::kBlue());
1101 builder.DrawRect(bounds, paint2);
1102 builder.Restore();
1103 builder.Restore();
1104 return builder.Build();
1105 };
1106
1107 ASSERT_TRUE(OpenPlaygroundHere(callback));
1108 }

References impeller::Matrix::MakeTranslation(), impeller::Matrix::Scale(), and impeller::Matrix::Translate().

## ◆ TEST_P() [373/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 394 of file dl_unittests.cc.

394 {
395 flutter::DisplayListBuilder builder;
396 flutter::DlPaint paint;
397
398 paint.setColor(flutter::DlColor::kRed());
399 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
400
401 builder.Translate(300, 300);
402 flutter::DlPathBuilder path_builder;
403 path_builder.AddCircle(DlPoint(0, 0), 100);
404 path_builder.AddCircle(DlPoint(0, 0), 50);
405 path_builder.SetFillType(flutter::DlPathFillType::kOdd);
406 builder.DrawPath(path_builder.TakePath(), paint);
407
408 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
409 }

## ◆ TEST_P() [374/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 843 of file dl_unittests.cc.

843 {
844 flutter::DisplayListBuilder builder;
845 std::vector<flutter::DlStrokeCap> caps = {
846 flutter::DlStrokeCap::kButt,
847 flutter::DlStrokeCap::kRound,
848 flutter::DlStrokeCap::kSquare,
849 };
850 flutter::DlPaint paint =
851 flutter::DlPaint() //
852 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
853 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
854 .setStrokeCap(flutter::DlStrokeCap::kButt) //
855 .setStrokeWidth(20);
856 DlPath path = DlPath::MakeLine({150, 50}, {150, 50});
857 for (auto cap : caps) {
858 paint.setStrokeCap(cap);
859 builder.DrawLine(DlPoint(50, 50), DlPoint(50, 50), paint);
860 builder.DrawPath(path, paint);
861 builder.Translate(0, 150);
862 }
863 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
864 }

## ◆ TEST_P() [375/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 914 of file dl_unittests.cc.

914 {
915 flutter::DisplayListBuilder builder;
916 std::vector<flutter::DlStrokeCap> caps = {
917 flutter::DlStrokeCap::kButt,
918 flutter::DlStrokeCap::kRound,
919 flutter::DlStrokeCap::kSquare,
920 };
921 flutter::DlPaint paint = //
922 flutter::DlPaint() //
923 .setColor(flutter::DlColor::kWhite()) //
924 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
925 .setStrokeWidth(0);
926 flutter::DlPaint outline_paint = //
927 flutter::DlPaint() //
928 .setColor(flutter::DlColor::kYellow()) //
929 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
930 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
931 .setStrokeWidth(1);
932 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
933 for (auto cap : caps) {
934 paint.setStrokeCap(cap);
935 builder.DrawLine(DlPoint(50, 50), DlPoint(60, 50), paint);
936 builder.DrawRect(DlRect::MakeLTRB(45, 45, 65, 55), outline_paint);
937 builder.DrawLine(DlPoint{100, 50}, DlPoint{100, 50}, paint);
938 if (cap != flutter::DlStrokeCap::kButt) {
939 builder.DrawRect(DlRect::MakeLTRB(95, 45, 105, 55), outline_paint);
940 }
941 builder.DrawPath(path, paint);
942 builder.DrawRect(path.GetBounds().Expand(5, 5), outline_paint);
943 builder.Translate(0, 150);
944 }
945 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
946 }

## ◆ TEST_P() [376/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1343 of file dl_unittests.cc.

1343 {
1344 flutter::DisplayListBuilder builder;
1345
1346 flutter::DlPaint fill_paint = //
1347 flutter::DlPaint() //
1348 .setColor(flutter::DlColor::kBlue()) //
1349 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1350 .setStrokeWidth(10);
1351 flutter::DlPaint stroke_paint = //
1352 flutter::DlPaint() //
1353 .setColor(flutter::DlColor::kGreen()) //
1354 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1355 .setStrokeWidth(10);
1356
1357 builder.DrawRoundRect(
1358 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1359 fill_paint);
1360 builder.DrawRoundRect(
1361 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1362 stroke_paint);
1363
1364 builder.DrawRoundRect(
1365 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1366 fill_paint);
1367 builder.DrawRoundRect(
1368 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1369 stroke_paint);
1370
1371 flutter::DlPaint reference_paint = //
1372 flutter::DlPaint() //
1373 .setColor(flutter::DlColor::kMidGrey()) //
1374 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1375 .setStrokeWidth(10);
1376
1377 builder.DrawRoundRect(
1378 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1379 reference_paint);
1380 builder.DrawRoundRect(
1381 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1382 reference_paint);
1383
1384 flutter::DlPaint clip_fill_paint = //
1385 flutter::DlPaint() //
1386 .setColor(flutter::DlColor::kCyan()) //
1387 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1388 .setStrokeWidth(10);
1389
1390 builder.Save();
1391 builder.ClipRoundRect(
1392 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1393 builder.DrawPaint(clip_fill_paint);
1394 builder.Restore();
1395
1396 builder.Save();
1397 builder.ClipRoundRect(
1398 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1399 builder.DrawPaint(clip_fill_paint);
1400 builder.Restore();
1401
1402 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1403 }

## ◆ TEST_P() [377/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1519 of file dl_unittests.cc.

1519 {
1520 flutter::DisplayListBuilder builder;
1521 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1522 Vector2 scale = GetContentScale();
1523 builder.Scale(scale.x, scale.y);
1524
1525 builder.Save();
1526 // We need a small transform op to avoid a deferred save
1527 builder.Translate(1.0f, 1.0f);
1528 auto solid_filter =
1529 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1530 flutter::DlPaint solid_alpha_paint =
1531 flutter::DlPaint() //
1532 .setMaskFilter(solid_filter) //
1533 .setColor(flutter::DlColor::kBlue()) //
1534 .setAlpha(0x7f);
1535 for (int x = 1; x <= 4; x++) {
1536 for (int y = 1; y <= 4; y++) {
1537 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1538 solid_alpha_paint);
1539 }
1540 }
1541 builder.Restore();
1542
1543 builder.Save();
1544 builder.Translate(500.0f, 0.0f);
1545 auto normal_filter =
1546 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1547 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1548 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1549 flutter::DlPaint normal_if_paint =
1550 flutter::DlPaint() //
1551 .setMaskFilter(solid_filter) //
1552 .setImageFilter(rotate_if) //
1553 .setColor(flutter::DlColor::kGreen()) //
1554 .setAlpha(0x7f);
1555 for (int x = 1; x <= 4; x++) {
1556 for (int y = 1; y <= 4; y++) {
1557 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1558 normal_if_paint);
1559 }
1560 }
1561 builder.Restore();
1562
1563 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1564 }

References impeller::Matrix::MakeRotationZ(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [378/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1496 of file dl_unittests.cc.

1496 {
1497 flutter::DisplayListBuilder builder;
1498 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1499
1500 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1501 builder.DrawCircle(DlPoint(300, 300), 200,
1502 flutter::DlPaint().setMaskFilter(&filter));
1503
1504 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1505 flutter::DlColor::kGreen()};
1506 const float stops[2] = {0.0, 1.0};
1507 auto linear = flutter::DlColorSource::MakeLinear(
1508 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1509 flutter::DlTileMode::kRepeat);
1510 flutter::DlPaint blend_paint =
1511 flutter::DlPaint() //
1512 .setColorSource(linear) //
1513 .setBlendMode(flutter::DlBlendMode::kScreen);
1514 builder.DrawPaint(blend_paint);
1515
1516 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1517 }

## ◆ TEST_P() [379/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1304 of file dl_unittests.cc.

1304 {
1305 flutter::DisplayListBuilder builder;
1306 std::vector<flutter::DlStrokeJoin> joins = {
1307 flutter::DlStrokeJoin::kBevel,
1308 flutter::DlStrokeJoin::kRound,
1309 flutter::DlStrokeJoin::kMiter,
1310 };
1311 flutter::DlPaint paint = //
1312 flutter::DlPaint() //
1313 .setColor(flutter::DlColor::kWhite()) //
1314 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1315 .setStrokeWidth(10);
1316 flutter::DlPaint stroke_paint = //
1317 flutter::DlPaint() //
1318 .setColor(flutter::DlColor::kWhite()) //
1319 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1320 .setStrokeWidth(10);
1321 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1322
1323 builder.Translate(300, 50);
1324 builder.Scale(0.8, 0.8);
1325 for (auto join : joins) {
1326 paint.setStrokeJoin(join);
1327 stroke_paint.setStrokeJoin(join);
1328 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1329 builder.DrawRect(DlRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1330 builder.DrawRoundRect(
1331 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 0, 100, 100), 30, 30),
1332 paint);
1333 builder.DrawRoundRect(
1334 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1335 stroke_paint);
1336 builder.DrawCircle(DlPoint(350, 50), 50, paint);
1337 builder.DrawCircle(DlPoint(350, 200), 50, stroke_paint);
1338 builder.Translate(0, 300);
1339 }
1340 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1341 }

## ◆ TEST_P() [380/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1405 of file dl_unittests.cc.

1405 {
1406 std::vector<const char*> blend_mode_names;
1407 std::vector<flutter::DlBlendMode> blend_mode_values;
1408 {
1409 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1410 // Pipeline blends (Porter-Duff alpha compositing)
1411 {"Clear", flutter::DlBlendMode::kClear},
1412 {"Source", flutter::DlBlendMode::kSrc},
1413 {"Destination", flutter::DlBlendMode::kDst},
1414 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1415 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1416 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1417 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1418 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1419 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1420 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1421 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1422 {"Xor", flutter::DlBlendMode::kXor},
1423 {"Plus", flutter::DlBlendMode::kPlus},
1424 {"Modulate", flutter::DlBlendMode::kModulate},
1425 // Advanced blends (color component blends)
1426 {"Screen", flutter::DlBlendMode::kScreen},
1427 {"Overlay", flutter::DlBlendMode::kOverlay},
1428 {"Darken", flutter::DlBlendMode::kDarken},
1429 {"Lighten", flutter::DlBlendMode::kLighten},
1430 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1431 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1432 {"HardLight", flutter::DlBlendMode::kHardLight},
1433 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1434 {"Difference", flutter::DlBlendMode::kDifference},
1435 {"Exclusion", flutter::DlBlendMode::kExclusion},
1436 {"Multiply", flutter::DlBlendMode::kMultiply},
1437 {"Hue", flutter::DlBlendMode::kHue},
1438 {"Saturation", flutter::DlBlendMode::kSaturation},
1439 {"Color", flutter::DlBlendMode::kColor},
1440 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1441 };
1442 assert(blends.size() ==
1443 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1444 for (const auto& [name, mode] : blends) {
1445 blend_mode_names.push_back(name);
1446 blend_mode_values.push_back(mode);
1447 }
1448 }
1449
1450 auto callback = [&]() {
1451 static int current_blend_index = 3;
1452 static float dst_alpha = 1;
1453 static float src_alpha = 1;
1454 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1455 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1456 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1457 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1458
1459 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1460 {
1461 ImGui::ListBox("Blending mode", &current_blend_index,
1462 blend_mode_names.data(), blend_mode_names.size());
1463 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1464 ImGui::ColorEdit4("Color A", color0);
1465 ImGui::ColorEdit4("Color B", color1);
1466 ImGui::ColorEdit4("Color C", color2);
1467 ImGui::ColorEdit4("Source Color", src_color);
1468 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1469 }
1470 ImGui::End();
1471
1472 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1473 DlPoint(200, 100), //
1474 DlPoint(300, 300)};
1475 std::vector<flutter::DlColor> colors = {
1476 toColor(color0).modulateOpacity(dst_alpha),
1477 toColor(color1).modulateOpacity(dst_alpha),
1478 toColor(color2).modulateOpacity(dst_alpha)};
1479
1480 auto vertices = flutter::DlVertices::Make(
1481 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1482 /*texture_coordinates=*/nullptr, colors.data());
1483
1484 flutter::DisplayListBuilder builder;
1485 flutter::DlPaint paint;
1486
1487 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1488 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1489 paint);
1490 return builder.Build();
1491 };
1492
1493 ASSERT_TRUE(OpenPlaygroundHere(callback));
1494 }
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:38

References toColor().

## ◆ TEST_P() [381/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 513 of file dl_unittests.cc.

513 {
514 auto texture = CreateTextureForFixture("embarcadero.jpg");
515 flutter::DisplayListBuilder builder;
516 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
517 flutter::DlPaint paint;
518 paint.setMaskFilter(&filter);
519 builder.SaveLayer(std::nullopt, &paint);
520 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
521 flutter::DlImageSampling::kNearestNeighbor);
522 builder.Restore();
523 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
524 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [382/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1256 of file dl_unittests.cc.

1256 {
1257 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1258 flutter::DlBlurStyle::kNormal, 10);
1259
1260 flutter::DisplayListBuilder builder;
1261
1262 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1263 flutter::DlColor::kGreen()};
1264 std::array<float, 2> stops = {0, 1};
1265 auto texture = CreateTextureForFixture("airplane.jpg");
1266 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1267 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1268 flutter::DlColorSource::MakeImage(
1269 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1270 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1271 &matrix),
1272 flutter::DlColorSource::MakeLinear(
1273 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1274 stops.data(), flutter::DlTileMode::kClamp),
1275 };
1276
1277 builder.Save();
1278 builder.Translate(0, 100);
1279 for (const auto& color_source : color_sources) {
1280 flutter::DlPaint paint;
1281 paint.setColorSource(color_source);
1282 paint.setMaskFilter(blur_filter);
1283
1284 builder.Save();
1285 builder.Translate(100, 0);
1286 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1287 builder.DrawRoundRect(
1288 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1289
1290 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1291 paint.setStrokeWidth(10);
1292 builder.Translate(200, 0);
1293 builder.DrawRoundRect(
1294 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1295
1296 builder.Restore();
1297 builder.Translate(0, 100);
1298 }
1299 builder.Restore();
1300
1301 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1302 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [383/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 796 of file dl_unittests.cc.

796 {
797 // Draw a nine patch image with colored corners and verify that the corner
798 // color does not leak outside the intended region.
799 auto texture = CreateTextureForFixture("nine_patch_corners.png");
800 flutter::DisplayListBuilder builder;
801 builder.DrawImageNine(DlImageImpeller::Make(texture),
802 DlIRect::MakeXYWH(10, 10, 1, 1),
803 DlRect::MakeXYWH(0, 0, 200, 100),
804 flutter::DlFilterMode::kNearest, nullptr);
805 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
806 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [384/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 213 of file dl_unittests.cc.

213 {
214 auto callback = [&]() {
215 flutter::DisplayListBuilder builder;
216 flutter::DlPaint paint;
217
218 paint.setColor(flutter::DlColor::kRed());
219 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
220
221 static float stroke_width = 10.0f;
222 static int selected_stroke_type = 0;
223 static int selected_join_type = 0;
224 const char* stroke_types[] = {"Butte", "Round", "Square"};
225 const char* join_type[] = {"kMiter", "Round", "kBevel"};
226
227 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
228 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
229 sizeof(stroke_types) / sizeof(char*));
230 ImGui::Combo("Join", &selected_join_type, join_type,
231 sizeof(join_type) / sizeof(char*));
232 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
233 ImGui::End();
234
235 flutter::DlStrokeCap cap;
236 flutter::DlStrokeJoin join;
237 switch (selected_stroke_type) {
238 case 0:
239 cap = flutter::DlStrokeCap::kButt;
240 break;
241 case 1:
242 cap = flutter::DlStrokeCap::kRound;
243 break;
244 case 2:
245 cap = flutter::DlStrokeCap::kSquare;
246 break;
247 default:
248 cap = flutter::DlStrokeCap::kButt;
249 break;
250 }
251 switch (selected_join_type) {
252 case 0:
253 join = flutter::DlStrokeJoin::kMiter;
254 break;
255 case 1:
256 join = flutter::DlStrokeJoin::kRound;
257 break;
258 case 2:
259 join = flutter::DlStrokeJoin::kBevel;
260 break;
261 default:
262 join = flutter::DlStrokeJoin::kMiter;
263 break;
264 }
265 paint.setStrokeCap(cap);
266 paint.setStrokeJoin(join);
267 paint.setStrokeWidth(stroke_width);
268
269 // Make rendering better to watch.
270 builder.Scale(1.5f, 1.5f);
271
272 // Rectangle
273 builder.Translate(100, 100);
274 builder.DrawRect(DlRect::MakeWH(100, 100), paint);
275
276 // Rounded rectangle
277 builder.Translate(150, 0);
278 builder.DrawRoundRect(
279 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10), paint);
280
281 // Double rounded rectangle
282 builder.Translate(150, 0);
283 builder.DrawDiffRoundRect(
284 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10),
285 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 10, 80, 30), 10, 10),
286 paint);
287
288 // Contour with duplicate join points
289 {
290 builder.Translate(150, 0);
291 flutter::DlPathBuilder path_builder;
292 path_builder.MoveTo(DlPoint(0, 0));
293 path_builder.LineTo(DlPoint(0, 0));
294 path_builder.LineTo(DlPoint(100, 0));
295 path_builder.LineTo(DlPoint(100, 0));
296 path_builder.LineTo(DlPoint(100, 100));
297 builder.DrawPath(path_builder.TakePath(), paint);
298 }
299
300 // Contour with duplicate start and end points
301
302 // Line.
303 builder.Translate(200, 0);
304 {
305 builder.Save();
306
307 flutter::DlPathBuilder line_path_builder;
308 line_path_builder.MoveTo(DlPoint(0, 0));
309 line_path_builder.MoveTo(DlPoint(0, 0));
310 line_path_builder.LineTo(DlPoint(0, 0));
311 line_path_builder.LineTo(DlPoint(0, 0));
312 line_path_builder.LineTo(DlPoint(50, 50));
313 line_path_builder.LineTo(DlPoint(50, 50));
314 line_path_builder.LineTo(DlPoint(100, 0));
315 line_path_builder.LineTo(DlPoint(100, 0));
316 DlPath line_path = line_path_builder.TakePath();
317 builder.DrawPath(line_path, paint);
318
319 builder.Translate(0, 100);
320 builder.DrawPath(line_path, paint);
321
322 builder.Translate(0, 100);
323 flutter::DlPathBuilder line_path_builder2;
324 line_path_builder2.MoveTo(DlPoint(0, 0));
325 line_path_builder2.LineTo(DlPoint(0, 0));
326 line_path_builder2.LineTo(DlPoint(0, 0));
327 builder.DrawPath(line_path_builder2.TakePath(), paint);
328
329 builder.Restore();
330 }
331
332 // Cubic.
333 builder.Translate(150, 0);
334 {
335 builder.Save();
336
337 flutter::DlPathBuilder cubic_path;
338 cubic_path.MoveTo(DlPoint(0, 0));
339 cubic_path.CubicCurveTo(DlPoint(0, 0), //
340 DlPoint(140.0, 100.0), //
341 DlPoint(140, 20));
342 builder.DrawPath(cubic_path.TakePath(), paint);
343
344 builder.Translate(0, 100);
345 flutter::DlPathBuilder cubic_path2;
346 cubic_path2.MoveTo(DlPoint(0, 0));
347 cubic_path2.CubicCurveTo(DlPoint(0, 0), //
348 DlPoint(0, 0), //
349 DlPoint(150, 150));
350 builder.DrawPath(cubic_path2.TakePath(), paint);
351
352 builder.Translate(0, 100);
353 flutter::DlPathBuilder cubic_path3;
354 cubic_path3.MoveTo(DlPoint(0, 0));
355 cubic_path3.CubicCurveTo(DlPoint(0, 0), //
356 DlPoint(0, 0), //
357 DlPoint(0, 0));
358 builder.DrawPath(cubic_path3.TakePath(), paint);
359
360 builder.Restore();
361 }
362
363 // Quad.
364 builder.Translate(200, 0);
365 {
366 builder.Save();
367
368 flutter::DlPathBuilder quad_path;
369 quad_path.MoveTo(DlPoint(0, 0));
370 quad_path.MoveTo(DlPoint(0, 0));
371 quad_path.QuadraticCurveTo(DlPoint(100, 40), DlPoint(50, 80));
372 builder.DrawPath(quad_path.TakePath(), paint);
373
374 builder.Translate(0, 150);
375 flutter::DlPathBuilder quad_path2;
376 quad_path2.MoveTo(DlPoint(0, 0));
377 quad_path2.MoveTo(DlPoint(0, 0));
378 quad_path2.QuadraticCurveTo(DlPoint(0, 0), DlPoint(100, 100));
379 builder.DrawPath(quad_path2.TakePath(), paint);
380
381 builder.Translate(0, 100);
382 flutter::DlPathBuilder quad_path3;
383 quad_path3.MoveTo(DlPoint(0, 0));
384 quad_path3.QuadraticCurveTo(DlPoint(0, 0), DlPoint(0, 0));
385 builder.DrawPath(quad_path3.TakePath(), paint);
386
387 builder.Restore();
388 }
389 return builder.Build();
390 };
391 ASSERT_TRUE(OpenPlaygroundHere(callback));
392 }

## ◆ TEST_P() [385/545]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 488 of file dl_unittests.cc.

488 {
489 flutter::DisplayListBuilder builder;
490 flutter::DlPaint paint;
491 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
492
493 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
494 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
495
496 // Draw a blue filled rectangle so the text is easier to see.
497 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
498 paint.setColor(mat_blue);
499 builder.DrawRect(DlRect::MakeXYWH(0, 0, 500, 500), paint);
500
501 // Draw stacked text, with stroked text on top.
502 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
503 paint.setColor(flutter::DlColor::kWhite());
504 builder.DrawTextBlob(text_blob, 250, 250, paint);
505
506 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
507 paint.setColor(flutter::DlColor::kBlack());
508 builder.DrawTextBlob(text_blob, 250, 250, paint);
509
510 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
511 }

## ◆ TEST_P() [386/545]

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() [387/545]

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() [388/545]

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() [389/545]

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() [390/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 878 of file entity_unittests.cc.

878 {
879 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
880 static float scale = 20;
881
882 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
883 ImGui::SliderFloat("Scale", &scale, 1, 100);
884 ImGui::End();
885
886 Entity entity;
887 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
888 auto path = flutter::DlPathBuilder{}
889 .MoveTo({97.325, 34.818})
890 .CubicCurveTo({98.50862885295136, 34.81812293973836},
891 {99.46822048142015, 33.85863261475589},
892 {99.46822048142015, 32.67499810206613})
893 .CubicCurveTo({99.46822048142015, 31.491363589376355},
894 {98.50862885295136, 30.53187326439389},
895 {97.32499434685802, 30.531998226542708})
896 .CubicCurveTo({96.14153655073771, 30.532123170035373},
897 {95.18222070648729, 31.491540299350355},
898 {95.18222070648729, 32.67499810206613})
899 .CubicCurveTo({95.18222070648729, 33.85845590478189},
900 {96.14153655073771, 34.81787303409686},
901 {97.32499434685802, 34.81799797758954})
902 .Close()
903 .TakePath();
904 entity.SetTransform(
905 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
906
907 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
908
909 auto contents = std::make_shared<SolidColorContents>();
910 contents->SetColor(Color::Red());
911 contents->SetGeometry(geom.get());
912
913 entity.SetContents(contents);
914 return entity.Render(context, pass);
915 };
916 ASSERT_TRUE(OpenPlaygroundHere(callback));
917 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [391/545]

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.GetTransientsBuffer()));
833
834 VS::FrameInfo frame_info;
835 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
836 VS::BindFrameInfo(
837 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
838 FS::FragInfo frag_info;
839 frag_info.color = color.Premultiply();
840 FS::BindFragInfo(
841 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
842 return pass.Draw().ok();
843 };
844
845 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
846 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
847 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
848 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
849 static int current_blend_index = 3;
850 ImGui::ListBox("Blending mode", &current_blend_index,
851 blend_mode_names.data(), blend_mode_names.size());
852 ImGui::End();
853
854 BlendMode selected_mode = blend_mode_values[current_blend_index];
855
856 Point a, b, c, d;
857 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
858 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
859 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
860 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
861 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
862 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
863
864 bool result = true;
865 result = result &&
866 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
867 pass.GetRenderTargetSize().height),
868 Color(), BlendMode::kClear);
869 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
870 BlendMode::kSrcOver);
871 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
872 selected_mode);
873 return result;
874 };
875 ASSERT_TRUE(OpenPlaygroundHere(callback));
876 }
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::GetTransientsBuffer(), 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() [392/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1319 of file entity_unittests.cc.

1319 {
1320 auto fill = std::make_shared<SolidColorContents>();
1321 auto geom = Geometry::MakeFillPath(
1322 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1323 fill->SetGeometry(geom.get());
1324 fill->SetColor(Color::CornflowerBlue());
1325 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1326 FilterInput::Make(fill), Radius{3}, Radius{4});
1327
1328 {
1329 Entity e;
1330 e.SetTransform(Matrix());
1331 auto actual = border_mask_blur->GetCoverage(e);
1332 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1333 ASSERT_TRUE(actual.has_value());
1334 ASSERT_RECT_NEAR(actual.value(), expected);
1335 }
1336
1337 {
1338 Entity e;
1339 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1340 auto actual = border_mask_blur->GetCoverage(e);
1341 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1342 ASSERT_TRUE(actual.has_value());
1343 ASSERT_RECT_NEAR(actual.value(), expected);
1344 }
1345 }
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() [393/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2314 of file entity_unittests.cc.

2314 {
2315 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2316
2317 EXPECT_TRUE(path.GetBounds().IsEmpty());
2318
2319 auto geom = Geometry::MakeFillPath(path);
2320
2321 Entity entity;
2322 RenderTarget target =
2323 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2324 *GetContext(), {1, 1}, 1u);
2325 testing::MockRenderPass render_pass(GetContext(), target);
2326 auto position_result =
2327 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2328
2329 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2330
2331 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2332 }

References impeller::GeometryResult::kNormal, impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [394/545]

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() [395/545]

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() [396/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2334 of file entity_unittests.cc.

2334 {
2335 flutter::DlPath path = flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 0, 0));
2336
2337 EXPECT_TRUE(path.GetBounds().IsEmpty());
2338
2339 auto contents = std::make_shared<SolidColorContents>();
2340 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2341 contents->SetGeometry(geom.get());
2342 contents->SetColor(Color::Red());
2343
2344 Entity entity;
2345 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2346 entity.SetContents(contents);
2347
2348 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2349 }

References impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [397/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2158 of file entity_unittests.cc.

2158 {
2159 Entity entity;
2160 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2161 auto src_contents = std::make_shared<SolidColorContents>();
2162 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2163 src_contents->SetGeometry(src_geom.get());
2164 src_contents->SetColor(Color::Red());
2165
2166 auto dst_contents = std::make_shared<SolidColorContents>();
2167 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2168 dst_contents->SetGeometry(dst_geom.get());
2169 dst_contents->SetColor(Color::Blue());
2170
2171 auto contents = ColorFilterContents::MakeBlend(
2172 BlendMode::kSrcOver, {FilterInput::Make(dst_contents, false),
2173 FilterInput::Make(src_contents, false)});
2174 entity.SetContents(std::move(contents));
2175 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2176 }

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() [398/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1921 of file entity_unittests.cc.

1921 {
1922 auto image = CreateTextureForFixture("boston.jpg");
1923 auto filter = ColorFilterContents::MakeBlend(
1924 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1925
1926 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1927 Entity entity;
1928 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1929 Matrix::MakeTranslation({500, 300}) *
1930 Matrix::MakeScale(Vector2{0.5, 0.5}));
1931 entity.SetContents(filter);
1932 return entity.Render(context, pass);
1933 };
1934 ASSERT_TRUE(OpenPlaygroundHere(callback));
1935 }

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() [399/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1937 of file entity_unittests.cc.

1937 {
1938 auto image = CreateTextureForFixture("boston.jpg");
1939 auto filter = ColorFilterContents::MakeBlend(
1940 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1941
1942 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1943 Entity entity;
1944 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1945 Matrix::MakeTranslation({500, 300}) *
1946 Matrix::MakeScale(Vector2{0.5, 0.5}));
1947 entity.SetContents(filter);
1948 return entity.Render(context, pass);
1949 };
1950 ASSERT_TRUE(OpenPlaygroundHere(callback));
1951 }

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() [400/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1969 of file entity_unittests.cc.

1969 {
1970 auto image = CreateTextureForFixture("boston.jpg");
1971 auto filter = ColorFilterContents::MakeBlend(
1972 BlendMode::kDst, FilterInput::Make({image}), Color::Red());
1973
1974 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1975 Entity entity;
1976 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1977 Matrix::MakeTranslation({500, 300}) *
1978 Matrix::MakeScale(Vector2{0.5, 0.5}));
1979 entity.SetContents(filter);
1980 return entity.Render(context, pass);
1981 };
1982 ASSERT_TRUE(OpenPlaygroundHere(callback));
1983 }

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() [401/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1953 of file entity_unittests.cc.

1953 {
1954 auto image = CreateTextureForFixture("boston.jpg");
1955 auto filter = ColorFilterContents::MakeBlend(
1956 BlendMode::kSrc, FilterInput::Make({image}), Color::Red());
1957
1958 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1959 Entity entity;
1960 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1961 Matrix::MakeTranslation({500, 300}) *
1962 Matrix::MakeScale(Vector2{0.5, 0.5}));
1963 entity.SetContents(filter);
1964 return entity.Render(context, pass);
1965 };
1966 ASSERT_TRUE(OpenPlaygroundHere(callback));
1967 }

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() [402/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 1985 of file entity_unittests.cc.

1985 {
1986 auto image = CreateTextureForFixture("boston.jpg");
1987 auto filter = ColorFilterContents::MakeBlend(
1988 BlendMode::kSrcIn, FilterInput::Make({image}), Color::Red());
1989
1990 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1991 Entity entity;
1992 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1993 Matrix::MakeTranslation({500, 300}) *
1994 Matrix::MakeScale(Vector2{0.5, 0.5}));
1995 entity.SetContents(filter);
1996 return entity.Render(context, pass);
1997 };
1998 ASSERT_TRUE(OpenPlaygroundHere(callback));
1999 }

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() [403/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1446 of file entity_unittests.cc.

1446 {
1447 // Set up a simple color background.
1448 auto fill = std::make_shared<SolidColorContents>();
1449 auto geom = Geometry::MakeFillPath(
1450 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1451 fill->SetGeometry(geom.get());
1452 fill->SetColor(Color::Coral());
1453
1454 // Set the color matrix filter.
1455 ColorMatrix matrix = {
1456 1, 1, 1, 1, 1, //
1457 1, 1, 1, 1, 1, //
1458 1, 1, 1, 1, 1, //
1459 1, 1, 1, 1, 1, //
1460 };
1461
1462 auto filter =
1463 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1464
1465 Entity e;
1466 e.SetTransform(Matrix());
1467
1468 // Confirm that the actual filter coverage matches the expected coverage.
1469 auto actual = filter->GetCoverage(e);
1470 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1471
1472 ASSERT_TRUE(actual.has_value());
1473 ASSERT_RECT_NEAR(actual.value(), expected);
1474 }

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() [404/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1476 of file entity_unittests.cc.

1476 {
1477 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1478 ASSERT_TRUE(bay_bridge);
1479
1480 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1481 // UI state.
1482 static ColorMatrix color_matrix = {
1483 1, 0, 0, 0, 0, //
1484 0, 3, 0, 0, 0, //
1485 0, 0, 1, 0, 0, //
1486 0, 0, 0, 1, 0, //
1487 };
1488 static float offset[2] = {500, 400};
1489 static float rotation = 0;
1490 static float scale[2] = {0.65, 0.65};
1491 static float skew[2] = {0, 0};
1492
1493 // Define the ImGui
1494 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1495 {
1496 std::string label = "##1";
1497 for (int i = 0; i < 20; i += 5) {
1498 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1499 &(color_matrix.array[i]), 5, nullptr, nullptr,
1500 "%.2f", 0);
1501 label[2]++;
1502 }
1503
1504 ImGui::SliderFloat2("Translation", &offset[0], 0,
1505 pass.GetRenderTargetSize().width);
1506 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1507 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1508 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1509 }
1510 ImGui::End();
1511
1512 // Set the color matrix filter.
1513 auto filter = ColorFilterContents::MakeColorMatrix(
1514 FilterInput::Make(bay_bridge), color_matrix);
1515
1516 // Define the entity with the color matrix filter.
1517 Entity entity;
1518 entity.SetTransform(
1519 Matrix::MakeScale(GetContentScale()) *
1520 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1521 Matrix::MakeRotationZ(Radians(rotation)) *
1522 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1523 Matrix::MakeSkew(skew[0], skew[1]) *
1524 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1525 entity.SetContents(filter);
1526 entity.Render(context, pass);
1527
1528 return true;
1529 };
1530
1531 ASSERT_TRUE(OpenPlaygroundHere(callback));
1532 }

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() [405/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2046 of file entity_unittests.cc.

2046 {
2047 Matrix matrix;
2048 ConicalGradientContents contents;
2049 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2050 contents.SetGeometry(geom.get());
2051
2052 contents.SetColors({Color::CornflowerBlue()});
2053 EXPECT_FALSE(contents.IsOpaque(matrix));
2054 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2055 EXPECT_FALSE(contents.IsOpaque(matrix));
2056
2057 // Create stroked path that required alpha coverage.
2058 geom = Geometry::MakeStrokePath(
2059 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2060 {.width = 0.05f});
2061 contents.SetGeometry(geom.get());
2062 contents.SetColors({Color::CornflowerBlue()});
2063
2064 EXPECT_FALSE(contents.IsOpaque(matrix));
2065 }

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() [406/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2225 of file entity_unittests.cc.

2225 {
2226 ContentContextOptions opts;
2227 auto hash_a = opts.ToKey();
2228
2229 opts.blend_mode = BlendMode::kColorBurn;
2230 auto hash_b = opts.ToKey();
2231
2232 opts.has_depth_stencil_attachments = false;
2233 auto hash_c = opts.ToKey();
2234
2235 opts.primitive_type = PrimitiveType::kPoint;
2236 auto hash_d = opts.ToKey();
2237
2238 EXPECT_NE(hash_a, hash_b);
2239 EXPECT_NE(hash_b, hash_c);
2240 EXPECT_NE(hash_c, hash_d);
2241 }

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() [407/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1242 of file entity_unittests.cc.

1242 {
1243 Entity entity;
1244 entity.SetContents(std::make_shared<SolidColorContents>());
1245 ASSERT_FALSE(entity.GetCoverage().has_value());
1246 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [408/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2001 of file entity_unittests.cc.

2001 {
2002 auto arrow_head = flutter::DlPathBuilder{}
2003 .MoveTo({50, 120})
2004 .LineTo({120, 190})
2005 .LineTo({190, 120})
2006 .TakePath();
2007 auto geometry = Geometry::MakeStrokePath(arrow_head, //
2008 {
2009 .width = 15.0f,
2010 .cap = Cap::kRound,
2011 .join = Join::kRound,
2012 .miter_limit = 4.0f,
2013 });
2014
2015 auto transform = Matrix::MakeTranslation({300, 300}) *
2016 Matrix::MakeRotationZ(Radians(kPiOver2));
2017 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2018 // due to floating point inaccuracy in the transcendental trig functions.
2019 // e[1][0] is the intended negative value that we care about (-1.0) as it
2020 // comes from the rotation of pi/2.
2021 EXPECT_LT(transform.e[1][0], 0.0f);
2022 auto coverage = geometry->GetCoverage(transform);
2023 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2024 }

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() [409/545]

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() [410/545]

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() [411/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2209 of file entity_unittests.cc.

2209 {
2210 auto content_context = GetContentContext();
2211 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2212 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2213 });
2214
2215 auto decal_supported = static_cast<Scalar>(
2216 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2217 std::vector<Scalar> expected_constants = {decal_supported};
2218 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2219 expected_constants);
2220 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [412/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipse |
| ) |  |

Definition at line 2384 of file entity_unittests.cc.

2384 {
2385 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2386 // UI state.
2387 static int style_index = 0;
2388 static float center[2] = {830, 830};
2389 static float size[2] = {600, 600};
2390 static bool horizontal_symmetry = true;
2391 static bool vertical_symmetry = true;
2392 static bool corner_symmetry = true;
2393
2394 const char* style_options[] = {"Fill", "Stroke"};
2395
2396 // Initially radius_tl[0] will be mirrored to all 8 values since all 3
2397 // symmetries are enabled.
2398 static std::array<float, 2> radius_tl = {200};
2399 static std::array<float, 2> radius_tr;
2400 static std::array<float, 2> radius_bl;
2401 static std::array<float, 2> radius_br;
2402
2403 auto AddRadiusControl = [](std::array<float, 2>& radii, const char* tb_name,
2404 const char* lr_name) {
2405 std::string name = "Radius";
2406 if (!horizontal_symmetry || !vertical_symmetry) {
2407 name += ":";
2408 }
2409 if (!vertical_symmetry) {
2410 name = name + " " + tb_name;
2411 }
2412 if (!horizontal_symmetry) {
2413 name = name + " " + lr_name;
2414 }
2415 if (corner_symmetry) {
2416 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2417 } else {
2418 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2419 }
2420 };
2421
2422 if (corner_symmetry) {
2423 radius_tl[1] = radius_tl[0];
2424 radius_tr[1] = radius_tr[0];
2425 radius_bl[1] = radius_bl[0];
2426 radius_br[1] = radius_br[0];
2427 }
2428
2429 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2430 {
2431 ImGui::Combo("Style", &style_index, style_options,
2432 sizeof(style_options) / sizeof(char*));
2433 ImGui::SliderFloat2("Center", center, 0, 1000);
2434 ImGui::SliderFloat2("Size", size, 0, 1000);
2435 ImGui::Checkbox("Symmetry: Horizontal", &horizontal_symmetry);
2436 ImGui::Checkbox("Symmetry: Vertical", &vertical_symmetry);
2437 ImGui::Checkbox("Symmetry: Corners", &corner_symmetry);
2438 AddRadiusControl(radius_tl, "Top", "Left");
2439 if (!horizontal_symmetry) {
2440 AddRadiusControl(radius_tr, "Top", "Right");
2441 } else {
2442 radius_tr = radius_tl;
2443 }
2444 if (!vertical_symmetry) {
2445 AddRadiusControl(radius_bl, "Bottom", "Left");
2446 } else {
2447 radius_bl = radius_tl;
2448 }
2449 if (!horizontal_symmetry && !vertical_symmetry) {
2450 AddRadiusControl(radius_br, "Bottom", "Right");
2451 } else {
2452 if (horizontal_symmetry) {
2453 radius_br = radius_bl;
2454 } else {
2455 radius_br = radius_tr;
2456 }
2457 }
2458 }
2459
2460 ImGui::End();
2461
2462 RoundingRadii radii{
2463 .top_left = {radius_tl[0], radius_tl[1]},
2464 .top_right = {radius_tr[0], radius_tr[1]},
2465 .bottom_left = {radius_bl[0], radius_bl[1]},
2466 .bottom_right = {radius_br[0], radius_br[1]},
2467 };
2468
2469 auto rse = RoundSuperellipse::MakeRectRadii(
2470 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}), radii);
2471
2472 flutter::DlPath path;
2473 std::unique_ptr<Geometry> geom;
2474 if (style_index == 0) {
2475 geom = std::make_unique<RoundSuperellipseGeometry>(
2476 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}),
2477 radii);
2478 } else {
2479 path = flutter::DlPath::MakeRoundSuperellipse(rse);
2480 geom = Geometry::MakeStrokePath(path, {.width = 2.0f});
2481 }
2482
2483 auto contents = std::make_shared<SolidColorContents>();
2484 contents->SetColor(Color::Red());
2485 contents->SetGeometry(geom.get());
2486
2487 Entity entity;
2488 entity.SetContents(contents);
2489
2490 return entity.Render(context, pass);
2491 };
2492
2493 ASSERT_TRUE(OpenPlaygroundHere(callback));
2494 }
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() [413/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2351 of file entity_unittests.cc.

2351 {
2352 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2353 // UI state.
2354 static float alpha = 10;
2355 static float beta = 10;
2356 static float radius = 40;
2357 static int degree = 4;
2358 static Color color = Color::Red();
2359
2360 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2361 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2362 ImGui::SliderFloat("Beta", &beta, 0, 100);
2363 ImGui::SliderInt("Degreee", &degree, 1, 20);
2364 ImGui::SliderFloat("Radius", &radius, 0, 400);
2365 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2366 ImGui::End();
2367
2368 auto contents = std::make_shared<SolidColorContents>();
2369 std::unique_ptr<SuperellipseGeometry> geom =
2370 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2371 alpha, beta);
2372 contents->SetColor(color);
2373 contents->SetGeometry(geom.get());
2374
2375 Entity entity;
2376 entity.SetContents(contents);
2377
2378 return entity.Render(context, pass);
2379 };
2380
2381 ASSERT_TRUE(OpenPlaygroundHere(callback));
2382 }

References impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [414/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2300 of file entity_unittests.cc.

2300 {
2301 if (GetParam() != PlaygroundBackend::kVulkan) {
2302 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2303 }
2304 EXPECT_DEATH(
2305 // The easiest way to trigger a validation error is to try to compile
2306 // a shader with an unsupported pixel format.
2307 GetContentContext()->GetBlendColorBurnPipeline({
2308 .color_attachment_pixel_format = PixelFormat::kUnknown,
2309 .has_depth_stencil_attachments = false,
2310 }),
2311 "");
2312 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [415/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2269 of file entity_unittests.cc.

2269 {
2270 RenderTarget target;
2271 testing::MockRenderPass mock_pass(GetContext(), target);
2272
2273 auto get_result = [this, &mock_pass](const flutter::DlPath& path) {
2274 auto geometry = Geometry::MakeFillPath(
2275 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2276 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2277 };
2278
2279 // Convex path
2280 {
2281 GeometryResult result =
2282 get_result(flutter::DlPath::MakeRect(Rect::MakeLTRB(0, 0, 100, 100)));
2283 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2284 }
2285
2286 // Concave path
2287 {
2288 flutter::DlPath path = flutter::DlPathBuilder{}
2289 .MoveTo({0, 0})
2290 .LineTo({100, 0})
2291 .LineTo({100, 100})
2292 .LineTo({51, 50})
2293 .Close()
2294 .TakePath();
2295 GeometryResult result = get_result(path);
2296 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2297 }
2298 }

References impeller::Close(), impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::GeometryResult::mode.

## ◆ TEST_P() [416/545]

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() [417/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 919 of file entity_unittests.cc.

919 {
920 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
921 auto boston = CreateTextureForFixture("boston.jpg");
922 auto kalimba = CreateTextureForFixture("kalimba.jpg");
923 ASSERT_TRUE(bridge && boston && kalimba);
924
925 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
926 auto fi_bridge = FilterInput::Make(bridge);
927 auto fi_boston = FilterInput::Make(boston);
928 auto fi_kalimba = FilterInput::Make(kalimba);
929
930 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
931 BlendMode::kModulate, {fi_kalimba, fi_boston});
932
933 auto blend1 = ColorFilterContents::MakeBlend(
934 BlendMode::kScreen,
935 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
936
937 Entity entity;
938 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
939 Matrix::MakeTranslation({500, 300}) *
940 Matrix::MakeScale(Vector2{0.5, 0.5}));
941 entity.SetContents(blend1);
942 return entity.Render(context, pass);
943 };
944 ASSERT_TRUE(OpenPlaygroundHere(callback));
945 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [418/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 947 of file entity_unittests.cc.

947 {
948 auto boston =
949 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
950 ASSERT_TRUE(boston);
951
952 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
953 const char* input_type_names[] = {"Texture", "Solid Color"};
954 const char* blur_type_names[] = {"Image blur", "Mask blur"};
955 const char* pass_variation_names[] = {"New"};
956 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
957 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
958 const FilterContents::BlurStyle blur_styles[] = {
959 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
960 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
961 const Entity::TileMode tile_modes[] = {
962 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
963 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
964
965 // UI state.
966 static int selected_input_type = 0;
967 static Color input_color = Color::Black();
968 static int selected_blur_type = 0;
969 static int selected_pass_variation = 0;
970 static bool combined_sigma = false;
971 static float blur_amount_coarse[2] = {0, 0};
972 static float blur_amount_fine[2] = {10, 10};
973 static int selected_blur_style = 0;
974 static int selected_tile_mode = 3;
975 static Color cover_color(1, 0, 0, 0.2);
976 static Color bounds_color(0, 1, 0, 0.1);
977 static float offset[2] = {500, 400};
978 static float rotation = 0;
979 static float scale[2] = {0.65, 0.65};
980 static float skew[2] = {0, 0};
981 static float path_rect[4] = {0, 0,
982 static_cast<float>(boston->GetSize().width),
983 static_cast<float>(boston->GetSize().height)};
984
985 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
986 {
987 ImGui::Combo("Input type", &selected_input_type, input_type_names,
988 sizeof(input_type_names) / sizeof(char*));
989 if (selected_input_type == 0) {
990 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
991 } else {
992 ImGui::ColorEdit4("Input color",
993 reinterpret_cast<float*>(&input_color));
994 }
995 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
996 sizeof(blur_type_names) / sizeof(char*));
997 if (selected_blur_type == 0) {
998 ImGui::Combo("Pass variation", &selected_pass_variation,
999 pass_variation_names,
1000 sizeof(pass_variation_names) / sizeof(char*));
1001 }
1002 ImGui::Checkbox("Combined sigma", &combined_sigma);
1003 if (combined_sigma) {
1004 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1005 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1006 blur_amount_coarse[1] = blur_amount_coarse[0];
1007 blur_amount_fine[1] = blur_amount_fine[0];
1008 } else {
1009 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1010 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1011 }
1012 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1013 sizeof(blur_style_names) / sizeof(char*));
1014 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1015 sizeof(tile_mode_names) / sizeof(char*));
1016 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1017 ImGui::ColorEdit4("Bounds color ",
1018 reinterpret_cast<float*>(&bounds_color));
1019 ImGui::SliderFloat2("Translation", offset, 0,
1020 pass.GetRenderTargetSize().width);
1021 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1022 ImGui::SliderFloat2("Scale", scale, 0, 3);
1023 ImGui::SliderFloat2("Skew", skew, -3, 3);
1024 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1025 }
1026 ImGui::End();
1027
1028 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1029 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1030
1031 std::shared_ptr<Contents> input;
1032 Size input_size;
1033
1034 auto input_rect =
1035 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1036
1037 std::unique_ptr<Geometry> solid_color_input;
1038 if (selected_input_type == 0) {
1039 auto texture = std::make_shared<TextureContents>();
1040 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1041 texture->SetDestinationRect(input_rect);
1042 texture->SetTexture(boston);
1043 texture->SetOpacity(input_color.alpha);
1044
1045 input = texture;
1046 input_size = input_rect.GetSize();
1047 } else {
1048 auto fill = std::make_shared<SolidColorContents>();
1049 fill->SetColor(input_color);
1050 solid_color_input =
1051 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1052
1053 fill->SetGeometry(solid_color_input.get());
1054
1055 input = fill;
1056 input_size = input_rect.GetSize();
1057 }
1058
1059 std::shared_ptr<FilterContents> blur;
1060 switch (selected_pass_variation) {
1061 case 0:
1062 blur = std::make_shared<GaussianBlurFilterContents>(
1063 blur_sigma_x.sigma, blur_sigma_y.sigma,
1064 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1065 /*geometry=*/nullptr);
1066 blur->SetInputs({FilterInput::Make(input)});
1067 break;
1068 case 1:
1069 blur = FilterContents::MakeGaussianBlur(
1070 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1071 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1072 break;
1073 };
1074 FML_CHECK(blur);
1075
1076 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1077 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1078 blur_styles[selected_blur_style]);
1079
1080 auto ctm = Matrix::MakeScale(GetContentScale()) *
1081 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1082 Matrix::MakeRotationZ(Radians(rotation)) *
1083 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1084 Matrix::MakeSkew(skew[0], skew[1]) *
1085 Matrix::MakeTranslation(-Point(input_size) / 2);
1086
1087 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1088
1089 Entity entity;
1090 entity.SetContents(target_contents);
1091 entity.SetTransform(ctm);
1092
1093 entity.Render(context, pass);
1094
1095 // Renders a red "cover" rectangle that shows the original position of the
1096 // unfiltered input.
1097 Entity cover_entity;
1098 std::unique_ptr<Geometry> geom =
1099 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1100 auto contents = std::make_shared<SolidColorContents>();
1101 contents->SetColor(cover_color);
1102 contents->SetGeometry(geom.get());
1103 cover_entity.SetContents(std::move(contents));
1104 cover_entity.SetTransform(ctm);
1105 cover_entity.Render(context, pass);
1106
1107 // Renders a green bounding rect of the target filter.
1108 Entity bounds_entity;
1109 std::optional<Rect> target_contents_coverage =
1110 target_contents->GetCoverage(entity);
1111 if (target_contents_coverage.has_value()) {
1112 std::unique_ptr<Geometry> geom =
1113 Geometry::MakeFillPath(flutter::DlPath::MakeRect(
1114 target_contents->GetCoverage(entity).value()));
1115 auto contents = std::make_shared<SolidColorContents>();
1116 contents->SetColor(bounds_color);
1117 contents->SetGeometry(geom.get());
1118
1119 bounds_entity.SetContents(contents);
1120 bounds_entity.SetTransform(Matrix());
1121 bounds_entity.Render(context, pass);
1122 }
1123
1124 return true;
1125 };
1126 ASSERT_TRUE(OpenPlaygroundHere(callback));
1127 }

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() [419/545]

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() [420/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantStrokePathAllocation |
| ) |  |

Definition at line 2526 of file entity_unittests.cc.

2526 {
2527 flutter::DlPathBuilder builder;
2528 for (int i = 0; i < 10000; i++) {
2529 builder.LineTo(Point(i, i));
2530 }
2531 flutter::DlPath path = builder.TakePath();
2532 auto geom = Geometry::MakeStrokePath(path, {.width = 10.0f});
2533
2534 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2535 Entity entity;
2536
2537 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2538
2539 RenderTargetAllocator allocator(
2540 content_context.GetContext()->GetResourceAllocator());
2541
2542 auto render_target = allocator.CreateOffscreen(
2543 *content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);
2544 auto pass = cmd_buffer->CreateRenderPass(render_target);
2545
2546 GeometryResult result =
2547 geom->GetPositionBuffer(content_context, entity, *pass);
2548
2549 // Validate the buffer data overflowed the small buffer
2550 EXPECT_GT(result.vertex_buffer.vertex_count, kPointArenaSize);
2551
2552 // Validate that there are no uninitialized points near the gap.
2553 Point* written_data = reinterpret_cast<Point*>(
2554 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2555 result.vertex_buffer.vertex_buffer.GetRange().offset));
2556
2557 std::vector<Point> expected = {
2558 Point(2043.46, 2050.54), //
2559 Point(2050.54, 2043.46), //
2560 Point(2044.46, 2051.54), //
2561 Point(2051.54, 2044.46), //
2562 Point(2045.46, 2052.54) //
2563 };
2564
2565 Point point = written_data[kPointArenaSize - 2];
2566 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2567 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2568
2569 point = written_data[kPointArenaSize - 1];
2570 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2571 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2572
2573 point = written_data[kPointArenaSize];
2574 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2575 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2576
2577 point = written_data[kPointArenaSize + 1];
2578 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2579 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2580
2581 point = written_data[kPointArenaSize + 2];
2582 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2583 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2584 }
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() [421/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2067 of file entity_unittests.cc.

2067 {
2068 Matrix matrix;
2069 LinearGradientContents contents;
2070 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2071 contents.SetGeometry(geom.get());
2072
2073 contents.SetColors({Color::CornflowerBlue()});
2074 EXPECT_TRUE(contents.IsOpaque(matrix));
2075 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2076 EXPECT_FALSE(contents.IsOpaque(matrix));
2077 contents.SetColors({Color::CornflowerBlue()});
2078 contents.SetTileMode(Entity::TileMode::kDecal);
2079 EXPECT_FALSE(contents.IsOpaque(matrix));
2080
2081 // Create stroked path that required alpha coverage.
2082 geom = Geometry::MakeStrokePath(
2083 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2084 {.width = 0.05f});
2085 contents.SetGeometry(geom.get());
2086 contents.SetColors({Color::CornflowerBlue()});
2087
2088 EXPECT_FALSE(contents.IsOpaque(matrix));
2089 }

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() [422/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1556 of file entity_unittests.cc.

1556 {
1557 auto image = CreateTextureForFixture("kalimba.jpg");
1558 ASSERT_TRUE(image);
1559
1560 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1561 auto filtered =
1562 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1563
1564 // Define the entity that will serve as the control image as a Gaussian blur
1565 // filter with no filter at all.
1566 Entity entity_left;
1567 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1568 Matrix::MakeTranslation({100, 300}) *
1569 Matrix::MakeScale(Vector2{0.5, 0.5}));
1570 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1571 Sigma{0}, Sigma{0});
1572 entity_left.SetContents(unfiltered);
1573
1574 // Define the entity that will be filtered from linear to sRGB.
1575 Entity entity_right;
1576 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1577 Matrix::MakeTranslation({500, 300}) *
1578 Matrix::MakeScale(Vector2{0.5, 0.5}));
1579 entity_right.SetContents(filtered);
1580 return entity_left.Render(context, pass) &&
1581 entity_right.Render(context, pass);
1582 };
1583
1584 ASSERT_TRUE(OpenPlaygroundHere(callback));
1585 }

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() [423/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1534 of file entity_unittests.cc.

1534 {
1535 // Set up a simple color background.
1536 auto geom = Geometry::MakeFillPath(
1537 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1538 auto fill = std::make_shared<SolidColorContents>();
1539 fill->SetGeometry(geom.get());
1540 fill->SetColor(Color::MintCream());
1541
1542 auto filter =
1543 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1544
1545 Entity e;
1546 e.SetTransform(Matrix());
1547
1548 // Confirm that the actual filter coverage matches the expected coverage.
1549 auto actual = filter->GetCoverage(e);
1550 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1551
1552 ASSERT_TRUE(actual.has_value());
1553 ASSERT_RECT_NEAR(actual.value(), expected);
1554 }

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() [424/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1129 of file entity_unittests.cc.

1129 {
1130 auto boston = CreateTextureForFixture("boston.jpg");
1131 ASSERT_TRUE(boston);
1132
1133 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1134 const char* morphology_type_names[] = {"Dilate", "Erode"};
1135 const FilterContents::MorphType morphology_types[] = {
1136 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1137 static Color input_color = Color::Black();
1138 // UI state.
1139 static int selected_morphology_type = 0;
1140 static float radius[2] = {20, 20};
1141 static Color cover_color(1, 0, 0, 0.2);
1142 static Color bounds_color(0, 1, 0, 0.1);
1143 static float offset[2] = {500, 400};
1144 static float rotation = 0;
1145 static float scale[2] = {0.65, 0.65};
1146 static float skew[2] = {0, 0};
1147 static float path_rect[4] = {0, 0,
1148 static_cast<float>(boston->GetSize().width),
1149 static_cast<float>(boston->GetSize().height)};
1150 static float effect_transform_scale = 1;
1151
1152 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1153 {
1154 ImGui::Combo("Morphology type", &selected_morphology_type,
1155 morphology_type_names,
1156 sizeof(morphology_type_names) / sizeof(char*));
1157 ImGui::SliderFloat2("Radius", radius, 0, 200);
1158 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1159 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1160 ImGui::ColorEdit4("Bounds color ",
1161 reinterpret_cast<float*>(&bounds_color));
1162 ImGui::SliderFloat2("Translation", offset, 0,
1163 pass.GetRenderTargetSize().width);
1164 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1165 ImGui::SliderFloat2("Scale", scale, 0, 3);
1166 ImGui::SliderFloat2("Skew", skew, -3, 3);
1167 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1168 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1169 3);
1170 }
1171 ImGui::End();
1172
1173 std::shared_ptr<Contents> input;
1174 Size input_size;
1175
1176 auto input_rect =
1177 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1178 auto texture = std::make_shared<TextureContents>();
1179 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1180 texture->SetDestinationRect(input_rect);
1181 texture->SetTexture(boston);
1182 texture->SetOpacity(input_color.alpha);
1183
1184 input = texture;
1185 input_size = input_rect.GetSize();
1186
1187 auto contents = FilterContents::MakeMorphology(
1188 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1189 morphology_types[selected_morphology_type]);
1190 contents->SetEffectTransform(Matrix::MakeScale(
1191 Vector2{effect_transform_scale, effect_transform_scale}));
1192
1193 auto ctm = Matrix::MakeScale(GetContentScale()) *
1194 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1195 Matrix::MakeRotationZ(Radians(rotation)) *
1196 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1197 Matrix::MakeSkew(skew[0], skew[1]) *
1198 Matrix::MakeTranslation(-Point(input_size) / 2);
1199
1200 Entity entity;
1201 entity.SetContents(contents);
1202 entity.SetTransform(ctm);
1203
1204 entity.Render(context, pass);
1205
1206 // Renders a red "cover" rectangle that shows the original position of the
1207 // unfiltered input.
1208 Entity cover_entity;
1209 std::unique_ptr<Geometry> geom =
1210 Geometry::MakeFillPath(flutter::DlPath::MakeRect(input_rect));
1211 auto cover_contents = std::make_shared<SolidColorContents>();
1212 cover_contents->SetColor(cover_color);
1213 cover_contents->SetGeometry(geom.get());
1214 cover_entity.SetContents(cover_contents);
1215 cover_entity.SetTransform(ctm);
1216 cover_entity.Render(context, pass);
1217
1218 // Renders a green bounding rect of the target filter.
1219 Entity bounds_entity;
1220 std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1221 flutter::DlPath::MakeRect(contents->GetCoverage(entity).value()));
1222 auto bounds_contents = std::make_shared<SolidColorContents>();
1223 bounds_contents->SetColor(bounds_color);
1224 bounds_contents->SetGeometry(bounds_geom.get());
1225 bounds_entity.SetContents(std::move(bounds_contents));
1226 bounds_entity.SetTransform(Matrix());
1227
1228 bounds_entity.Render(context, pass);
1229
1230 return true;
1231 };
1232 ASSERT_TRUE(OpenPlaygroundHere(callback));
1233 }

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() [425/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2150 of file entity_unittests.cc.

2150 {
2151 std::vector<Point> points = {{10, 20}, {100, 200}};
2152 PointFieldGeometry geometry(points.data(), 2, 5.0, false);
2153 ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2154 ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2155 Rect::MakeLTRB(35, 15, 135, 205));
2156 }

References impeller::PointFieldGeometry::GetCoverage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and points.

## ◆ TEST_P() [426/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2091 of file entity_unittests.cc.

2091 {
2092 Matrix matrix;
2093 RadialGradientContents contents;
2094 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2095 contents.SetGeometry(geom.get());
2096
2097 contents.SetColors({Color::CornflowerBlue()});
2098 EXPECT_TRUE(contents.IsOpaque(matrix));
2099 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2100 EXPECT_FALSE(contents.IsOpaque(matrix));
2101 contents.SetColors({Color::CornflowerBlue()});
2102 contents.SetTileMode(Entity::TileMode::kDecal);
2103 EXPECT_FALSE(contents.IsOpaque(matrix));
2104
2105 // Create stroked path that required alpha coverage.
2106 geom = Geometry::MakeStrokePath(
2107 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2108 {.width = 0.05});
2109 contents.SetGeometry(geom.get());
2110 contents.SetColors({Color::CornflowerBlue()});
2111
2112 EXPECT_FALSE(contents.IsOpaque(matrix));
2113 }

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() [427/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1392 of file entity_unittests.cc.

1392 {
1393 auto callback = [&](ContentContext& context, RenderPass& pass) {
1394 static Color color = Color::Red();
1395 static float corner_radius = 100;
1396 static float blur_radius = 100;
1397 static bool show_coverage = false;
1398 static Color coverage_color = Color::Green().WithAlpha(0.2);
1399 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1400 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1401 Color::White());
1402
1403 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1404 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1405 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1406 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1407 ImGui::Checkbox("Show coverage", &show_coverage);
1408 if (show_coverage) {
1409 ImGui::ColorEdit4("Coverage color",
1410 reinterpret_cast<Scalar*>(&coverage_color));
1411 }
1412 ImGui::End();
1413
1414 auto [top_left, bottom_right] =
1415 DrawPlaygroundLine(top_left_point, bottom_right_point);
1416 auto rect =
1417 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1418
1419 auto contents = std::make_unique<SolidRRectBlurContents>();
1420 contents->SetShape(rect, corner_radius);
1421 contents->SetColor(color);
1422 contents->SetSigma(Radius(blur_radius));
1423
1424 Entity entity;
1425 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1426 entity.SetContents(std::move(contents));
1427 entity.Render(context, pass);
1428
1429 auto coverage = entity.GetCoverage();
1430 if (show_coverage && coverage.has_value()) {
1431 auto bounds_contents = std::make_unique<SolidColorContents>();
1432 auto geom = Geometry::MakeFillPath(
1433 flutter::DlPath::MakeRect(entity.GetCoverage().value()));
1434 bounds_contents->SetGeometry(geom.get());
1435 bounds_contents->SetColor(coverage_color.Premultiply());
1436 Entity bounds_entity;
1437 bounds_entity.SetContents(std::move(bounds_contents));
1438 bounds_entity.Render(context, pass);
1439 }
1440
1441 return true;
1442 };
1443 ASSERT_TRUE(OpenPlaygroundHere(callback));
1444 }

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() [428/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1752 of file entity_unittests.cc.

1752 {
1753 auto runtime_stages =
1754 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1755 auto runtime_stage =
1756 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1757 ASSERT_TRUE(runtime_stage);
1758 ASSERT_TRUE(runtime_stage->IsDirty());
1759
1760 bool expect_dirty = true;
1761
1762 PipelineRef first_pipeline;
1763 std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1764
1765 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1766 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1767
1768 auto contents = std::make_shared<RuntimeEffectContents>();
1769 contents->SetGeometry(geom.get());
1770 contents->SetRuntimeStage(runtime_stage);
1771
1772 struct FragUniforms {
1773 Vector2 iResolution;
1774 Scalar iTime;
1775 } frag_uniforms = {
1776 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1777 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1778 };
1779 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1780 uniform_data->resize(sizeof(FragUniforms));
1781 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1782 contents->SetUniformData(uniform_data);
1783
1784 Entity entity;
1785 entity.SetContents(contents);
1786 bool result = contents->Render(context, entity, pass);
1787
1788 if (expect_dirty) {
1789 first_pipeline = pass.GetCommands().back().pipeline;
1790 } else {
1791 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1792 }
1793 expect_dirty = false;
1794 return result;
1795 };
1796
1797 // Simulate some renders and hot reloading of the shader.
1798 auto content_context = GetContentContext();
1799 {
1800 RenderTarget target =
1801 content_context->GetRenderTargetCache()->CreateOffscreen(
1802 *content_context->GetContext(), {1, 1}, 1u);
1803
1804 testing::MockRenderPass mock_pass(GetContext(), target);
1805 callback(*content_context, mock_pass);
1806 callback(*content_context, mock_pass);
1807
1808 // Dirty the runtime stage.
1809 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1810 runtime_stage =
1811 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1812
1813 ASSERT_TRUE(runtime_stage->IsDirty());
1814 expect_dirty = true;
1815
1816 callback(*content_context, mock_pass);
1817 }
1818 }
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() [429/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1867 of file entity_unittests.cc.

1867 {
1868 auto runtime_stages =
1869 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1870 auto runtime_stage =
1871 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1872 ASSERT_TRUE(runtime_stage);
1873 ASSERT_TRUE(runtime_stage->IsDirty());
1874
1875 auto contents = std::make_shared<RuntimeEffectContents>();
1876 contents->SetRuntimeStage(runtime_stage);
1877
1878 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1879 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [430/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1820 of file entity_unittests.cc.

1820 {
1821 auto runtime_stages =
1822 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1823 auto runtime_stage =
1824 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1825 ASSERT_TRUE(runtime_stage);
1826 ASSERT_TRUE(runtime_stage->IsDirty());
1827
1828 auto contents = std::make_shared<RuntimeEffectContents>();
1829 auto geom = Geometry::MakeCover();
1830 contents->SetGeometry(geom.get());
1831 contents->SetRuntimeStage(runtime_stage);
1832
1833 struct FragUniforms {
1834 Vector2 iResolution;
1835 Scalar iTime;
1836 } frag_uniforms = {
1837 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1838 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1839 };
1840 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1841 uniform_data->resize(sizeof(FragUniforms));
1842 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1843 contents->SetUniformData(uniform_data);
1844
1845 Entity entity;
1846 entity.SetContents(contents);
1847
1848 // Create a render target with a depth-stencil, similar to how EntityPass
1849 // does.
1850 RenderTarget target =
1851 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1852 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1853 "RuntimeEffect Texture");
1854 testing::MockRenderPass pass(GetContext(), target);
1855
1856 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1857 ASSERT_EQ(pass.GetCommands().size(), 1u);
1858 const auto& command = pass.GetCommands()[0];
1859 ASSERT_TRUE(command.pipeline->GetDescriptor()
1860 .GetDepthStencilAttachmentDescriptor()
1861 .has_value());
1862 ASSERT_TRUE(command.pipeline->GetDescriptor()
1863 .GetFrontStencilAttachmentDescriptor()
1864 .has_value());
1865 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [431/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1881 of file entity_unittests.cc.

1881 {
1882 if (GetBackend() != PlaygroundBackend::kVulkan) {
1883 GTEST_SKIP() << "Test only applies to Vulkan";
1884 }
1885
1886 auto runtime_stages =
1887 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1888 auto runtime_stage =
1889 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1890 ASSERT_TRUE(runtime_stage);
1891 ASSERT_TRUE(runtime_stage->IsDirty());
1892
1893 auto contents = std::make_shared<RuntimeEffectContents>();
1894 auto geom = Geometry::MakeCover();
1895 contents->SetGeometry(geom.get());
1896 contents->SetRuntimeStage(runtime_stage);
1897
1898 struct FragUniforms {
1899 Vector2 iResolution;
1900 Scalar iTime;
1901 } frag_uniforms = {
1902 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1903 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1904 };
1905 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1906 uniform_data->resize(sizeof(FragUniforms));
1907 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1908
1909 auto buffer_view = RuntimeEffectContents::EmplaceVulkanUniform(
1910 uniform_data, GetContentContext()->GetTransientsBuffer(),
1911 runtime_stage->GetUniforms()[0],
1912 GetContentContext()->GetTransientsBuffer().GetMinimumUniformAlignment());
1913
1914 // 16 bytes:
1915 // 8 bytes for iResolution
1916 // 4 bytes for iTime
1917 // 4 bytes padding
1918 EXPECT_EQ(buffer_view.GetRange().length, 16u);
1919 }

References buffer_view, impeller::RuntimeEffectContents::EmplaceVulkanUniform(), impeller::kVulkan, impeller::Geometry::MakeCover(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [432/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1235 of file entity_unittests.cc.

1235 {
1236 Entity entity;
1237 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSrcOver);
1238 entity.SetBlendMode(BlendMode::kClear);
1239 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1240 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSrcOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [433/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2496 of file entity_unittests.cc.

2496 {
2497 auto contents = SolidColorContents();
2498 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2499 auto result = contents.ApplyColorFilter([](const Color& color) {
2500 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2501 });
2502 ASSERT_TRUE(result);
2503 ASSERT_COLOR_NEAR(contents.GetColor(),
2504 Color(0.424452, 0.828743, 0.79105, 0.9375));
2505 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [434/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2026 of file entity_unittests.cc.

2026 {
2027 Matrix matrix;
2028 SolidColorContents contents;
2029 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2030 contents.SetGeometry(geom.get());
2031
2032 contents.SetColor(Color::CornflowerBlue());
2033 EXPECT_TRUE(contents.IsOpaque(matrix));
2034 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2035 EXPECT_FALSE(contents.IsOpaque(matrix));
2036
2037 // Create stroked path that required alpha coverage.
2038 geom = Geometry::MakeStrokePath(flutter::DlPath::MakeLine({0, 0}, {100, 100}),
2039 {.width = 0.05});
2040 contents.SetGeometry(geom.get());
2041 contents.SetColor(Color::CornflowerBlue());
2042
2043 EXPECT_FALSE(contents.IsOpaque(matrix));
2044 }

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() [435/545]

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() [436/545]

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() [437/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1347 of file entity_unittests.cc.

1347 {
1348 // No transform
1349 {
1350 auto fill = std::make_shared<SolidColorContents>();
1351 fill->SetColor(Color::CornflowerBlue());
1352 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1353 auto geom = Geometry::MakeFillPath(flutter::DlPath::MakeRect(expected));
1354 fill->SetGeometry(geom.get());
1355
1356 auto coverage = fill->GetCoverage({});
1357 ASSERT_TRUE(coverage.has_value());
1358 ASSERT_RECT_NEAR(coverage.value(), expected);
1359 }
1360
1361 // Entity transform
1362 {
1363 auto fill = std::make_shared<SolidColorContents>();
1364 auto geom = Geometry::MakeFillPath(
1365 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1366 fill->SetColor(Color::CornflowerBlue());
1367 fill->SetGeometry(geom.get());
1368
1369 Entity entity;
1370 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1371 entity.SetContents(std::move(fill));
1372
1373 auto coverage = entity.GetCoverage();
1374 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1375 ASSERT_TRUE(coverage.has_value());
1376 ASSERT_RECT_NEAR(coverage.value(), expected);
1377 }
1378
1379 // No coverage for fully transparent colors
1380 {
1381 auto fill = std::make_shared<SolidColorContents>();
1382 auto geom = Geometry::MakeFillPath(
1383 flutter::DlPath::MakeRect(Rect::MakeLTRB(100, 110, 200, 220)));
1384 fill->SetColor(Color::WhiteTransparent());
1385 fill->SetGeometry(geom.get());
1386
1387 auto coverage = fill->GetCoverage({});
1388 ASSERT_FALSE(coverage.has_value());
1389 }
1390 }

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() [438/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1248 of file entity_unittests.cc.

1248 {
1249 {
1250 auto geometry = Geometry::MakeStrokePath(
1251 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1252 {
1253 .width = 4.0f,
1254 .cap = Cap::kButt,
1255 .join = Join::kBevel,
1256 .miter_limit = 4.0f,
1257 });
1258
1259 Entity entity;
1260 auto contents = std::make_unique<SolidColorContents>();
1261 contents->SetGeometry(geometry.get());
1262 contents->SetColor(Color::Black());
1263 entity.SetContents(std::move(contents));
1264 auto actual = entity.GetCoverage();
1265 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1266
1267 ASSERT_TRUE(actual.has_value());
1268 ASSERT_RECT_NEAR(actual.value(), expected);
1269 }
1270
1271 // Cover the Cap::kSquare case.
1272 {
1273 auto geometry = Geometry::MakeStrokePath(
1274 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1275 {
1276 .width = 4.0,
1277 .cap = Cap::kSquare,
1278 .join = Join::kBevel,
1279 .miter_limit = 4.0,
1280 });
1281
1282 Entity entity;
1283 auto contents = std::make_unique<SolidColorContents>();
1284 contents->SetGeometry(geometry.get());
1285 contents->SetColor(Color::Black());
1286 entity.SetContents(std::move(contents));
1287 auto actual = entity.GetCoverage();
1288 auto expected =
1289 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1290
1291 ASSERT_TRUE(actual.has_value());
1292 ASSERT_RECT_NEAR(actual.value(), expected);
1293 }
1294
1295 // Cover the Join::kMiter case.
1296 {
1297 auto geometry = Geometry::MakeStrokePath(
1298 flutter::DlPath::MakeLine({0, 0}, {10, 10}), //
1299 {
1300 .width = 4.0f,
1301 .cap = Cap::kSquare,
1302 .join = Join::kMiter,
1303 .miter_limit = 2.0f,
1304 });
1305
1306 Entity entity;
1307 auto contents = std::make_unique<SolidColorContents>();
1308 contents->SetGeometry(geometry.get());
1309 contents->SetColor(Color::Black());
1310 entity.SetContents(std::move(contents));
1311 auto actual = entity.GetCoverage();
1312 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1313
1314 ASSERT_TRUE(actual.has_value());
1315 ASSERT_RECT_NEAR(actual.value(), expected);
1316 }
1317 }

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() [439/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2186 of file entity_unittests.cc.

2186 {
2187 auto content_context = GetContentContext();
2188
2189 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2190 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2191 .has_depth_stencil_attachments = false,
2192 });
2193 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2194 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2195 .has_depth_stencil_attachments = true});
2196
2197 EXPECT_NE(default_gyph, alt_gyph);
2198 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2199 alt_gyph->GetDescriptor().GetSpecializationConstants());
2200
2201 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2202 PixelFormat::kA8UNormInt;
2203
2204 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2205 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2206 expected_constants);
2207 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [440/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1609 of file entity_unittests.cc.

1609 {
1610 auto image = CreateTextureForFixture("embarcadero.jpg");
1611 ASSERT_TRUE(image);
1612
1613 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1614 auto filtered =
1615 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1616
1617 // Define the entity that will serve as the control image as a Gaussian blur
1618 // filter with no filter at all.
1619 Entity entity_left;
1620 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1621 Matrix::MakeTranslation({100, 300}) *
1622 Matrix::MakeScale(Vector2{0.5, 0.5}));
1623 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1624 Sigma{0}, Sigma{0});
1625 entity_left.SetContents(unfiltered);
1626
1627 // Define the entity that will be filtered from sRGB to linear.
1628 Entity entity_right;
1629 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1630 Matrix::MakeTranslation({500, 300}) *
1631 Matrix::MakeScale(Vector2{0.5, 0.5}));
1632 entity_right.SetContents(filtered);
1633 return entity_left.Render(context, pass) &&
1634 entity_right.Render(context, pass);
1635 };
1636
1637 ASSERT_TRUE(OpenPlaygroundHere(callback));
1638 }

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() [441/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1587 of file entity_unittests.cc.

1587 {
1588 // Set up a simple color background.
1589 auto fill = std::make_shared<SolidColorContents>();
1590 auto geom = Geometry::MakeFillPath(
1591 flutter::DlPath::MakeRect(Rect::MakeXYWH(0, 0, 300, 400)));
1592 fill->SetGeometry(geom.get());
1593 fill->SetColor(Color::DeepPink());
1594
1595 auto filter =
1596 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1597
1598 Entity e;
1599 e.SetTransform(Matrix());
1600
1601 // Confirm that the actual filter coverage matches the expected coverage.
1602 auto actual = filter->GetCoverage(e);
1603 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1604
1605 ASSERT_TRUE(actual.has_value());
1606 ASSERT_RECT_NEAR(actual.value(), expected);
1607 }

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() [442/545]

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() [443/545]

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() [444/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2115 of file entity_unittests.cc.

2115 {
2116 Matrix matrix;
2117 RadialGradientContents contents;
2118 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2119 contents.SetGeometry(geom.get());
2120
2121 contents.SetColors({Color::CornflowerBlue()});
2122 EXPECT_TRUE(contents.IsOpaque(matrix));
2123 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2124 EXPECT_FALSE(contents.IsOpaque(matrix));
2125 contents.SetColors({Color::CornflowerBlue()});
2126 contents.SetTileMode(Entity::TileMode::kDecal);
2127 EXPECT_FALSE(contents.IsOpaque(matrix));
2128
2129 // Create stroked path that required alpha coverage.
2130 geom = Geometry::MakeStrokePath(
2131 flutter::DlPathBuilder{}.MoveTo({0, 0}).LineTo({100, 100}).TakePath(),
2132 {.width = 0.05f});
2133 contents.SetGeometry(geom.get());
2134 contents.SetColors({Color::CornflowerBlue()});
2135
2136 EXPECT_FALSE(contents.IsOpaque(matrix));
2137 }

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() [445/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2178 of file entity_unittests.cc.

2178 {
2179 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f), Rational(43, 100));
2180 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f), Rational(53, 100));
2181 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f), Rational(21, 10));
2182 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f), Rational(0, 1));
2183 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f), Rational(48, 1));
2184 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [446/545]

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() [447/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2139 of file entity_unittests.cc.

2139 {
2140 Matrix matrix;
2141 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2142 TiledTextureContents contents;
2143 contents.SetTexture(bay_bridge);
2144 // This is a placeholder test. Images currently never decompress as opaque
2145 // (whether in Flutter or the playground), and so this should currently always
2146 // return false in practice.
2147 EXPECT_FALSE(contents.IsOpaque(matrix));
2148 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [448/545]

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() [449/545]

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() [450/545]

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() [451/545]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1718 of file entity_unittests.cc.

1718 {
1719 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1720 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1721 GTEST_SKIP()
1722 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1723 }
1724
1725 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1726 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1727 YUVColorSpace::kBT601LimitedRange};
1728 for (int i = 0; i < 2; i++) {
1729 auto yuv_color_space = yuv_color_space_array[i];
1730 auto textures =
1731 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1732 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1733 textures[0], textures[1], yuv_color_space);
1734 Entity filter_entity;
1735 filter_entity.SetContents(filter_contents);
1736 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1737
1738 Entity entity;
1739 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1740 contents->SetTexture(snapshot->texture);
1741 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1742 entity.SetContents(contents);
1743 entity.SetTransform(
1744 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1745 entity.Render(context, pass);
1746 }
1747 return true;
1748 };
1749 ASSERT_TRUE(OpenPlaygroundHere(callback));
1750 }
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1657
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() [452/545]

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() [453/545]

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() [454/545]

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() [455/545]

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() [456/545]

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() [457/545]

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() [458/545]

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() [459/545]

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() [460/545]

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() [461/545]

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() [462/545]

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() [463/545]

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() [464/545]

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() [465/545]

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() [466/545]

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() [467/545]

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() [468/545]

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() [469/545]

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() [470/545]

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() [471/545]

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() [472/545]

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() [473/545]

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() [474/545]

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() [475/545]

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() [476/545]

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() [477/545]

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() [478/545]

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() [479/545]

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() [480/545]

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() [481/545]

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() [482/545]

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() [483/545]

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() [484/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 1029 of file renderer_unittests.cc.

1029 {
1030 using VS = ArrayVertexShader;
1031 using FS = ArrayFragmentShader;
1032
1033 auto context = GetContext();
1034 auto pipeline_descriptor =
1035 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1036 ASSERT_TRUE(pipeline_descriptor.has_value());
1037 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1038 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1039 auto pipeline =
1040 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1041 ASSERT_TRUE(pipeline && pipeline->IsValid());
1042
1043 auto host_buffer = HostBuffer::Create(
1044 context->GetResourceAllocator(), context->GetIdleWaiter(),
1045 context->GetCapabilities()->GetMinimumUniformAlignment());
1046 SinglePassCallback callback = [&](RenderPass& pass) {
1047 auto size = pass.GetRenderTargetSize();
1048
1049 pass.SetPipeline(pipeline);
1050 pass.SetCommandLabel("Google Dots");
1051 VertexBufferBuilder<VS::PerVertexData> builder;
1052 builder.AddVertices({{Point()},
1053 {Point(0, size.height)},
1054 {Point(size.width, 0)},
1055 {Point(size.width, 0)},
1056 {Point(0, size.height)},
1057 {Point(size.width, size.height)}});
1058 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1059
1060 VS::FrameInfo frame_info;
1061 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1062 frame_info.mvp =
1063 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1064 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1065
1066 auto time = GetSecondsElapsed();
1067 auto y_pos = [&time](float x) {
1068 return 400 + 10 * std::cos(time * 5 + x / 6);
1069 };
1070
1071 FS::FragInfo fs_uniform = {
1072 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1073 Point(530, y_pos(2)), Point(580, y_pos(3))},
1074 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1075 Color::MakeRGBA8(219, 68, 55, 255),
1076 Color::MakeRGBA8(244, 180, 0, 255),
1077 Color::MakeRGBA8(15, 157, 88, 255)},
1078 };
1079 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1080
1081 pass.Draw();
1082 host_buffer->Reset();
1083 return true;
1084 };
1085 OpenPlaygroundHere(callback);
1086 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [485/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BabysFirstTriangle |
| ) |  |

Definition at line 123 of file renderer_unittests.cc.

123 {
124 auto context = GetContext();
125 ASSERT_TRUE(context);
126
127 // Declare a shorthand for the shaders we are going to use.
128 using VS = BabyVertexShader;
129 using FS = BabyFragmentShader;
130
131 // Create a pipeline descriptor that uses the shaders together and default
132 // initializes the fixed function state.
133 //
134 // If the vertex shader outputs disagree with the fragment shader inputs, this
135 // will be a compile time error.
136 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
137 ASSERT_TRUE(desc.has_value());
138
139 // Modify the descriptor for our environment. This is specific to our test.
140 desc->SetSampleCount(SampleCount::kCount4);
141 desc->SetStencilAttachmentDescriptors(std::nullopt);
142
143 // Create a pipeline from our descriptor. This is expensive to do. So just do
144 // it once.
145 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
146
147 // Create a host side buffer to build the vertex and uniform information.
148 auto host_buffer = HostBuffer::Create(
149 context->GetResourceAllocator(), context->GetIdleWaiter(),
150 context->GetCapabilities()->GetMinimumUniformAlignment());
151
152 // Specify the vertex buffer information.
153 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
154 vertex_buffer_builder.AddVertices({
155 {{-0.5, -0.5}, Color::Red(), Color::Green()},
156 {{0.0, 0.5}, Color::Green(), Color::Blue()},
157 {{0.5, -0.5}, Color::Blue(), Color::Red()},
158 });
159
160 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
161 *context->GetResourceAllocator());
162
163 SinglePassCallback callback = [&](RenderPass& pass) {
164 pass.SetPipeline(pipeline);
165 pass.SetVertexBuffer(vertex_buffer);
166
167 FS::FragInfo frag_info;
168 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
169
170 auto host_buffer = HostBuffer::Create(
171 context->GetResourceAllocator(), context->GetIdleWaiter(),
172 context->GetCapabilities()->GetMinimumUniformAlignment());
173 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
174
175 return pass.Draw().ok();
176 };
177 OpenPlaygroundHere(callback);
178 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Color::Blue(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Color::Red().

## ◆ TEST_P() [486/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BindingNullTexturesDoesNotCrash |
| ) |  |

Definition at line 1630 of file renderer_unittests.cc.

1630 {
1631 using FS = BoxFadeFragmentShader;
1632
1633 auto context = GetContext();
1634 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1635 auto command_buffer = context->CreateCommandBuffer();
1636
1637 RenderTargetAllocator allocator(context->GetResourceAllocator());
1638 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1639
1640 auto pass = command_buffer->CreateRenderPass(target);
1641 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1642 }

References impeller::RenderTargetAllocator::CreateOffscreen().

## ◆ TEST_P() [487/545]

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() [488/545]

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() [489/545]

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() [490/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 642 of file renderer_unittests.cc.

642 {
643 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
644 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
645 }
646 auto context = GetContext();
647 ASSERT_TRUE(context);
648
649 using VS = MipmapsVertexShader;
650 using FS = MipmapsFragmentShader;
651 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
652 ASSERT_TRUE(desc.has_value());
653 desc->SetSampleCount(SampleCount::kCount4);
654 desc->SetStencilAttachmentDescriptors(std::nullopt);
655 auto mipmaps_pipeline =
656 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
657 ASSERT_TRUE(mipmaps_pipeline);
658
659 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
660 auto boston = CreateTextureForFixture("boston.jpg");
661 ASSERT_TRUE(bridge && boston);
662 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
663 ASSERT_TRUE(sampler);
664
665 TextureDescriptor texture_desc;
666 texture_desc.storage_mode = StorageMode::kHostVisible;
667 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
668 texture_desc.size = bridge->GetTextureDescriptor().size;
669 texture_desc.mip_count = 1u;
670 texture_desc.usage = TextureUsage::kRenderTarget |
671 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
672 DeviceBufferDescriptor device_buffer_desc;
673 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
674 device_buffer_desc.size =
675 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
676 auto device_buffer =
677 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
678
679 // Vertex buffer.
680 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
681 vertex_builder.SetLabel("Box");
682 auto size = Point(boston->GetSize());
683 vertex_builder.AddVertices({
684 {{0, 0}, {0.0, 0.0}}, // 1
685 {{size.x, 0}, {1.0, 0.0}}, // 2
686 {{size.x, size.y}, {1.0, 1.0}}, // 3
687 {{0, 0}, {0.0, 0.0}}, // 1
688 {{size.x, size.y}, {1.0, 1.0}}, // 3
689 {{0, size.y}, {0.0, 1.0}}, // 4
690 });
691 auto vertex_buffer =
692 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
693 ASSERT_TRUE(vertex_buffer);
694
695 auto host_buffer = HostBuffer::Create(
696 context->GetResourceAllocator(), context->GetIdleWaiter(),
697 context->GetCapabilities()->GetMinimumUniformAlignment());
698 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
699 {
700 auto buffer = context->CreateCommandBuffer();
701 if (!buffer) {
702 return false;
703 }
704 buffer->SetLabel("Playground Command Buffer");
705 auto pass = buffer->CreateBlitPass();
706 if (!pass) {
707 return false;
708 }
709 pass->SetLabel("Playground Blit Pass");
710
711 // Blit `bridge` to the top left corner of the texture.
712 pass->AddCopy(bridge, device_buffer);
713 pass->EncodeCommands();
714
715 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
716 return false;
717 }
718 }
719
720 {
721 auto buffer = context->CreateCommandBuffer();
722 if (!buffer) {
723 return false;
724 }
725 buffer->SetLabel("Playground Command Buffer");
726
727 auto pass = buffer->CreateRenderPass(render_target);
728 if (!pass) {
729 return false;
730 }
731 pass->SetLabel("Playground Render Pass");
732 {
733 pass->SetCommandLabel("Image");
734 pass->SetPipeline(mipmaps_pipeline);
735 pass->SetVertexBuffer(vertex_buffer);
736
737 VS::FrameInfo frame_info;
738 EXPECT_EQ(pass->GetOrthographicTransform(),
739 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
740 frame_info.mvp = pass->GetOrthographicTransform() *
741 Matrix::MakeScale(GetContentScale());
742 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
743
744 FS::FragInfo frag_info;
745 frag_info.lod = 0;
746 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
747
748 raw_ptr<const Sampler> sampler =
749 context->GetSamplerLibrary()->GetSampler({});
750 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
751 auto texture =
752 context->GetResourceAllocator()->CreateTexture(texture_desc);
753 if (!texture->SetContents(device_buffer->OnGetContents(),
754 buffer_view.GetRange().length)) {
755 VALIDATION_LOG << "Could not upload texture to device memory";
756 return false;
757 }
758 FS::BindTex(*pass, texture, sampler);
759
760 pass->Draw().ok();
761 }
762 pass->EncodeCommands();
763 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
764 return false;
765 }
766 }
767 host_buffer->Reset();
768 return true;
769 };
770 OpenPlaygroundHere(callback);
771 }
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::DeviceBuffer::AsBufferView(), buffer_view, impeller::HostBuffer::Create(), 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() [491/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 530 of file renderer_unittests.cc.

530 {
531 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
532 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
533 }
534 auto context = GetContext();
535 ASSERT_TRUE(context);
536
537 using VS = MipmapsVertexShader;
538 using FS = MipmapsFragmentShader;
539 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
540 ASSERT_TRUE(desc.has_value());
541 desc->SetSampleCount(SampleCount::kCount4);
542 desc->SetStencilAttachmentDescriptors(std::nullopt);
543 auto mipmaps_pipeline =
544 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
545 ASSERT_TRUE(mipmaps_pipeline);
546
547 TextureDescriptor texture_desc;
548 texture_desc.storage_mode = StorageMode::kHostVisible;
549 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
550 texture_desc.size = {800, 600};
551 texture_desc.mip_count = 1u;
552 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
553 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
554 ASSERT_TRUE(texture);
555
556 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
557 auto boston = CreateTextureForFixture("boston.jpg");
558 ASSERT_TRUE(bridge && boston);
559 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
560 ASSERT_TRUE(sampler);
561
562 // Vertex buffer.
563 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
564 vertex_builder.SetLabel("Box");
565 auto size = Point(boston->GetSize());
566 vertex_builder.AddVertices({
567 {{0, 0}, {0.0, 0.0}}, // 1
568 {{size.x, 0}, {1.0, 0.0}}, // 2
569 {{size.x, size.y}, {1.0, 1.0}}, // 3
570 {{0, 0}, {0.0, 0.0}}, // 1
571 {{size.x, size.y}, {1.0, 1.0}}, // 3
572 {{0, size.y}, {0.0, 1.0}}, // 4
573 });
574 auto vertex_buffer =
575 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
576 ASSERT_TRUE(vertex_buffer);
577
578 auto host_buffer = HostBuffer::Create(
579 context->GetResourceAllocator(), context->GetIdleWaiter(),
580 context->GetCapabilities()->GetMinimumUniformAlignment());
581 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
582 auto buffer = context->CreateCommandBuffer();
583 if (!buffer) {
584 return false;
585 }
586 buffer->SetLabel("Playground Command Buffer");
587
588 {
589 auto pass = buffer->CreateBlitPass();
590 if (!pass) {
591 return false;
592 }
593 pass->SetLabel("Playground Blit Pass");
594
595 // Blit `bridge` to the top left corner of the texture.
596 pass->AddCopy(bridge, texture);
597
598 if (!pass->EncodeCommands()) {
599 return false;
600 }
601 }
602
603 {
604 auto pass = buffer->CreateRenderPass(render_target);
605 if (!pass) {
606 return false;
607 }
608 pass->SetLabel("Playground Render Pass");
609 {
610 pass->SetCommandLabel("Image");
611 pass->SetPipeline(mipmaps_pipeline);
612 pass->SetVertexBuffer(vertex_buffer);
613
614 VS::FrameInfo frame_info;
615 EXPECT_EQ(pass->GetOrthographicTransform(),
616 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
617 frame_info.mvp = pass->GetOrthographicTransform() *
618 Matrix::MakeScale(GetContentScale());
619 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
620
621 FS::FragInfo frag_info;
622 frag_info.lod = 0;
623 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
624
625 auto sampler = context->GetSamplerLibrary()->GetSampler({});
626 FS::BindTex(*pass, texture, sampler);
627
628 pass->Draw();
629 }
630 pass->EncodeCommands();
631 }
632
633 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
634 return false;
635 }
636 host_buffer->Reset();
637 return true;
638 };
639 OpenPlaygroundHere(callback);
640 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [492/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 53 of file renderer_unittests.cc.

53 {
54 using VS = BoxFadeVertexShader;
55 using FS = BoxFadeFragmentShader;
56 auto context = GetContext();
57 ASSERT_TRUE(context);
58 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
59 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
60 ASSERT_TRUE(desc.has_value());
61 desc->SetSampleCount(SampleCount::kCount4);
62 desc->SetStencilAttachmentDescriptors(std::nullopt);
63
64 // Vertex buffer.
65 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
66 vertex_builder.SetLabel("Box");
67 vertex_builder.AddVertices({
68 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
69 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
70 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
71 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
72 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
73 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
74 });
75 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
76 auto boston = CreateTextureForFixture("boston.jpg");
77 ASSERT_TRUE(bridge && boston);
78 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
79 ASSERT_TRUE(sampler);
80
81 auto host_buffer = HostBuffer::Create(
82 context->GetResourceAllocator(), context->GetIdleWaiter(),
83 context->GetCapabilities()->GetMinimumUniformAlignment());
84 SinglePassCallback callback = [&](RenderPass& pass) {
85 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
86 static bool wireframe;
87 ImGui::Checkbox("Wireframe", &wireframe);
88 ImGui::End();
89
90 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
91 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
92
93 assert(pipeline && pipeline->IsValid());
94
95 pass.SetCommandLabel("Box");
96 pass.SetPipeline(pipeline);
97 pass.SetVertexBuffer(
98 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
99
100 VS::UniformBuffer uniforms;
101 EXPECT_EQ(pass.GetOrthographicTransform(),
102 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
103 uniforms.mvp =
104 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
105 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
106
107 FS::FrameInfo frame_info;
108 frame_info.current_time = GetSecondsElapsed();
109 frame_info.cursor_position = GetCursorPosition();
110 frame_info.window_size.x = GetWindowSize().width;
111 frame_info.window_size.y = GetWindowSize().height;
112
113 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
114 FS::BindContents1(pass, boston, sampler);
115 FS::BindContents2(pass, bridge, sampler);
116
117 host_buffer->Reset();
118 return pass.Draw().ok();
119 };
120 OpenPlaygroundHere(callback);
121 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [493/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 773 of file renderer_unittests.cc.

773 {
774 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
775 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
776 }
777 auto context = GetContext();
778 ASSERT_TRUE(context);
779
780 using VS = MipmapsVertexShader;
781 using FS = MipmapsFragmentShader;
782 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
783 ASSERT_TRUE(desc.has_value());
784 desc->SetSampleCount(SampleCount::kCount4);
785 desc->SetStencilAttachmentDescriptors(std::nullopt);
786 auto mipmaps_pipeline =
787 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
788 ASSERT_TRUE(mipmaps_pipeline);
789
790 auto boston = CreateTextureForFixture("boston.jpg", true);
791 ASSERT_TRUE(boston);
792
793 // Vertex buffer.
794 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
795 vertex_builder.SetLabel("Box");
796 auto size = Point(boston->GetSize());
797 vertex_builder.AddVertices({
798 {{0, 0}, {0.0, 0.0}}, // 1
799 {{size.x, 0}, {1.0, 0.0}}, // 2
800 {{size.x, size.y}, {1.0, 1.0}}, // 3
801 {{0, 0}, {0.0, 0.0}}, // 1
802 {{size.x, size.y}, {1.0, 1.0}}, // 3
803 {{0, size.y}, {0.0, 1.0}}, // 4
804 });
805 auto vertex_buffer =
806 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
807 ASSERT_TRUE(vertex_buffer);
808
809 bool first_frame = true;
810 auto host_buffer = HostBuffer::Create(
811 context->GetResourceAllocator(), context->GetIdleWaiter(),
812 context->GetCapabilities()->GetMinimumUniformAlignment());
813 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
814 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
815 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
816 MipFilter::kLinear};
817 const char* min_filter_names[] = {"Nearest", "Linear"};
818 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
819 MinMagFilter::kLinear};
820
821 // UI state.
822 static int selected_mip_filter = 1;
823 static int selected_min_filter = 0;
824 static float lod = 4.5;
825
826 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
827 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
828 sizeof(mip_filter_names) / sizeof(char*));
829 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
830 sizeof(min_filter_names) / sizeof(char*));
831 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
832 ImGui::End();
833
834 auto buffer = context->CreateCommandBuffer();
835 if (!buffer) {
836 return false;
837 }
838 buffer->SetLabel("Playground Command Buffer");
839
840 if (first_frame) {
841 auto pass = buffer->CreateBlitPass();
842 if (!pass) {
843 return false;
844 }
845 pass->SetLabel("Playground Blit Pass");
846
847 pass->GenerateMipmap(boston, "Boston Mipmap");
848
849 pass->EncodeCommands();
850 }
851
852 first_frame = false;
853
854 {
855 auto pass = buffer->CreateRenderPass(render_target);
856 if (!pass) {
857 return false;
858 }
859 pass->SetLabel("Playground Render Pass");
860 {
861 pass->SetCommandLabel("Image LOD");
862 pass->SetPipeline(mipmaps_pipeline);
863 pass->SetVertexBuffer(vertex_buffer);
864
865 VS::FrameInfo frame_info;
866 EXPECT_EQ(pass->GetOrthographicTransform(),
867 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
868 frame_info.mvp = pass->GetOrthographicTransform() *
869 Matrix::MakeScale(GetContentScale());
870 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
871
872 FS::FragInfo frag_info;
873 frag_info.lod = lod;
874 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
875
876 SamplerDescriptor sampler_desc;
877 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
878 sampler_desc.min_filter = min_filters[selected_min_filter];
879 raw_ptr<const Sampler> sampler =
880 context->GetSamplerLibrary()->GetSampler(sampler_desc);
881 FS::BindTex(*pass, boston, sampler);
882
883 pass->Draw();
884 }
885 pass->EncodeCommands();
886 }
887
888 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
889 return false;
890 }
891 host_buffer->Reset();
892 return true;
893 };
894 OpenPlaygroundHere(callback);
895 }
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::HostBuffer::Create(), 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() [494/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1378 of file renderer_unittests.cc.

1378 {
1379 auto context = GetContext();
1380 auto cmd_buffer = context->CreateCommandBuffer();
1381 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1382 GetContext()->GetResourceAllocator());
1383
1384 auto render_target = render_target_cache->CreateOffscreen(
1385 *context, {100, 100}, /*mip_count=*/1);
1386 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1387
1388 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1389 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1390 render_target.GetRenderTargetPixelFormat());
1391 EXPECT_EQ(render_pass->HasStencilAttachment(),
1392 render_target.GetStencilAttachment().has_value());
1393 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1394 render_target.GetRenderTargetSize());
1395 render_pass->EncodeCommands();
1396 }

## ◆ TEST_P() [495/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 471 of file renderer_unittests.cc.

471 {
472 if (GetParam() == PlaygroundBackend::kOpenGLES) {
473 GTEST_SKIP() << "Instancing is not supported on OpenGL.";
474 }
475 using VS = InstancedDrawVertexShader;
476 using FS = InstancedDrawFragmentShader;
477
478 VertexBufferBuilder<VS::PerVertexData> builder;
479 builder.AddVertices({
480 VS::PerVertexData{Point{10, 10}},
481 VS::PerVertexData{Point{10, 110}},
482 VS::PerVertexData{Point{110, 10}},
483 VS::PerVertexData{Point{10, 110}},
484 VS::PerVertexData{Point{110, 10}},
485 VS::PerVertexData{Point{110, 110}},
486 });
487
488 ASSERT_NE(GetContext(), nullptr);
489 auto pipeline =
490 GetContext()
491 ->GetPipelineLibrary()
492 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
493 *GetContext())
494 ->SetSampleCount(SampleCount::kCount4)
495 .SetStencilAttachmentDescriptors(std::nullopt))
496
497 .Get();
498 ASSERT_TRUE(pipeline && pipeline->IsValid());
499
500 static constexpr size_t kInstancesCount = 5u;
501 VS::InstanceInfo<kInstancesCount> instances;
502 for (size_t i = 0; i < kInstancesCount; i++) {
503 instances.colors[i] = Color::Random();
504 }
505
506 auto host_buffer = HostBuffer::Create(
507 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
508 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
509 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
510 pass.SetPipeline(pipeline);
511 pass.SetCommandLabel("InstancedDraw");
512
513 VS::FrameInfo frame_info;
514 EXPECT_EQ(pass.GetOrthographicTransform(),
515 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
516 frame_info.mvp =
517 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
518 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
519 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
520 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
521
522 pass.SetInstanceCount(kInstancesCount);
523 pass.Draw();
524
525 host_buffer->Reset();
526 return true;
527 }));
528 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [496/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 293 of file renderer_unittests.cc.

293 {
294 using VS = BoxFadeVertexShader;
295 using FS = BoxFadeFragmentShader;
296 auto context = GetContext();
297 ASSERT_TRUE(context);
298 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
299 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
300 ASSERT_TRUE(desc.has_value());
301 desc->SetSampleCount(SampleCount::kCount4);
302 desc->SetStencilAttachmentDescriptors(std::nullopt);
303 auto box_pipeline =
304 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
305 ASSERT_TRUE(box_pipeline);
306
307 // Vertex buffer.
308 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
309 vertex_builder.SetLabel("Box");
310 vertex_builder.AddVertices({
311 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
312 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
313 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
314 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
315 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
316 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
317 });
318 auto vertex_buffer =
319 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
320 ASSERT_TRUE(vertex_buffer);
321
322 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
323 auto boston = CreateTextureForFixture("boston.jpg");
324 ASSERT_TRUE(bridge && boston);
325 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
326 ASSERT_TRUE(sampler);
327
328 auto host_buffer = HostBuffer::Create(
329 context->GetResourceAllocator(), context->GetIdleWaiter(),
330 context->GetCapabilities()->GetMinimumUniformAlignment());
331 SinglePassCallback callback = [&](RenderPass& pass) {
332 for (size_t i = 0; i < 1; i++) {
333 for (size_t j = 0; j < 1; j++) {
334 pass.SetCommandLabel("Box");
335 pass.SetPipeline(box_pipeline);
336 pass.SetVertexBuffer(vertex_buffer);
337
338 FS::FrameInfo frame_info;
339 frame_info.current_time = GetSecondsElapsed();
340 frame_info.cursor_position = GetCursorPosition();
341 frame_info.window_size.x = GetWindowSize().width;
342 frame_info.window_size.y = GetWindowSize().height;
343
344 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
345 FS::BindContents1(pass, boston, sampler);
346 FS::BindContents2(pass, bridge, sampler);
347
348 VS::UniformBuffer uniforms;
349 EXPECT_EQ(pass.GetOrthographicTransform(),
350 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
351 uniforms.mvp = pass.GetOrthographicTransform() *
352 Matrix::MakeScale(GetContentScale()) *
353 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
354 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
355 if (!pass.Draw().ok()) {
356 return false;
357 }
358 }
359 }
360
361 host_buffer->Reset();
362 return true;
363 };
364 OpenPlaygroundHere(callback);
365 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [497/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 180 of file renderer_unittests.cc.

180 {
181 using VS = ColorsVertexShader;
182 using FS = ColorsFragmentShader;
183 auto context = GetContext();
184 ASSERT_TRUE(context);
185 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
186 ASSERT_TRUE(desc.has_value());
187 desc->SetCullMode(CullMode::kBackFace);
188 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
189 desc->SetSampleCount(SampleCount::kCount4);
190 desc->ClearStencilAttachments();
191
192 // Setup the vertex layout to take two bindings. The first for positions and
193 // the second for colors.
194 auto vertex_desc = std::make_shared<VertexDescriptor>();
195 ShaderStageIOSlot position_slot = VS::kInputPosition;
196 ShaderStageIOSlot color_slot = VS::kInputColor;
197 position_slot.binding = 0;
198 position_slot.offset = 0;
199 color_slot.binding = 1;
200 color_slot.offset = 0;
201 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
202 const std::vector<ShaderStageBufferLayout> layouts = {
203 ShaderStageBufferLayout{.stride = 12u, .binding = 0},
204 ShaderStageBufferLayout{.stride = 16u, .binding = 1}};
205 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
206 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
207 vertex_desc->SetStageInputs(io_slots, layouts);
208 desc->SetVertexDescriptor(std::move(vertex_desc));
209 auto pipeline =
210 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
211 ASSERT_TRUE(pipeline);
212
213 struct Cube {
214 Vector3 positions[8] = {
215 // -Z
216 {-1, -1, -1},
217 {1, -1, -1},
218 {1, 1, -1},
219 {-1, 1, -1},
220 // +Z
221 {-1, -1, 1},
222 {1, -1, 1},
223 {1, 1, 1},
224 {-1, 1, 1},
225 };
226 Color colors[8] = {
227 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
228 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
229 };
230 uint16_t indices[36] = {
231 1, 5, 2, 2, 5, 6, // +X
232 4, 0, 7, 7, 0, 3, // -X
233 4, 5, 0, 0, 5, 1, // +Y
234 3, 2, 7, 7, 2, 6, // -Y
235 5, 4, 6, 6, 4, 7, // +Z
236 0, 1, 3, 3, 1, 2, // -Z
237 };
238 } cube;
239
240 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
241 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
242
243 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
244 ASSERT_TRUE(sampler);
245
246 Vector3 euler_angles;
247 auto host_buffer = HostBuffer::Create(
248 context->GetResourceAllocator(), context->GetIdleWaiter(),
249 context->GetCapabilities()->GetMinimumUniformAlignment());
250 SinglePassCallback callback = [&](RenderPass& pass) {
251 static Degrees fov_y(60);
252 static Scalar distance = 10;
253
254 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
255 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
256 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
257 ImGui::End();
258
259 pass.SetCommandLabel("Perspective Cube");
260 pass.SetPipeline(pipeline);
261
262 std::array<BufferView, 2> vertex_buffers = {
263 BufferView(device_buffer,
264 Range(offsetof(Cube, positions), sizeof(Cube::positions))),
265 BufferView(device_buffer,
266 Range(offsetof(Cube, colors), sizeof(Cube::colors))),
267 };
268
269 BufferView index_buffer(
270 device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
271 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
272 pass.SetElementCount(36);
273 pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
274
275 VS::UniformBuffer uniforms;
276 Scalar time = GetSecondsElapsed();
277 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
278
279 uniforms.mvp =
280 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
281 Matrix::MakeTranslation({0, 0, distance}) *
282 Matrix::MakeRotationX(Radians(euler_angles.x)) *
283 Matrix::MakeRotationY(Radians(euler_angles.y)) *
284 Matrix::MakeRotationZ(Radians(euler_angles.z));
285 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
286
287 host_buffer->Reset();
288 return pass.Draw().ok();
289 };
290 OpenPlaygroundHere(callback);
291 }

References impeller::ShaderStageIOSlot::binding, impeller::Color::Blue(), impeller::HostBuffer::Create(), 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() [498/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 367 of file renderer_unittests.cc.

367 {
368 using VS = BoxFadeVertexShader;
369 using FS = BoxFadeFragmentShader;
370 auto context = GetContext();
371 ASSERT_TRUE(context);
372 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
373 auto pipeline_desc =
374 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
375 pipeline_desc->SetSampleCount(SampleCount::kCount1);
376 pipeline_desc->ClearDepthAttachment();
377 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
378
379 ASSERT_TRUE(pipeline_desc.has_value());
380 auto box_pipeline =
381 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
382 ASSERT_TRUE(box_pipeline);
383 auto host_buffer = HostBuffer::Create(
384 context->GetResourceAllocator(), context->GetIdleWaiter(),
385 context->GetCapabilities()->GetMinimumUniformAlignment());
386
387 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
388 vertex_builder.SetLabel("Box");
389 vertex_builder.AddVertices({
390 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
391 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
392 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
393 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
394 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
395 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
396 });
397 auto vertex_buffer =
398 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
399 ASSERT_TRUE(vertex_buffer);
400
401 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
402 auto boston = CreateTextureForFixture("boston.jpg");
403 ASSERT_TRUE(bridge && boston);
404 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
405 ASSERT_TRUE(sampler);
406
407 std::shared_ptr<RenderPass> r2t_pass;
408 auto cmd_buffer = context->CreateCommandBuffer();
409 ASSERT_TRUE(cmd_buffer);
410 {
411 ColorAttachment color0;
412 color0.load_action = LoadAction::kClear;
413 color0.store_action = StoreAction::kStore;
414
415 TextureDescriptor texture_descriptor;
416 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
417 texture_descriptor.format =
418 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
419 texture_descriptor.storage_mode = StorageMode::kHostVisible;
420 texture_descriptor.size = {400, 400};
421 texture_descriptor.mip_count = 1u;
422 texture_descriptor.usage = TextureUsage::kRenderTarget;
423
424 color0.texture =
425 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
426
427 ASSERT_TRUE(color0.IsValid());
428
429 color0.texture->SetLabel("r2t_target");
430
431 StencilAttachment stencil0;
432 stencil0.load_action = LoadAction::kClear;
433 stencil0.store_action = StoreAction::kDontCare;
434 TextureDescriptor stencil_texture_desc;
435 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
436 stencil_texture_desc.size = texture_descriptor.size;
437 stencil_texture_desc.format = PixelFormat::kS8UInt;
438 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
439 stencil0.texture =
440 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
441
442 RenderTarget r2t_desc;
443 r2t_desc.SetColorAttachment(color0, 0u);
444 r2t_desc.SetStencilAttachment(stencil0);
445 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
446 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
447 }
448
449 r2t_pass->SetCommandLabel("Box");
450 r2t_pass->SetPipeline(box_pipeline);
451 r2t_pass->SetVertexBuffer(vertex_buffer);
452
453 FS::FrameInfo frame_info;
454 frame_info.current_time = GetSecondsElapsed();
455 frame_info.cursor_position = GetCursorPosition();
456 frame_info.window_size.x = GetWindowSize().width;
457 frame_info.window_size.y = GetWindowSize().height;
458
459 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
460 FS::BindContents1(*r2t_pass, boston, sampler);
461 FS::BindContents2(*r2t_pass, bridge, sampler);
462
463 VS::UniformBuffer uniforms;
464 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
465 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
466 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
467 ASSERT_TRUE(r2t_pass->Draw().ok());
468 ASSERT_TRUE(r2t_pass->EncodeCommands());
469 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [499/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1521 of file renderer_unittests.cc.

1521 {
1522 // Define shader types
1523 using TextureVS = TextureVertexShader;
1524 using TextureFS = TextureFragmentShader;
1525
1526 using SwizzleVS = SepiaVertexShader;
1527 using SwizzleFS = SwizzleFragmentShader;
1528
1529 using SepiaVS = SepiaVertexShader;
1530 using SepiaFS = SepiaFragmentShader;
1531
1532 auto context = GetContext();
1533 ASSERT_TRUE(context);
1534
1535 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1536 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1537 "support it.";
1538 return;
1539 }
1540
1541 // Create pipelines.
1542 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1543 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1544 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1545
1546 ASSERT_TRUE(texture_pipeline);
1547 ASSERT_TRUE(swizzle_pipeline);
1548 ASSERT_TRUE(sepia_pipeline);
1549
1550 // Vertex buffer builders.
1551 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1552 texture_vtx_builder.AddVertices({
1553 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1554 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1555 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1556 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1557 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1558 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1559 });
1560
1561 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1562 sepia_vtx_builder.AddVertices({
1563 {{100, 100, 0.0}}, // 1
1564 {{800, 100, 0.0}}, // 2
1565 {{800, 800, 0.0}}, // 3
1566 {{100, 100, 0.0}}, // 1
1567 {{800, 800, 0.0}}, // 3
1568 {{100, 800, 0.0}}, // 4
1569 });
1570
1571 auto boston = CreateTextureForFixture("boston.jpg");
1572 ASSERT_TRUE(boston);
1573
1574 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1575 ASSERT_TRUE(sampler);
1576
1577 SinglePassCallback callback = [&](RenderPass& pass) {
1578 auto buffer = HostBuffer::Create(
1579 context->GetResourceAllocator(), context->GetIdleWaiter(),
1580 context->GetCapabilities()->GetMinimumUniformAlignment());
1581
1582 // Draw the texture.
1583 {
1584 pass.SetPipeline(texture_pipeline);
1585 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1586 *context->GetResourceAllocator()));
1587 TextureVS::UniformBuffer uniforms;
1588 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1589 Matrix::MakeScale(GetContentScale());
1590 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1591 TextureFS::BindTextureContents(pass, boston, sampler);
1592 if (!pass.Draw().ok()) {
1593 return false;
1594 }
1595 }
1596
1597 // Draw the sepia toner.
1598 {
1599 pass.SetPipeline(sepia_pipeline);
1600 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1601 *context->GetResourceAllocator()));
1602 SepiaVS::UniformBuffer uniforms;
1603 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1604 Matrix::MakeScale(GetContentScale());
1605 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1606 if (!pass.Draw().ok()) {
1607 return false;
1608 }
1609 }
1610
1611 // Draw the swizzle.
1612 {
1613 pass.SetPipeline(swizzle_pipeline);
1614 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1615 *context->GetResourceAllocator()));
1616 SwizzleVS::UniformBuffer uniforms;
1617 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1618 Matrix::MakeScale(GetContentScale());
1619 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1620 if (!pass.Draw().ok()) {
1621 return false;
1622 }
1623 }
1624
1625 return true;
1626 };
1627 OpenPlaygroundHere(callback);
1628 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [500/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1431 of file renderer_unittests.cc.

1431 {
1432 // Define shader types
1433 using TextureVS = TextureVertexShader;
1434 using TextureFS = TextureFragmentShader;
1435
1436 using SepiaVS = SepiaVertexShader;
1437 using SepiaFS = SepiaFragmentShader;
1438
1439 auto context = GetContext();
1440 ASSERT_TRUE(context);
1441
1442 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1443 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1444 "support it.";
1445 return;
1446 }
1447
1448 // Create pipelines.
1449 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1450 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1451
1452 ASSERT_TRUE(texture_pipeline);
1453 ASSERT_TRUE(sepia_pipeline);
1454
1455 // Vertex buffer builders.
1456 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1457 texture_vtx_builder.AddVertices({
1458 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1459 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1460 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1461 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1462 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1463 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1464 });
1465
1466 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1467 sepia_vtx_builder.AddVertices({
1468 {{100, 100, 0.0}}, // 1
1469 {{800, 100, 0.0}}, // 2
1470 {{800, 800, 0.0}}, // 3
1471 {{100, 100, 0.0}}, // 1
1472 {{800, 800, 0.0}}, // 3
1473 {{100, 800, 0.0}}, // 4
1474 });
1475
1476 auto boston = CreateTextureForFixture("boston.jpg");
1477 ASSERT_TRUE(boston);
1478
1479 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1480 ASSERT_TRUE(sampler);
1481
1482 SinglePassCallback callback = [&](RenderPass& pass) {
1483 auto buffer = HostBuffer::Create(
1484 context->GetResourceAllocator(), context->GetIdleWaiter(),
1485 context->GetCapabilities()->GetMinimumUniformAlignment());
1486
1487 // Draw the texture.
1488 {
1489 pass.SetPipeline(texture_pipeline);
1490 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1491 *context->GetResourceAllocator()));
1492 TextureVS::UniformBuffer uniforms;
1493 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1494 Matrix::MakeScale(GetContentScale());
1495 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1496 TextureFS::BindTextureContents(pass, boston, sampler);
1497 if (!pass.Draw().ok()) {
1498 return false;
1499 }
1500 }
1501
1502 // Draw the sepia toner.
1503 {
1504 pass.SetPipeline(sepia_pipeline);
1505 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1506 *context->GetResourceAllocator()));
1507 SepiaVS::UniformBuffer uniforms;
1508 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1509 Matrix::MakeScale(GetContentScale());
1510 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1511 if (!pass.Draw().ok()) {
1512 return false;
1513 }
1514 }
1515
1516 return true;
1517 };
1518 OpenPlaygroundHere(callback);
1519 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [501/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1147 of file renderer_unittests.cc.

1147 {
1148 using VS = BoxFadeVertexShader;
1149
1150 // Do not create any index buffer if no indices were provided.
1151 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1152 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1153 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [502/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1137 of file renderer_unittests.cc.

1137 {
1138 using VS = BoxFadeVertexShader;
1139
1140 // Default to 16bit index buffer size, as this is a reasonable default and
1141 // supported on all backends without extensions.
1142 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1143 vertex_builder.AppendIndex(0u);
1144 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1145 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [503/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 1088 of file renderer_unittests.cc.

1088 {
1089 using VS = InactiveUniformsVertexShader;
1090 using FS = InactiveUniformsFragmentShader;
1091
1092 auto context = GetContext();
1093 auto pipeline_descriptor =
1094 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1095 ASSERT_TRUE(pipeline_descriptor.has_value());
1096 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1097 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1098 auto pipeline =
1099 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1100 ASSERT_TRUE(pipeline && pipeline->IsValid());
1101
1102 auto host_buffer = HostBuffer::Create(
1103 context->GetResourceAllocator(), context->GetIdleWaiter(),
1104 context->GetCapabilities()->GetMinimumUniformAlignment());
1105 SinglePassCallback callback = [&](RenderPass& pass) {
1106 auto size = pass.GetRenderTargetSize();
1107
1108 pass.SetPipeline(pipeline);
1109 pass.SetCommandLabel("Inactive Uniform");
1110
1111 VertexBufferBuilder<VS::PerVertexData> builder;
1112 builder.AddVertices({{Point()},
1113 {Point(0, size.height)},
1114 {Point(size.width, 0)},
1115 {Point(size.width, 0)},
1116 {Point(0, size.height)},
1117 {Point(size.width, size.height)}});
1118 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1119
1120 VS::FrameInfo frame_info;
1121 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1122 frame_info.mvp =
1123 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1124 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1125
1126 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1127 .color = Color::Green()};
1128 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1129
1130 pass.Draw().ok();
1131 host_buffer->Reset();
1132 return true;
1133 };
1134 OpenPlaygroundHere(callback);
1135 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [504/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | Planet |
| ) |  |

Definition at line 961 of file renderer_unittests.cc.

961 {
962 using VS = PlanetVertexShader;
963 using FS = PlanetFragmentShader;
964
965 auto context = GetContext();
966 auto pipeline_descriptor =
967 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
968 ASSERT_TRUE(pipeline_descriptor.has_value());
969 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
970 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
971 auto pipeline =
972 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
973 ASSERT_TRUE(pipeline && pipeline->IsValid());
974
975 auto host_buffer = HostBuffer::Create(
976 context->GetResourceAllocator(), context->GetIdleWaiter(),
977 context->GetCapabilities()->GetMinimumUniformAlignment());
978
979 SinglePassCallback callback = [&](RenderPass& pass) {
980 static Scalar speed = 0.1;
981 static Scalar planet_size = 550.0;
982 static bool show_normals = false;
983 static bool show_noise = false;
984 static Scalar seed_value = 42.0;
985
986 auto size = pass.GetRenderTargetSize();
987
988 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
989 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
990 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
991 ImGui::Checkbox("Show Normals", &show_normals);
992 ImGui::Checkbox("Show Noise", &show_noise);
993 ImGui::InputFloat("Seed Value", &seed_value);
994 ImGui::End();
995
996 pass.SetPipeline(pipeline);
997 pass.SetCommandLabel("Planet scene");
998 VertexBufferBuilder<VS::PerVertexData> builder;
999 builder.AddVertices({{Point()},
1000 {Point(0, size.height)},
1001 {Point(size.width, 0)},
1002 {Point(size.width, 0)},
1003 {Point(0, size.height)},
1004 {Point(size.width, size.height)}});
1005 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1006
1007 VS::FrameInfo frame_info;
1008 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1009 frame_info.mvp = pass.GetOrthographicTransform();
1010 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1011
1012 FS::FragInfo fs_uniform;
1013 fs_uniform.resolution = Point(size);
1014 fs_uniform.time = GetSecondsElapsed();
1015 fs_uniform.speed = speed;
1016 fs_uniform.planet_size = planet_size;
1017 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1018 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1019 fs_uniform.seed_value = seed_value;
1020 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1021
1022 pass.Draw().ok();
1023 host_buffer->Reset();
1024 return true;
1025 };
1026 OpenPlaygroundHere(callback);
1027 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Matrix::MakeOrthographic().

## ◆ TEST_P() [505/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1398 of file renderer_unittests.cc.

1399 {
1400 auto context = GetContext();
1401 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1402 GetContext()->GetResourceAllocator());
1403
1404 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1405 *context, {100, 100}, /*mip_count=*/1);
1406 EXPECT_EQ(render_target.GetDepthAttachment()
1407 ->texture->GetTextureDescriptor()
1408 .format,
1409 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1410 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [506/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1225 of file renderer_unittests.cc.

1225 {
1226 using VS = BoxFadeVertexShader;
1227 using FS = BoxFadeFragmentShader;
1228 auto context = GetContext();
1229 ASSERT_TRUE(context);
1230 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1231 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1232 ASSERT_TRUE(desc.has_value());
1233
1234 // Vertex buffer.
1235 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1236 vertex_builder.SetLabel("Box");
1237 vertex_builder.AddVertices({
1238 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1239 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1240 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1241 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1242 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1243 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1244 });
1245 auto vertex_buffer =
1246 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1247 ASSERT_TRUE(vertex_buffer);
1248
1249 desc->SetSampleCount(SampleCount::kCount4);
1250 desc->SetStencilAttachmentDescriptors(std::nullopt);
1251
1252 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1253 auto boston = CreateTextureForFixture("boston.jpg");
1254 ASSERT_TRUE(bridge && boston);
1255 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1256 ASSERT_TRUE(sampler);
1257
1258 static bool mirror = false;
1259 static int stencil_reference_write = 0xFF;
1260 static int stencil_reference_read = 0x1;
1261 std::vector<uint8_t> stencil_contents;
1262 static int last_stencil_contents_reference_value = 0;
1263 static int current_front_compare =
1264 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1265 static int current_back_compare =
1266 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1267
1268 auto host_buffer = HostBuffer::Create(
1269 context->GetResourceAllocator(), context->GetIdleWaiter(),
1270 context->GetCapabilities()->GetMinimumUniformAlignment());
1271 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1272 auto buffer = context->CreateCommandBuffer();
1273 if (!buffer) {
1274 return false;
1275 }
1276 buffer->SetLabel("Playground Command Buffer");
1277
1278 {
1279 // Configure the stencil attachment for the test.
1280 RenderTarget::AttachmentConfig stencil_config;
1281 stencil_config.load_action = LoadAction::kLoad;
1282 stencil_config.store_action = StoreAction::kDontCare;
1283 stencil_config.storage_mode = StorageMode::kHostVisible;
1284 render_target.SetupDepthStencilAttachments(
1285 *context, *context->GetResourceAllocator(),
1286 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1287 // Fill the stencil buffer with an checkerboard pattern.
1288 const auto target_width = render_target.GetRenderTargetSize().width;
1289 const auto target_height = render_target.GetRenderTargetSize().height;
1290 const size_t target_size = target_width * target_height;
1291 if (stencil_contents.size() != target_size ||
1292 last_stencil_contents_reference_value != stencil_reference_write) {
1293 stencil_contents.resize(target_size);
1294 last_stencil_contents_reference_value = stencil_reference_write;
1295 for (int y = 0; y < target_height; y++) {
1296 for (int x = 0; x < target_width; x++) {
1297 const auto index = y * target_width + x;
1298 const auto kCheckSize = 64;
1299 const auto value =
1300 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1301 stencil_reference_write;
1302 stencil_contents[index] = value;
1303 }
1304 }
1305 }
1306 if (!render_target.GetStencilAttachment()->texture->SetContents(
1307 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1308 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1309 return false;
1310 }
1311 auto pass = buffer->CreateRenderPass(render_target);
1312 if (!pass) {
1313 return false;
1314 }
1315 pass->SetLabel("Stencil Buffer");
1316 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1317 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1318 0xFF);
1319 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1320 0xFF);
1321 ImGui::Checkbox("Back face mode", &mirror);
1322 ImGui::ListBox("Front face compare function", &current_front_compare,
1323 CompareFunctionUI().labels(), CompareFunctionUI().size());
1324 ImGui::ListBox("Back face compare function", &current_back_compare,
1325 CompareFunctionUI().labels(), CompareFunctionUI().size());
1326 ImGui::End();
1327
1328 StencilAttachmentDescriptor front;
1329 front.stencil_compare =
1330 CompareFunctionUI().FunctionOf(current_front_compare);
1331 StencilAttachmentDescriptor back;
1332 back.stencil_compare =
1333 CompareFunctionUI().FunctionOf(current_back_compare);
1334 desc->SetStencilAttachmentDescriptors(front, back);
1335 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1336
1337 assert(pipeline && pipeline->IsValid());
1338
1339 pass->SetCommandLabel("Box");
1340 pass->SetPipeline(pipeline);
1341 pass->SetStencilReference(stencil_reference_read);
1342 pass->SetVertexBuffer(vertex_buffer);
1343
1344 VS::UniformBuffer uniforms;
1345 EXPECT_EQ(pass->GetOrthographicTransform(),
1346 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1347 uniforms.mvp = pass->GetOrthographicTransform() *
1348 Matrix::MakeScale(GetContentScale());
1349 if (mirror) {
1350 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1351 }
1352 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1353
1354 FS::FrameInfo frame_info;
1355 frame_info.current_time = GetSecondsElapsed();
1356 frame_info.cursor_position = GetCursorPosition();
1357 frame_info.window_size.x = GetWindowSize().width;
1358 frame_info.window_size.y = GetWindowSize().height;
1359
1360 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1361 FS::BindContents1(*pass, boston, sampler);
1362 FS::BindContents2(*pass, bridge, sampler);
1363 if (!pass->Draw().ok()) {
1364 return false;
1365 }
1366 pass->EncodeCommands();
1367 }
1368
1369 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1370 return false;
1371 }
1372 host_buffer->Reset();
1373 return true;
1374 };
1375 OpenPlaygroundHere(callback);
1376 }
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1213
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1203
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1220

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), CompareFunctionUI(), impeller::HostBuffer::Create(), 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() [507/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 897 of file renderer_unittests.cc.

897 {
898 using VS = ImpellerVertexShader;
899 using FS = ImpellerFragmentShader;
900
901 auto context = GetContext();
902 auto pipeline_descriptor =
903 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
904 ASSERT_TRUE(pipeline_descriptor.has_value());
905 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
906 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
907 auto pipeline =
908 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
909 ASSERT_TRUE(pipeline && pipeline->IsValid());
910
911 auto blue_noise = CreateTextureForFixture("blue_noise.png");
912 SamplerDescriptor noise_sampler_desc;
913 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
914 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
915 raw_ptr<const Sampler> noise_sampler =
916 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
917
918 auto cube_map = CreateTextureCubeForFixture(
919 {"table_mountain_px.png", "table_mountain_nx.png",
920 "table_mountain_py.png", "table_mountain_ny.png",
921 "table_mountain_pz.png", "table_mountain_nz.png"});
922 raw_ptr<const Sampler> cube_map_sampler =
923 context->GetSamplerLibrary()->GetSampler({});
924 auto host_buffer = HostBuffer::Create(
925 context->GetResourceAllocator(), context->GetIdleWaiter(),
926 context->GetCapabilities()->GetMinimumUniformAlignment());
927
928 SinglePassCallback callback = [&](RenderPass& pass) {
929 auto size = pass.GetRenderTargetSize();
930
931 pass.SetPipeline(pipeline);
932 pass.SetCommandLabel("Impeller SDF scene");
933 VertexBufferBuilder<VS::PerVertexData> builder;
934 builder.AddVertices({{Point()},
935 {Point(0, size.height)},
936 {Point(size.width, 0)},
937 {Point(size.width, 0)},
938 {Point(0, size.height)},
939 {Point(size.width, size.height)}});
940 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
941
942 VS::FrameInfo frame_info;
943 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
944 frame_info.mvp = pass.GetOrthographicTransform();
945 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
946
947 FS::FragInfo fs_uniform;
948 fs_uniform.texture_size = Point(size);
949 fs_uniform.time = GetSecondsElapsed();
950 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
951 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
952 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
953
954 pass.Draw().ok();
955 host_buffer->Reset();
956 return true;
957 };
958 OpenPlaygroundHere(callback);
959 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), 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() [508/545]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1155 of file renderer_unittests.cc.

1155 {
1156 // Does not create index buffer if one is provided.
1157 using VS = BoxFadeVertexShader;
1158 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1159 vertex_builder.SetLabel("Box");
1160 vertex_builder.AddVertices({
1161 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1162 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1163 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1164 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1165 });
1166 vertex_builder.AppendIndex(0);
1167 vertex_builder.AppendIndex(1);
1168 vertex_builder.AppendIndex(2);
1169 vertex_builder.AppendIndex(1);
1170 vertex_builder.AppendIndex(2);
1171 vertex_builder.AppendIndex(3);
1172
1173 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1174 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1175 }

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() [509/545]

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() [510/545]

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() [511/545]

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() [512/545]

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() [513/545]

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() [514/545]

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() [515/545]

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() [516/545]

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() [517/545]

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() [518/545]

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() [519/545]

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() [520/545]

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() [521/545]

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() [522/545]

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() [523/545]

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> 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(), *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 &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() [524/545]

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> 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(), *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() [525/545]

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> 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(), *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() [526/545]

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> 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(), *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() [527/545]

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> 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(), *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() [528/545]

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> 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(), *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() [529/545]

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> 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(), *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() [530/545]

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() [531/545]

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 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(), *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 &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() [532/545]

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() [533/545]

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 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(), *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(), *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() [534/545]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 262 of file typographer_unittests.cc.

262 {
263 auto 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(), *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(), *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() [535/545]

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 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(), *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(), *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() [536/545]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 212 of file typographer_unittests.cc.

212 {
213 auto 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 *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() [537/545]

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 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(), *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() [538/545]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsIgnoredForNonEmojiFonts |
| ) |  |

Definition at line 337 of file typographer_unittests.cc.

337 {
338 auto 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(), *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() [539/545]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsPartOfCacheKey |
| ) |  |

Definition at line 301 of file typographer_unittests.cc.

301 {
302 auto 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(), *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() [540/545]

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 host_buffer = HostBuffer::Create(
641 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
642 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
643
644 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *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(), *host_buffer,
666 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() [541/545]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 120 of file typographer_unittests.cc.

120 {
121 auto 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(), *host_buffer, GlyphAtlas::Type::kColorBitmap);
154
155 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
156 *GetContext(), *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() [542/545]

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() [543/545]

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 host_buffer = HostBuffer::Create(
588 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
589 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
590
591 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *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(), *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(), *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() [544/545]

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 host_buffer = HostBuffer::Create(
518 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
519 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
520
521 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *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(), *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() [545/545]

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 host_buffer = HostBuffer::Create(
552 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
553 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
554
555 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *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(), *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 38 of file dl_unittests.cc.

38 {
39 return flutter::DlColor(Color::ToIColor(
40 Color(components[0], components[1], components[2], components[3])));
41 }

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
| staticconstexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 375 of file aiks_dl_text_unittests.cc.

Referenced by TEST_P().

## ◆ kMagicFailingAllocation

constexpr const size_t impeller::testing::kMagicFailingAllocation = 1024000 * 2
| staticconstexpr

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.