| 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

## Typedefs
using | AiksTest = AiksPlayground
using | DisplayListTest = DlPlayground
using | HostBufferTest = EntityPlayground
using | TextContentsTest = PlaygroundTest
using | EntityTest = EntityPlayground
using | EntityPassTargetTest = EntityPlayground
using | RenderTargetCacheTest = EntityPlayground
using | SaveLayerUtilsTest = ::testing::Test
using | AllocatorMTLTest = PlaygroundTest
using | ContextMTLTest = PlaygroundTest
using | SwapchainTransientsMTLTest = PlaygroundTest
using | DriverInfoVKTest = PlaygroundTest
using | PipelineCacheDataVKPlaygroundTest = PlaygroundTest
using | RendererTest = PlaygroundTest
using | BlitPassTest = AiksTest
using | ComputeTest = ComputePlaygroundTest
using | DeviceBufferTest = Playground
using | RuntimeStageTest = RuntimeStagePlayground
using | 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, 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, FilledCirclesRenderCorrectly)
| TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
| TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
| 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, 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, 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, DisplayListToTextureWithMipGenerationOnGLES)
| 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)
| 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)
flutter::DlColor | toColor (const float *components)
| INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
| TEST_P (DisplayListTest, CanDrawRect)
| TEST_P (DisplayListTest, CanDrawTextBlob)
| TEST_P (DisplayListTest, CanDrawTextBlobWithGradient)
| TEST_P (DisplayListTest, CanDrawTextWithSaveLayer)
| TEST_P (DisplayListTest, CanDrawImage)
| TEST_P (DisplayListTest, CanDrawCapsAndJoins)
| TEST_P (DisplayListTest, CanDrawArc)
| TEST_P (DisplayListTest, StrokedPathsDrawCorrectly)
| TEST_P (DisplayListTest, CanDrawWithOddPathWinding)
| TEST_P (DisplayListTest, CanDrawAnOpenPath)
| TEST_P (DisplayListTest, CanDrawWithMaskBlur)
| TEST_P (DisplayListTest, CanDrawStrokedText)
| TEST_P (DisplayListTest, StrokedTextNotOffsetFromNormalText)
| TEST_P (DisplayListTest, IgnoreMaskFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawWithBlendColorFilter)
| TEST_P (DisplayListTest, CanDrawWithColorFilterImageFilter)
| TEST_P (DisplayListTest, CanDrawWithImageBlurFilter)
| TEST_P (DisplayListTest, CanDrawWithComposeImageFilter)
| TEST_P (DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter)
| TEST_P (DisplayListTest, CanDrawBackdropFilter)
| TEST_P (DisplayListTest, CanDrawNinePatchImage)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCornersScaledDown)
| TEST_P (DisplayListTest, NinePatchImagePrecision)
| TEST_P (DisplayListTest, CanDrawPoints)
| TEST_P (DisplayListTest, CanDrawZeroLengthLine)
| TEST_P (DisplayListTest, CanDrawShadow)
| TEST_P (DisplayListTest, CanDrawZeroWidthLine)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilter)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawRectWithLinearToSrgbColorFilter)
| TEST_P (DisplayListTest, CanDrawPaintWithColorSource)
| TEST_P (DisplayListTest, CanBlendDstOverAndDstCorrectly)
| TEST_P (DisplayListTest, CanDrawCorrectlyWithColorFilterAndImageFilter)
| TEST_P (DisplayListTest, MaskBlursApplyCorrectlyToColorSources)
| TEST_P (DisplayListTest, DrawShapes)
| TEST_P (DisplayListTest, ClipDrawRRectWithNonCircularRadii)
| TEST_P (DisplayListTest, DrawVerticesBlendModes)
| TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
| TEST_P (DisplayListTest, DrawMaskBlursThatMightUseSaveLayers)
| TEST (PaintTest, GradientStopConversion)
| TEST (PaintTest, GradientMissing0)
| TEST (PaintTest, GradientMissingLastValue)
| TEST (PaintTest, GradientStopGreaterThan1)
| TEST (PaintTest, GradientConversionNonMonotonic)
| TEST (SkiaConversionTest, ToSamplerDescriptor)
| TEST (SkiaConversionsTest, ToColor)
| TEST (EntityPassClipStackTest, CanPushAndPopEntities)
| TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverageNonAA)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverage)
| TEST (EntityPassClipStackTest, AppendLargerClipCoverageWithDifferenceOrNonSquare)
| TEST (EntityPassClipStackTest, AppendDecreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, AppendIncreasingSizeClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpassesNonAA)
| INSTANTIATE_PLAYGROUND_SUITE (BlendFilterContentsTest)
| TEST_P (BlendFilterContentsTest, AdvancedBlendColorAlignsColorTo4)
| INSTANTIATE_PLAYGROUND_SUITE (GaussianBlurFilterContentsTest)
| TEST (GaussianBlurFilterContentsTest, Create)
| TEST (GaussianBlurFilterContentsTest, CoverageEmpty)
| TEST (GaussianBlurFilterContentsTest, CoverageSimple)
| TEST (GaussianBlurFilterContentsTest, CoverageWithSigma)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithTexture)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, FilterSourceCoverage)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaValues)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageRotated)
| TEST_P (GaussianBlurFilterContentsTest, CalculateUVsSimple)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRect)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRectScaled)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaForBlurRadius)
| TEST (GaussianBlurFilterContentsTest, Coefficients)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesSimple)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesComplex)
| TEST (GaussianBlurFilterContentsTest, ChopHugeBlurs)
| TEST (FilterInputTest, CanSetLocalTransformForTexture)
| INSTANTIATE_PLAYGROUND_SUITE (MatrixFilterContentsTest)
| TEST (MatrixFilterContentsTest, CoverageEmpty)
| TEST (MatrixFilterContentsTest, CoverageSimple)
| TEST (MatrixFilterContentsTest, Coverage2x)
| TEST (MatrixFilterContentsTest, Coverage2xEffect)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageIdentity)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageSubpassScale)
| INSTANTIATE_PLAYGROUND_SUITE (HostBufferTest)
| TEST_P (HostBufferTest, IdleWaiter)
| TEST_P (HostBufferTest, CanEmplace)
| TEST_P (HostBufferTest, CanEmplaceWithAlignment)
| TEST_P (HostBufferTest, HostBufferInitialState)
| TEST_P (HostBufferTest, ResetIncrementsFrameCounter)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer)
| TEST_P (HostBufferTest, UnusedBuffersAreDiscardedWhenResetting)
| TEST_P (HostBufferTest, EmplaceWithProcIsAligned)
| TEST_P (HostBufferTest, EmplaceWithFailingAllocationDoesntCrash)
| TEST (LineContents, Create)
| TEST (LineContents, CalculatePerVertex)
| TEST (LineContents, CreateCurveData)
| TEST (LineContents, CreateCurveDataScaled)
| TEST (LineContents, CalculatePerVertexLimit)
| INSTANTIATE_PLAYGROUND_SUITE (TextContentsTest)
| TEST_P (TextContentsTest, SimpleComputeVertexData)
| TEST_P (TextContentsTest, SimpleComputeVertexData2x)
| TEST_P (TextContentsTest, MaintainsShape)
| TEST_P (TextContentsTest, SimpleSubpixel)
| TEST_P (TextContentsTest, SimpleSubpixel3x)
| TEST_P (TextContentsTest, SimpleSubpixel26)
| TEST_P (TextContentsTest, SimpleSubpixel80)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithNoClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithClips)
| TEST (DrawOrderResolverTest, GetSortedDrawsRespectsSkipCounts)
| TEST (DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithFlush)
| TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
| TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
Rect | RectMakeCenterSize (Point center, Size size)
| TEST_P (EntityTest, CanCreateEntity)
| TEST_P (EntityTest, FilterCoverageRespectsCropRect)
| TEST_P (EntityTest, GeometryBoundsAreTransformed)
| TEST_P (EntityTest, ThreeStrokesInOnePath)
| TEST_P (EntityTest, StrokeWithTextureContents)
| TEST_P (EntityTest, TriangleInsideASquare)
| TEST_P (EntityTest, StrokeCapAndJoinTest)
| TEST_P (EntityTest, CubicCurveTest)
| TEST_P (EntityTest, CanDrawCorrectlyWithRotatedTransform)
| TEST_P (EntityTest, CubicCurveAndOverlapTest)
| TEST_P (EntityTest, SolidColorContentsStrokeSetStrokeCapsAndJoins)
| TEST_P (EntityTest, SolidColorContentsStrokeSetMiterLimit)
| TEST_P (EntityTest, BlendingModeOptions)
| TEST_P (EntityTest, BezierCircleScaled)
| TEST_P (EntityTest, Filters)
| TEST_P (EntityTest, GaussianBlurFilter)
| TEST_P (EntityTest, MorphologyFilter)
| TEST_P (EntityTest, SetBlendMode)
| TEST_P (EntityTest, ContentsGetBoundsForEmptyPathReturnsNullopt)
| TEST_P (EntityTest, SolidStrokeCoverageIsCorrect)
| TEST_P (EntityTest, BorderMaskBlurCoverageIsCorrect)
| TEST_P (EntityTest, SolidFillCoverageIsCorrect)
| TEST_P (EntityTest, RRectShadowTest)
| TEST_P (EntityTest, ColorMatrixFilterCoverageIsCorrect)
| TEST_P (EntityTest, ColorMatrixFilterEditable)
| TEST_P (EntityTest, LinearToSrgbFilterCoverageIsCorrect)
| TEST_P (EntityTest, LinearToSrgbFilter)
| TEST_P (EntityTest, SrgbToLinearFilterCoverageIsCorrect)
| TEST_P (EntityTest, SrgbToLinearFilter)
static Vector3 | RGBToYUV (Vector3 rgb, YUVColorSpace yuv_color_space)
static std::vector< std::shared_ptr< Texture > > | CreateTestYUVTextures (Context *context, YUVColorSpace yuv_color_space)
| TEST_P (EntityTest, YUVToRGBFilter)
| TEST_P (EntityTest, RuntimeEffect)
| TEST_P (EntityTest, RuntimeEffectCanSuccessfullyRender)
| TEST_P (EntityTest, RuntimeEffectCanPrecache)
| TEST_P (EntityTest, RuntimeEffectSetsRightSizeWhenUniformIsStruct)
| TEST_P (EntityTest, ColorFilterWithForegroundColorAdvancedBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorClearBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorDstBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcInBlend)
| TEST_P (EntityTest, CoverageForStrokePathWithNegativeValuesInTransform)
| TEST_P (EntityTest, SolidColorContentsIsOpaque)
| TEST_P (EntityTest, ConicalGradientContentsIsOpaque)
| TEST_P (EntityTest, LinearGradientContentsIsOpaque)
| TEST_P (EntityTest, RadialGradientContentsIsOpaque)
| TEST_P (EntityTest, SweepGradientContentsIsOpaque)
| TEST_P (EntityTest, TiledTextureContentsIsOpaque)
| TEST_P (EntityTest, PointFieldGeometryCoverage)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, SpecializationConstantsAreAppliedToVariants)
| TEST_P (EntityTest, DecalSpecializationAppliedToMorphologyFilter)
| TEST_P (EntityTest, ContentContextOptionsHasReasonableHashFunctions)
| TEST_P (EntityTest, FillPathGeometryGetPositionBufferReturnsExpectedMode)
| TEST_P (EntityTest, FailOnValidationError)
| TEST_P (EntityTest, CanComputeGeometryForEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, CanRenderEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, DrawSuperEllipse)
| TEST_P (EntityTest, DrawRoundSuperEllipse)
| TEST_P (EntityTest, SolidColorApplyColorFilter)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Linear)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Radial)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Conical)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Sweep)
| TEST_P (EntityTest, GiantStrokePathAllocation)
| TEST_P (EntityTest, GiantLineStripPathAllocation)
| TEST (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (EntityGeometryTest, LineGeometryCoverage)
| TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
| TEST (EntityGeometryTest, GeometryResultHasReasonableDefaults)
| TEST (EntityGeometryTest, AlphaCoverageStrokePaths)
| 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 (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 (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (PathTest, EmptyPathWithContour)
| TEST (PathTest, PathCreatePolyLineDoesNotDuplicatePoints)
| TEST (PathTest, PathSingleContour)
| TEST (PathTest, PathSingleContourDoubleShapes)
| TEST (PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands)
| TEST (PathTest, PathCreatePolylineGeneratesCorrectContourData)
| TEST (PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges)
| TEST (PathTest, PathAddRectPolylineHasCorrectContourData)
| TEST (PathTest, PathPolylineDuplicatesAreRemovedForSameContour)
| TEST (PathTest, PolylineBufferReuse)
| TEST (PathTest, PolylineFailsWithNullptrBuffer)
| TEST (PathTest, PathShifting)
| TEST (PathTest, PathBuilderWillComputeBounds)
| TEST (PathTest, PathHorizontalLine)
| TEST (PathTest, PathVerticalLine)
| TEST (PathTest, QuadradicPath)
| TEST (PathTest, ConicPath)
| TEST (PathTest, CubicPath)
| TEST (PathTest, BoundingBoxCubic)
| TEST (PathTest, BoundingBoxOfCompositePathIsCorrect)
| TEST (PathTest, ExtremaOfCubicPathComponentIsCorrect)
| TEST (PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect)
| TEST (PathTest, EmptyPath)
| TEST (PathTest, SimplePath)
| TEST (PathTest, RepeatCloseDoesNotAddNewLines)
| TEST (PathTest, CloseAfterMoveDoesNotAddNewLines)
| TEST (PathTest, CloseAtOriginDoesNotAddNewLineSegment)
| TEST (PathTest, CanBeCloned)
| TEST (PathTest, FanTessellation)
| TEST (PathTest, FanTessellationUnclosedPath)
| TEST (PathTest, StripTessellationUnclosedPath)
| TEST (PathTest, FanTessellationMultiContour)
| TEST (PathTest, StripTessellation)
| TEST (PathTest, StripTessellationMultiContour)
| TEST (PathTest, PathBuilderAddPathBasher)
| TEST (PathTest, PathBuilderDoesNotMutateCopiedPaths)
| 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, SlimDiagnalContains)
| 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)
| TEST (BufferBindingsGLESTest, BindUniformData)
| 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 (TextureMTL, CreateFromDrawable)
| 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_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 (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)
| 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 (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)
| TEST (TessellatorTest, ChecksConcurrentPolylineUsage)
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 26 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 42 of file dl_unittests.cc.

## ◆ DriverInfoVKTest

using impeller::testing::DriverInfoVKTest = typedef PlaygroundTest

Definition at line 14 of file driver_info_vk_unittests.cc.

## ◆ EntityPassTargetTest

using impeller::testing::EntityPassTargetTest = typedef EntityPlayground

Definition at line 16 of file entity_pass_target_unittests.cc.

## ◆ EntityTest

typedef EntityPlayground impeller::testing::EntityTest

Definition at line 19 of file tiled_texture_contents_unittests.cc.

## ◆ HostBufferTest

using impeller::testing::HostBufferTest = typedef EntityPlayground

Definition at line 24 of file host_buffer_unittests.cc.

## ◆ PipelineCacheDataVKPlaygroundTest

using impeller::testing::PipelineCacheDataVKPlaygroundTest = typedef PlaygroundTest

Definition at line 95 of file pipeline_cache_data_vk_unittests.cc.

## ◆ RendererTest

typedef PlaygroundTest impeller::testing::RendererTest

Definition at line 14 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 499 of file aiks_dl_blend_unittests.cc.

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

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

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 91 of file aiks_dl_gradient_unittests.cc.

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

References impeller::AiksPlayground::OpenPlaygroundHere().

Referenced by TEST_P().

## ◆ CanRenderRadialGradientWithDithering()

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

Definition at line 111 of file aiks_dl_gradient_unittests.cc.

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

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 131 of file aiks_dl_gradient_unittests.cc.

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

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 1206 of file renderer_unittests.cc.

1206 {
1207 static CompareFunctionUIData data;
1208 return data;
1209 }
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67

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 1398 of file renderer_unittests.cc.

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

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:151
scale
const Scalar scale
Definition: stroke_path_geometry.cc:319

References impeller::TypographerContext::CreateGlyphAtlas(), scale, 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 }
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:322

References impeller::TypographerContext::CreateGlyphAtlas(), offset, scale, 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 24 of file canvas_unittests.cc.

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

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

1598 {
1599 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1600 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1601 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1602 Vector3 white = {1.0, 1.0, 1.0};
1603 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
1604 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
1605 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
1606 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
1607 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1608 std::vector<uint8_t> y_data;
1609 std::vector<uint8_t> uv_data;
1610 for (int i = 0; i < 4; i++) {
1611 auto yuv = yuvs[i];
1612 uint8_t y = std::round(yuv.x * 255.0);
1613 uint8_t u = std::round(yuv.y * 255.0);
1614 uint8_t v = std::round(yuv.z * 255.0);
1615 for (int j = 0; j < 16; j++) {
1616 y_data.push_back(y);
1617 }
1618 for (int j = 0; j < 8; j++) {
1619 uv_data.push_back(j % 2 == 0 ? u : v);
1620 }
1621 }
1622 auto cmd_buffer = context->CreateCommandBuffer();
1623 auto blit_pass = cmd_buffer->CreateBlitPass();
1624
1625 impeller::TextureDescriptor y_texture_descriptor;
1626 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1627 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
1628 y_texture_descriptor.size = {8, 8};
1629 auto y_texture =
1630 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
1631 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1632 auto y_mapping_buffer =
1633 context->GetResourceAllocator()->CreateBufferWithCopy(*y_mapping);
1634
1635 blit_pass->AddCopy(DeviceBuffer::AsBufferView(y_mapping_buffer), y_texture);
1636
1637 impeller::TextureDescriptor uv_texture_descriptor;
1638 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1639 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
1640 uv_texture_descriptor.size = {4, 4};
1641 auto uv_texture =
1642 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
1643 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1644 auto uv_mapping_buffer =
1645 context->GetResourceAllocator()->CreateBufferWithCopy(*uv_mapping);
1646
1647 blit_pass->AddCopy(DeviceBuffer::AsBufferView(uv_mapping_buffer), uv_texture);
1648
1649 if (!blit_pass->EncodeCommands() ||
1650 !context->GetCommandQueue()->Submit({cmd_buffer}).ok()) {
1651 FML_DLOG(ERROR) << "Could not copy contents into Y/UV texture.";
1652 }
1653
1654 return {y_texture, uv_texture};
1655 }
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1579
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 61 of file aiks_dl_blur_unittests.cc.

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

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

Referenced by TEST_P().

## ◆ flip_lr()

template<typename R >

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

Definition at line 1324 of file rect_unittests.cc.

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

Referenced by flip_lrtb(), and TEST().

## ◆ flip_lrtb()

template<typename R >

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

Definition at line 1336 of file rect_unittests.cc.

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

References flip_lr(), and flip_tb().

Referenced by TEST().

## ◆ flip_tb()

template<typename R >

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

Definition at line 1330 of file rect_unittests.cc.

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

Referenced by flip_lrtb(), and TEST().

## ◆ FML_TEST_CLASS()

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 504 of file aiks_dl_blur_unittests.cc.

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

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

1579 {
1580 Vector3 yuv;
1581 switch (yuv_color_space) {
1582 case YUVColorSpace::kBT601FullRange:
1583 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
1584 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
1585 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
1586 break;
1587 case YUVColorSpace::kBT601LimitedRange:
1588 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
1589 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
1590 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
1591 break;
1592 }
1593 return yuv;
1594 }

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

Referenced by CreateTestYUVTextures().

## ◆ swap_nan() [1/2]

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

Definition at line 1350 of file rect_unittests.cc.

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

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

## ◆ swap_nan() [2/2]

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

Definition at line 1340 of file rect_unittests.cc.

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

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

Referenced by TEST().

## ◆ TEST() [1/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 std::shared_ptr<ReactorGLES> reactor;
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 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
43 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
44
45 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
46 bound_buffers, Range{0, 0},
47 Range{0, 1}));
48 }
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:152
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() [20/501]

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 115 of file command_pool_vk_unittests.cc.

115 {
116 auto const context = MockVulkanContextBuilder().Build();
117
118 {
119 // Fetch a pool (which will be created).
120 auto const recycler = context->GetCommandPoolRecycler();
121 auto pool = recycler->Get();
122
123 auto buffer = pool->CreateCommandBuffer();
124 pool->CollectCommandBuffer(std::move(buffer));
125
126 // This normally is called at the end of a frame.
127 recycler->Dispose();
128 }
129
130 // Wait for the pool to be reclaimed.
131 for (auto i = 0u; i < 2u; i++) {
132 auto waiter = fml::AutoResetWaitableEvent();
133 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
134 {
135 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
136 std::move(rattle));
137 }
138 waiter.Wait();
139 }
140
141 {
142 // Create a second pool and command buffer, which should reused the existing
143 // pool and cmd buffer.
144 auto const recycler = context->GetCommandPoolRecycler();
145 auto pool = recycler->Get();
146
147 auto buffer = pool->CreateCommandBuffer();
148 pool->CollectCommandBuffer(std::move(buffer));
149
150 // This normally is called at the end of a frame.
151 recycler->Dispose();
152 }
153
154 // Now check that we only ever created one pool and one command buffer.
155 auto const called = GetMockVulkanFunctions(context->GetDevice());
156 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
157 1u);
158 EXPECT_EQ(
159 std::count(called->begin(), called->end(), "vkAllocateCommandBuffers"),
160 1u);
161
162 context->Shutdown();
163 }

## ◆ TEST() [32/501]

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

Definition at line 165 of file command_pool_vk_unittests.cc.

165 {
166 auto const context = MockVulkanContextBuilder().Build();
167
168 {
169 // Fetch a pool (which will be created).
170 auto const recycler = context->GetCommandPoolRecycler();
171 auto pool = recycler->Get();
172
173 // Allocate a large number of command buffers
174 for (auto i = 0; i < 64; i++) {
175 auto buffer = pool->CreateCommandBuffer();
176 pool->CollectCommandBuffer(std::move(buffer));
177 }
178
179 // This normally is called at the end of a frame.
180 recycler->Dispose();
181 }
182
183 // Wait for the pool to be reclaimed.
184 for (auto i = 0u; i < 2u; i++) {
185 auto waiter = fml::AutoResetWaitableEvent();
186 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
187 {
188 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
189 std::move(rattle));
190 }
191 waiter.Wait();
192 }
193
194 // Command pool is reset but does not release resources.
195 auto called = GetMockVulkanFunctions(context->GetDevice());
196 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetCommandPool"),
197 1u);
198
199 // Create the pool a second time, but dont use any command buffers.
200 {
201 // Fetch a pool (which will be created).
202 auto const recycler = context->GetCommandPoolRecycler();
203 auto pool = recycler->Get();
204
205 // This normally is called at the end of a frame.
206 recycler->Dispose();
207 }
208
209 // Wait for the pool to be reclaimed.
210 for (auto i = 0u; i < 2u; i++) {
211 auto waiter = fml::AutoResetWaitableEvent();
212 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
213 {
214 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
215 std::move(rattle));
216 }
217 waiter.Wait();
218 }
219
220 // Verify that the cmd pool was trimmed.
221
222 // Now check that we only ever created one pool and one command buffer.
223 called = GetMockVulkanFunctions(context->GetDevice());
224 EXPECT_EQ(std::count(called->begin(), called->end(),
225 "vkResetCommandPoolReleaseResources"),
226 1u);
227
228 context->Shutdown();
229 }

## ◆ TEST() [33/501]

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

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

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

Definition at line 76 of file command_pool_vk_unittests.cc.

76 {
77 auto const context = MockVulkanContextBuilder().Build();
78
79 {
80 // Fetch a pool (which will be created).
81 auto const recycler = context->GetCommandPoolRecycler();
82 auto const pool = recycler->Get();
83
84 // This normally is called at the end of a frame.
85 recycler->Dispose();
86 }
87
88 // Add something to the resource manager and have it notify us when it's
89 // destroyed. That should give us a non-flaky signal that the pool has been
90 // reclaimed as well.
91 auto waiter = fml::AutoResetWaitableEvent();
92 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
93 {
94 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
95 std::move(rattle));
96 }
97 waiter.Wait();
98
99 // On another thread explicitly, request a new pool.
100 std::thread thread([&]() {
101 auto const pool = context->GetCommandPoolRecycler()->Get();
102 EXPECT_NE(pool.get(), nullptr);
103 });
104
105 thread.join();
106
107 // Now check that we only ever created one pool.
108 auto const called = GetMockVulkanFunctions(context->GetDevice());
109 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
110 1u);
111
112 context->Shutdown();
113 }

## ◆ TEST() [36/501]

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

Definition at line 231 of file command_pool_vk_unittests.cc.

231 {
232 auto context = MockVulkanContextBuilder().Build();
233 auto const recycler = context->GetCommandPoolRecycler();
234
235 // The global pool list for this context should initially be empty.
236 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 0);
237
238 // Creating a pool for this thread should insert the pool into the global map.
239 auto pool = recycler->Get();
240 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 1);
241
242 // Disposing this thread's pool should remove it from the global map.
243 pool.reset();
244 recycler->Dispose();
245 EXPECT_EQ(CommandPoolRecyclerVK::GetGlobalPoolCount(*context), 0);
246
247 context->Shutdown();
248 }

References impeller::CommandPoolRecyclerVK::GetGlobalPoolCount().

## ◆ TEST() [37/501]

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 impeller::ConditionVariable::Wait().

## ◆ TEST() [38/501]

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 impeller::ConditionVariable::WaitFor().

## ◆ TEST() [39/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 140 of file geometry_unittests.cc.

140 {
141 auto matrix = Matrix::MakeScale(Vector2{3.0, 3.0});
142 EXPECT_EQ(Geometry::MakeStrokePath({}, 0.5)->ComputeAlphaCoverage(matrix), 1);
143 EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.1)->ComputeAlphaCoverage(matrix),
144 0.6, 0.05);
145 EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.05)->ComputeAlphaCoverage(matrix),
146 0.3, 0.05);
147 EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.01)->ComputeAlphaCoverage(matrix),
148 0.1, 0.1);
149 EXPECT_NEAR(
150 Geometry::MakeStrokePath({}, 0.0000005)->ComputeAlphaCoverage(matrix),
151 1e-05, 0.001);
152 EXPECT_EQ(Geometry::MakeStrokePath({}, 0)->ComputeAlphaCoverage(matrix), 1);
153 EXPECT_EQ(Geometry::MakeStrokePath({}, 40)->ComputeAlphaCoverage(matrix), 1);
154 }
impeller::Vector2
Point Vector2
Definition: point.h:331

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

## ◆ TEST() [84/501]

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

Definition at line 79 of file geometry_unittests.cc.

79 {
80 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
81 auto geometry = Geometry::MakeFillPath(
82 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
83 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
84 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
85 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
86 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
87 }
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792

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

## ◆ TEST() [85/501]

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

Definition at line 89 of file geometry_unittests.cc.

89 {
90 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
91 auto geometry = Geometry::MakeFillPath(path);
92 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
93 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
94 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
95 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
96 }

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

## ◆ TEST() [86/501]

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

Definition at line 133 of file geometry_unittests.cc.

133 {
134 GeometryResult result;
135 EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
136 EXPECT_EQ(result.transform, Matrix());
137 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
138 }

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

## ◆ TEST() [87/501]

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

Definition at line 98 of file geometry_unittests.cc.

98 {
99 {
100 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
101 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
102 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
103 }
104
105 {
106 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
107 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
108 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
109 }
110
111 {
112 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
113 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
114 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
115 }
116
117 {
118 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
119 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
120 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
121 }
122 }

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

## ◆ TEST() [88/501]

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

Definition at line 71 of file geometry_unittests.cc.

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

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

## ◆ TEST() [89/501]

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

Definition at line 124 of file geometry_unittests.cc.

124 {
125 auto geometry =
126 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
127 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
128 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
129 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
130 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
131 }
impeller::Size
TSize< Scalar > Size
Definition: size.h:159

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

## ◆ TEST() [90/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 // Terminate the waiter.
120 waiter->Terminate();
121
122 // Signal the fence.
123 raw_fence->SetStatus(vk::Result::eSuccess);
124
125 // This will hang if the fence was not signalled.
126 signal.Wait();
127 }

References value.

## ◆ TEST() [108/501]

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

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

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

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

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

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, 9);
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[8 - 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() [114/501]

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

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

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 }
EXPECT_RECT_NEAR
#define EXPECT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:203

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

## ◆ TEST() [117/501]

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

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

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

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

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

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 }
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32

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

## ◆ TEST() [123/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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(), impeller::Matrix::MakeScale(), and scale.

## ◆ TEST() [146/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References impeller::ScalarNearlyEqual().

## ◆ TEST() [179/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 58 of file line_contents_unittests.cc.

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

## ◆ TEST() [205/501]

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

Definition at line 122 of file line_contents_unittests.cc.

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

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

## ◆ TEST() [206/501]

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

Definition at line 37 of file line_contents_unittests.cc.

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

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

## ◆ TEST() [207/501]

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

Definition at line 99 of file line_contents_unittests.cc.

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

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

## ◆ TEST() [208/501]

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

Definition at line 110 of file line_contents_unittests.cc.

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

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

## ◆ TEST() [209/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impeller::testing::TEST | ( | PathTest | ,
|  | BoundingBoxCubic |
| ) |  |

Definition at line 660 of file path_unittests.cc.

660 {
661 PathBuilder builder;
662 auto path =
663 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
664 .TakePath();
665 auto box = path.GetBoundingBox();
666 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
667 ASSERT_TRUE(box.has_value());
668 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
669 }
ASSERT_RECT_NEAR
#define ASSERT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:191

References impeller::PathBuilder::AddCubicCurve(), ASSERT_RECT_NEAR, impeller::TRect< Scalar >::MakeMaximum(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [238/501]

impeller::testing::TEST | ( | PathTest | ,
|  | BoundingBoxOfCompositePathIsCorrect |
| ) |  |

Definition at line 671 of file path_unittests.cc.

671 {
672 PathBuilder builder;
673 builder.AddRoundRect(
674 RoundRect::MakeRectRadius(Rect::MakeXYWH(10, 10, 300, 300), 50));
675 auto path = builder.TakePath();
676 auto actual = path.GetBoundingBox();
677 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
678
679 ASSERT_TRUE(actual.has_value());
680 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
681 }

References impeller::PathBuilder::AddRoundRect(), ASSERT_RECT_NEAR, impeller::Path::GetBoundingBox(), impeller::TRect< Scalar >::MakeMaximum(), impeller::RoundRect::MakeRectRadius(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [239/501]

impeller::testing::TEST | ( | PathTest | ,
|  | CanBeCloned |
| ) |  |

Definition at line 885 of file path_unittests.cc.

885 {
886 PathBuilder builder;
887 builder.MoveTo({10, 10});
888 builder.LineTo({20, 20});
889 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
890 builder.SetConvexity(Convexity::kConvex);
891
892 auto path_a = builder.TakePath(FillType::kOdd);
893 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
894 auto path_b = path_a;
895
896 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
897 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
898 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
899
900 auto poly_a = path_a.CreatePolyline(1.0);
901 auto poly_b = path_b.CreatePolyline(1.0);
902
903 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
904 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
905
906 for (auto i = 0u; i < poly_a.points->size(); i++) {
907 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
908 }
909
910 for (auto i = 0u; i < poly_a.contours.size(); i++) {
911 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
912 EXPECT_EQ(poly_a.contours[i].start_direction,
913 poly_b.contours[i].start_direction);
914 }
915 }

References impeller::kConvex, impeller::kOdd, impeller::PathBuilder::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PathBuilder::MoveTo(), impeller::PathBuilder::SetBounds(), impeller::PathBuilder::SetConvexity(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [240/501]

impeller::testing::TEST | ( | PathTest | ,
|  | CloseAfterMoveDoesNotAddNewLines |
| ) |  |

Definition at line 855 of file path_unittests.cc.

855 {
856 PathBuilder builder;
857 auto path = builder.LineTo({0, 10})
858 .LineTo({10, 10})
859 .MoveTo({30, 30}) // Moves to (30, 30)
860 .Close() // No Op
861 .Close() // Still No op
862 .TakePath();
863
864 EXPECT_EQ(path.GetComponentCount(), 4u);
865 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
866 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
867 }
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
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:38

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::MoveTo().

## ◆ TEST() [241/501]

impeller::testing::TEST | ( | PathTest | ,
|  | CloseAtOriginDoesNotAddNewLineSegment |
| ) |  |

Definition at line 869 of file path_unittests.cc.

869 {
870 PathBuilder builder;
871 // Create a path that has a current position at the origin when close is
872 // called. This should not insert a new line segment
873 auto path = builder.LineTo({10, 0})
874 .LineTo({10, 10})
875 .LineTo({0, 10})
876 .LineTo({0, 0})
877 .Close()
878 .TakePath();
879
880 EXPECT_EQ(path.GetComponentCount(), 6u);
881 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
882 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
883 }

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), and impeller::PathBuilder::LineTo().

## ◆ TEST() [242/501]

impeller::testing::TEST | ( | PathTest | ,
|  | ConicPath |
| ) |  |

Definition at line 621 of file path_unittests.cc.

621 {
622 PathBuilder builder;
623 auto path =
624 builder.ConicCurveTo(Point(10, 10), Point(20, 20), 0.75f).TakePath();
625
626 auto it = path.begin();
627 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
628 ++it;
629
630 ASSERT_EQ(it.type(), Path::ComponentType::kConic);
631 const ConicPathComponent* conic = it.conic();
632 ASSERT_NE(conic, nullptr);
633
634 EXPECT_EQ(conic->p1, Point(0, 0));
635 EXPECT_EQ(conic->cp, Point(10, 10));
636 EXPECT_EQ(conic->p2, Point(20, 20));
637 EXPECT_EQ(conic->weight, Point(0.75f, 0.75f));
638 }

References impeller::Path::begin(), impeller::PathBuilder::ConicCurveTo(), impeller::ConicPathComponent::cp, impeller::Path::kConic, impeller::Path::kContour, impeller::ConicPathComponent::p1, impeller::ConicPathComponent::p2, impeller::PathBuilder::TakePath(), and impeller::ConicPathComponent::weight.

## ◆ TEST() [243/501]

impeller::testing::TEST | ( | PathTest | ,
|  | CubicPath |
| ) |  |

Definition at line 640 of file path_unittests.cc.

640 {
641 PathBuilder builder;
642 auto path =
643 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
644 .TakePath();
645
646 auto it = path.begin();
647 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
648 ++it;
649
650 ASSERT_EQ(it.type(), Path::ComponentType::kCubic);
651 const CubicPathComponent* cubic = it.cubic();
652 ASSERT_NE(cubic, nullptr);
653
654 EXPECT_EQ(cubic->p1, Point(0, 0));
655 EXPECT_EQ(cubic->cp1, Point(10, 10));
656 EXPECT_EQ(cubic->cp2, Point(-10, -10));
657 EXPECT_EQ(cubic->p2, Point(20, 20));
658 }

References impeller::Path::begin(), impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::PathBuilder::CubicCurveTo(), impeller::Path::kContour, impeller::Path::kCubic, impeller::CubicPathComponent::p1, impeller::CubicPathComponent::p2, and impeller::PathBuilder::TakePath().

## ◆ TEST() [244/501]

impeller::testing::TEST | ( | PathTest | ,
|  | CubicPathComponentPolylineDoesNotIncludePointOne |
| ) |  |

Definition at line 17 of file path_unittests.cc.

17 {
18 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
19 std::vector<Point> polyline;
20 component.AppendPolylinePoints(1.0f, polyline);
21 ASSERT_NE(polyline.front().x, 10);
22 ASSERT_NE(polyline.front().y, 10);
23 ASSERT_EQ(polyline.back().x, 40);
24 ASSERT_EQ(polyline.back().y, 40);
25 }
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:314

References polyline.

## ◆ TEST() [245/501]

impeller::testing::TEST | ( | PathTest | ,
|  | EmptyPath |
| ) |  |

Definition at line 706 of file path_unittests.cc.

706 {
707 auto path = PathBuilder{}.TakePath();
708 ASSERT_EQ(path.GetComponentCount(), 1u);
709
710 const ContourComponent* c = path.begin().contour();
711 ASSERT_POINT_NEAR(c->destination, Point());
712
713 Path::Polyline polyline = path.CreatePolyline(1.0f);
714 ASSERT_TRUE(polyline.points->empty());
715 ASSERT_TRUE(polyline.contours.empty());
716 }

References ASSERT_POINT_NEAR, impeller::ContourComponent::destination, polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [246/501]

impeller::testing::TEST | ( | PathTest | ,
|  | EmptyPathWithContour |
| ) |  |

Definition at line 27 of file path_unittests.cc.

27 {
28 PathBuilder builder;
29 auto path = builder.TakePath();
30
31 EXPECT_TRUE(path.IsEmpty());
32 }

References impeller::PathBuilder::TakePath().

## ◆ TEST() [247/501]

impeller::testing::TEST | ( | PathTest | ,
|  | ExtremaOfCubicPathComponentIsCorrect |
| ) |  |

Definition at line 683 of file path_unittests.cc.

683 {
684 CubicPathComponent cubic{{11.769268, 252.883148},
685 {-6.2857933, 204.356461},
686 {-4.53997231, 156.552902},
687 {17.0067291, 109.472488}};
688 auto points = cubic.Extrema();
689
690 ASSERT_EQ(points.size(), static_cast<size_t>(3));
691 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
692 }

References ASSERT_POINT_NEAR, and impeller::CubicPathComponent::Extrema().

## ◆ TEST() [248/501]

impeller::testing::TEST | ( | PathTest | ,
|  | FanTessellation |
| ) |  |

Definition at line 917 of file path_unittests.cc.

917 {
918 Path path = PathBuilder{}
919 .AddRoundRect(RoundRect::MakeRectRadius(
920 Rect::MakeLTRB(0, 0, 100, 100), 10))
921 .TakePath();
922 auto [points, contours] = path.CountStorage(1.0);
923
924 std::vector<Point> point_storage(points);
925 std::vector<uint16_t> index_storage(points + (contours - 1));
926
927 FanVertexWriter writer(point_storage.data(), index_storage.data());
928 path.WritePolyline(1.0, writer);
929
930 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
931 EXPECT_EQ(point_storage[0], Point(10, 0));
932 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::FanVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::PathBuilder::TakePath(), and impeller::Path::WritePolyline().

## ◆ TEST() [249/501]

impeller::testing::TEST | ( | PathTest | ,
|  | FanTessellationMultiContour |
| ) |  |

Definition at line 984 of file path_unittests.cc.

984 {
985 PathBuilder builder{};
986 for (auto i = 0; i < 10; i++) {
987 builder.AddRoundRect(
988 RoundRect::MakeRectRadius(Rect::MakeLTRB(0 + i, 0 + i, 100, 100), 10));
989 }
990 auto path = builder.TakePath();
991 auto [points, contours] = path.CountStorage(1.0);
992
993 std::vector<Point> point_storage(points);
994 std::vector<uint16_t> index_storage(points + (contours - 1));
995
996 FanVertexWriter writer(point_storage.data(), index_storage.data());
997 path.WritePolyline(1.0, writer);
998
999 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
1000 EXPECT_EQ(point_storage[0], Point(10, 0));
1001 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::FanVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [250/501]

impeller::testing::TEST | ( | PathTest | ,
|  | FanTessellationUnclosedPath |
| ) |  |

Definition at line 935 of file path_unittests.cc.

935 {
936 // Create a rectangle that lacks an explicit close.
937 Path path = PathBuilder{}
938 .LineTo({100, 0})
939 .LineTo({100, 100})
940 .LineTo({0, 100})
941 .TakePath();
942
943 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100},
944 {0, 100}, {0, 0}, {0, 0}};
945 std::vector<uint16_t> expected_indices = {0, 1, 2, 3, 0xFFFF, 0};
946
947 auto [points, contours] = path.CountStorage(1.0);
948
949 std::vector<Point> point_storage(points);
950 std::vector<uint16_t> index_storage(points + (contours - 1));
951
952 FanVertexWriter writer(point_storage.data(), index_storage.data());
953 path.WritePolyline(1.0, writer);
954
955 EXPECT_LE(index_storage, expected_indices);
956 EXPECT_EQ(point_storage, expected);
957 }

References impeller::Path::CountStorage(), impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::Path::WritePolyline().

## ◆ TEST() [251/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathAddRectPolylineHasCorrectContourData |
| ) |  |

Definition at line 409 of file path_unittests.cc.

409 {
410 Path::Polyline polyline = PathBuilder{}
411 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
412 .TakePath()
413 .CreatePolyline(1.0f);
414 ASSERT_EQ(polyline.contours.size(), 1u);
415 ASSERT_TRUE(polyline.contours[0].is_closed);
416 ASSERT_EQ(polyline.contours[0].start_index, 0u);
417 ASSERT_EQ(polyline.points->size(), 5u);
418 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
419 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
420 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
421 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
422 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
423 }

References impeller::PathBuilder::AddRect(), impeller::Path::CreatePolyline(), impeller::TRect< Scalar >::MakeLTRB(), polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [252/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathBuilderAddPathBasher |
| ) |  |

Definition at line 1039 of file path_unittests.cc.

1039 {
1040 PathBuilder test_path_builder;
1041 test_path_builder.AddOval(Rect::MakeLTRB(10, 10, 50, 50));
1042 Path test_path = test_path_builder.TakePath();
1043 for (int i = 0; i < 2000; i++) {
1044 PathBuilder path_builder;
1045 for (int j = 0; j < 10; j++) {
1046 path_builder.AddCircle(Point(50, 50), 25);
1047 path_builder.AddOval(Rect::MakeLTRB(100, 100, 200, 200));
1048 path_builder.AddPath(test_path);
1049 path_builder.AddRect(Rect::MakeLTRB(50, 50, 75, 57));
1050 path_builder.AddLine(Point(80, 70), Point(110, 95));
1051 path_builder.AddArc(Rect::MakeLTRB(50, 50, 100, 100), Degrees(20),
1052 Degrees(100));
1053 path_builder.AddRoundRect(RoundRect::MakeRectXY(
1054 Rect::MakeLTRB(70, 70, 130, 130), Size(10, 10)));
1055 }
1056 Path test_path = path_builder.TakePath();
1057 auto bounds = test_path.GetBoundingBox();
1058 EXPECT_TRUE(bounds.has_value());
1059 if (bounds.has_value()) {
1060 EXPECT_EQ(bounds.value(), Rect::MakeLTRB(10, 10, 200, 200));
1061 }
1062 }
1063 }

References impeller::PathBuilder::AddArc(), impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddPath(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::Path::GetBoundingBox(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectXY(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [253/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathBuilderDoesNotMutateCopiedPaths |
| ) |  |

Definition at line 1065 of file path_unittests.cc.

1065 {
1066 auto test_isolation =
1067 [](const std::function<void(PathBuilder & builder)>& mutator,
1068 bool will_close, Point mutation_offset, const std::string& label) {
1069 PathBuilder builder;
1070 builder.MoveTo({10, 10});
1071 builder.LineTo({20, 20});
1072 builder.LineTo({20, 10});
1073
1074 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
1075 Point offset, const std::string& label) {
1076 if (is_mutated) {
1077 // We can only test the initial state before the mutator did
1078 // its work. We have >= 3 components and the first 3 components
1079 // will match what we saw before the mutation.
1080 EXPECT_GE(path.GetComponentCount(), 3u) << label;
1081 } else {
1082 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
1083 }
1084 auto it = path.begin();
1085 {
1086 ASSERT_EQ(it.type(), Path::ComponentType::kContour) << label;
1087 const ContourComponent* contour = it.contour();
1088 ASSERT_NE(contour, nullptr) << label;
1089 ++it;
1090
1091 EXPECT_EQ(contour->destination, offset + Point(10, 10)) << label;
1092 EXPECT_EQ(contour->IsClosed(), is_closed) << label;
1093 }
1094 {
1095 ASSERT_EQ(it.type(), Path::ComponentType::kLinear) << label;
1096 const LinearPathComponent* line = it.linear();
1097 ASSERT_NE(line, nullptr) << label;
1098 ++it;
1099
1100 EXPECT_EQ(line->p1, offset + Point(10, 10)) << label;
1101 EXPECT_EQ(line->p2, offset + Point(20, 20)) << label;
1102 }
1103 {
1104 ASSERT_EQ(it.type(), Path::ComponentType::kLinear) << label;
1105 const LinearPathComponent* line = it.linear();
1106 ASSERT_NE(line, nullptr) << label;
1107 ++it;
1108
1109 EXPECT_EQ(line->p1, offset + Point(20, 20)) << label;
1110 EXPECT_EQ(line->p2, offset + Point(20, 10)) << label;
1111 }
1112 if (!is_mutated) {
1113 EXPECT_EQ(it, path.end()) << label;
1114 }
1115 };
1116
1117 auto path1 = builder.CopyPath();
1118 verify_path(path1, false, false, {},
1119 "Initial Path1 state before " + label);
1120
1121 for (int i = 0; i < 10; i++) {
1122 auto path = builder.CopyPath();
1123 verify_path(
1124 path, false, false, {},
1125 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
1126 }
1127 mutator(builder);
1128 verify_path(path1, false, false, {},
1129 "Path1 state after subsequent " + label);
1130
1131 auto path2 = builder.CopyPath();
1132 verify_path(path1, false, false, {},
1133 "Path1 state after subsequent " + label + " and CopyPath");
1134 verify_path(path2, true, will_close, mutation_offset,
1135 "Initial Path2 state with subsequent " + label);
1136 };
1137
1138 test_isolation(
1139 [](PathBuilder& builder) { //
1140 builder.SetConvexity(Convexity::kConvex);
1141 },
1142 false, {}, "SetConvex");
1143
1144 test_isolation(
1145 [](PathBuilder& builder) { //
1146 builder.SetConvexity(Convexity::kUnknown);
1147 },
1148 false, {}, "SetUnknownConvex");
1149
1150 test_isolation(
1151 [](PathBuilder& builder) { //
1152 builder.Close();
1153 },
1154 true, {}, "Close");
1155
1156 test_isolation(
1157 [](PathBuilder& builder) {
1158 builder.MoveTo({20, 30}, false);
1159 },
1160 false, {}, "Absolute MoveTo");
1161
1162 test_isolation(
1163 [](PathBuilder& builder) {
1164 builder.MoveTo({20, 30}, true);
1165 },
1166 false, {}, "Relative MoveTo");
1167
1168 test_isolation(
1169 [](PathBuilder& builder) {
1170 builder.LineTo({20, 30}, false);
1171 },
1172 false, {}, "Absolute LineTo");
1173
1174 test_isolation(
1175 [](PathBuilder& builder) {
1176 builder.LineTo({20, 30}, true);
1177 },
1178 false, {}, "Relative LineTo");
1179
1180 test_isolation(
1181 [](PathBuilder& builder) { //
1182 builder.HorizontalLineTo(100, false);
1183 },
1184 false, {}, "Absolute HorizontalLineTo");
1185
1186 test_isolation(
1187 [](PathBuilder& builder) { //
1188 builder.HorizontalLineTo(100, true);
1189 },
1190 false, {}, "Relative HorizontalLineTo");
1191
1192 test_isolation(
1193 [](PathBuilder& builder) { //
1194 builder.VerticalLineTo(100, false);
1195 },
1196 false, {}, "Absolute VerticalLineTo");
1197
1198 test_isolation(
1199 [](PathBuilder& builder) { //
1200 builder.VerticalLineTo(100, true);
1201 },
1202 false, {}, "Relative VerticalLineTo");
1203
1204 test_isolation(
1205 [](PathBuilder& builder) {
1206 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
1207 },
1208 false, {}, "Absolute QuadraticCurveTo");
1209
1210 test_isolation(
1211 [](PathBuilder& builder) {
1212 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
1213 },
1214 false, {}, "Relative QuadraticCurveTo");
1215
1216 test_isolation(
1217 [](PathBuilder& builder) {
1218 builder.ConicCurveTo({20, 30}, {30, 20}, 0.75f, false);
1219 },
1220 false, {}, "Absolute ConicCurveTo");
1221
1222 test_isolation(
1223 [](PathBuilder& builder) {
1224 builder.ConicCurveTo({20, 30}, {30, 20}, 0.75f, true);
1225 },
1226 false, {}, "Relative ConicCurveTo");
1227
1228 test_isolation(
1229 [](PathBuilder& builder) {
1230 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
1231 },
1232 false, {}, "Absolute CubicCurveTo");
1233
1234 test_isolation(
1235 [](PathBuilder& builder) {
1236 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
1237 },
1238 false, {}, "Relative CubicCurveTo");
1239
1240 test_isolation(
1241 [](PathBuilder& builder) {
1242 builder.AddLine({100, 100}, {150, 100});
1243 },
1244 false, {}, "AddLine");
1245
1246 test_isolation(
1247 [](PathBuilder& builder) {
1248 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
1249 },
1250 false, {}, "AddRect");
1251
1252 test_isolation(
1253 [](PathBuilder& builder) {
1254 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
1255 },
1256 false, {}, "AddOval");
1257
1258 test_isolation(
1259 [](PathBuilder& builder) {
1260 builder.AddCircle({100, 100}, 20);
1261 },
1262 false, {}, "AddCircle");
1263
1264 test_isolation(
1265 [](PathBuilder& builder) {
1266 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
1267 Degrees(170));
1268 },
1269 false, {}, "AddArc");
1270
1271 test_isolation(
1272 [](PathBuilder& builder) {
1273 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
1274 },
1275 false, {}, "AddQuadraticCurve");
1276
1277 test_isolation(
1278 [](PathBuilder& builder) {
1279 builder.AddConicCurve({100, 100}, {150, 100}, {150, 150}, 0.75f);
1280 },
1281 false, {}, "AddConicCurve");
1282
1283 test_isolation(
1284 [](PathBuilder& builder) {
1285 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
1286 },
1287 false, {}, "AddCubicCurve");
1288
1289 test_isolation(
1290 [](PathBuilder& builder) {
1291 builder.Shift({23, 42});
1292 },
1293 false, {23, 42}, "Shift");
1294 }

References impeller::PathBuilder::AddArc(), impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddConicCurve(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::Path::begin(), impeller::PathBuilder::Close(), impeller::PathBuilder::ConicCurveTo(), impeller::PathBuilder::CopyPath(), impeller::PathBuilder::CubicCurveTo(), impeller::ContourComponent::destination, impeller::Path::end(), impeller::Path::GetComponentCount(), impeller::PathBuilder::HorizontalLineTo(), impeller::ContourComponent::IsClosed(), impeller::Path::kContour, impeller::kConvex, impeller::Path::kLinear, impeller::kUnknown, impeller::PathBuilder::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PathBuilder::MoveTo(), offset, impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, impeller::PathBuilder::QuadraticCurveTo(), impeller::PathBuilder::SetConvexity(), impeller::PathBuilder::Shift(), and impeller::PathBuilder::VerticalLineTo().

## ◆ TEST() [254/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathBuilderSetsCorrectContourPropertiesForAddCommands |
| ) |  |

Definition at line 238 of file path_unittests.cc.

238 {
239 // Closed shapes.
240 {
241 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
242 EXPECT_NE(path.begin(), path.end());
243 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
244 auto contour = path.begin().contour();
245 ASSERT_NE(contour, nullptr);
246 EXPECT_POINT_NEAR(contour->destination, Point(100, 50));
247 EXPECT_TRUE(contour->IsClosed());
248 }
249
250 {
251 Path path =
252 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
253 EXPECT_NE(path.begin(), path.end());
254 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
255 auto contour = path.begin().contour();
256 ASSERT_NE(contour, nullptr);
257 EXPECT_POINT_NEAR(contour->destination, Point(150, 100));
258 EXPECT_TRUE(contour->IsClosed());
259 }
260
261 {
262 Path path =
263 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
264 EXPECT_NE(path.begin(), path.end());
265 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
266 auto contour = path.begin().contour();
267 ASSERT_NE(contour, nullptr);
268 EXPECT_POINT_NEAR(contour->destination, Point(100, 100));
269 EXPECT_TRUE(contour->IsClosed());
270 }
271
272 {
273 Path path = PathBuilder{}
274 .AddRoundRect(RoundRect::MakeRectRadius(
275 Rect::MakeXYWH(100, 100, 100, 100), 10))
276 .TakePath();
277 EXPECT_NE(path.begin(), path.end());
278 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
279 auto contour = path.begin().contour();
280 ASSERT_NE(contour, nullptr);
281 EXPECT_POINT_NEAR(contour->destination, Point(110, 100));
282 EXPECT_TRUE(contour->IsClosed());
283 }
284
285 {
286 Path path = PathBuilder{}
287 .AddRoundRect(RoundRect::MakeRectXY(
288 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
289 .TakePath();
290 EXPECT_NE(path.begin(), path.end());
291 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
292 auto contour = path.begin().contour();
293 ASSERT_NE(contour, nullptr);
294 EXPECT_POINT_NEAR(contour->destination, Point(110, 100));
295 EXPECT_TRUE(contour->IsClosed());
296 }
297
298 {
299 Path path = PathBuilder{}
300 .AddRoundSuperellipse(RoundSuperellipse::MakeRectRadius(
301 Rect::MakeXYWH(100, 100, 100, 100), 10))
302 .TakePath();
303 EXPECT_NE(path.begin(), path.end());
304 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
305 auto contour = path.begin().contour();
306 ASSERT_NE(contour, nullptr);
307 EXPECT_POINT_NEAR(contour->destination, Point(150, 100));
308 EXPECT_TRUE(contour->IsClosed());
309 }
310
311 {
312 Path path = PathBuilder{}
313 .AddRoundSuperellipse(RoundSuperellipse::MakeRectXY(
314 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
315 .TakePath();
316 EXPECT_NE(path.begin(), path.end());
317 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
318 auto contour = path.begin().contour();
319 ASSERT_NE(contour, nullptr);
320 EXPECT_POINT_NEAR(contour->destination, Point(150, 100));
321 EXPECT_TRUE(contour->IsClosed());
322 }
323
324 // Open shapes.
325 {
326 Point p(100, 100);
327 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
328 EXPECT_NE(path.begin(), path.end());
329 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
330 auto contour = path.begin().contour();
331 ASSERT_NE(contour, nullptr);
332 EXPECT_POINT_NEAR(contour->destination, p);
333 EXPECT_FALSE(contour->IsClosed());
334 }
335
336 {
337 Path path =
338 PathBuilder{}
339 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
340 .TakePath();
341 EXPECT_NE(path.begin(), path.end());
342 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
343 auto contour = path.begin().contour();
344 ASSERT_NE(contour, nullptr);
345 EXPECT_POINT_NEAR(contour->destination, Point(100, 100));
346 EXPECT_FALSE(contour->IsClosed());
347 }
348
349 {
350 Path path = PathBuilder{}
351 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
352 .TakePath();
353 EXPECT_NE(path.begin(), path.end());
354 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
355 auto contour = path.begin().contour();
356 ASSERT_NE(contour, nullptr);
357 EXPECT_POINT_NEAR(contour->destination, Point(100, 100));
358 EXPECT_FALSE(contour->IsClosed());
359 }
360
361 {
362 Path path = PathBuilder{}
363 .AddConicCurve({100, 100}, {100, 50}, {200, 100}, 0.75f)
364 .TakePath();
365 EXPECT_NE(path.begin(), path.end());
366 EXPECT_EQ(path.begin().type(), Path::ComponentType::kContour);
367 auto contour = path.begin().contour();
368 ASSERT_NE(contour, nullptr);
369 EXPECT_POINT_NEAR(contour->destination, Point(100, 100));
370 EXPECT_FALSE(contour->IsClosed());
371 }
372 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddConicCurve(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::PathBuilder::AddRoundSuperellipse(), impeller::Path::begin(), impeller::Path::ComponentIterator::contour(), impeller::Path::end(), EXPECT_POINT_NEAR, impeller::Path::kContour, impeller::RoundRect::MakeRectRadius(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::RoundRect::MakeRectXY(), impeller::RoundSuperellipse::MakeRectXY(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PathBuilder::TakePath(), and impeller::Path::ComponentIterator::type().

## ◆ TEST() [255/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathBuilderWillComputeBounds |
| ) |  |

Definition at line 550 of file path_unittests.cc.

550 {
551 PathBuilder builder;
552 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
553
554 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
555 Rect::MakeLTRB(0, 0, 1, 1));
556
557 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
558
559 // Verify that PathBuilder recomputes the bounds.
560 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
561 Rect::MakeLTRB(-1, -1, 1, 1));
562
563 // PathBuilder can set the bounds to whatever it wants
564 auto path_3 = builder.AddLine({0, 0}, {1, 1})
565 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
566 .TakePath();
567
568 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
569 Rect::MakeLTRB(0, 0, 100, 100));
570 }

References impeller::PathBuilder::AddLine(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeMaximum(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [256/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathCreatePolyLineDoesNotDuplicatePoints |
| ) |  |

Definition at line 34 of file path_unittests.cc.

34 {
35 PathBuilder builder;
36 builder.MoveTo({10, 10});
37 builder.LineTo({20, 20});
38 builder.LineTo({30, 30});
39 builder.MoveTo({40, 40});
40 builder.LineTo({50, 50});
41
42 auto polyline = builder.TakePath().CreatePolyline(1.0f);
43
44 ASSERT_EQ(polyline.contours.size(), 2u);
45 ASSERT_EQ(polyline.points->size(), 5u);
46 ASSERT_EQ(polyline.GetPoint(0).x, 10);
47 ASSERT_EQ(polyline.GetPoint(1).x, 20);
48 ASSERT_EQ(polyline.GetPoint(2).x, 30);
49 ASSERT_EQ(polyline.GetPoint(3).x, 40);
50 ASSERT_EQ(polyline.GetPoint(4).x, 50);
51 }

References impeller::Path::CreatePolyline(), impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [257/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathCreatePolylineGeneratesCorrectContourData |
| ) |  |

Definition at line 374 of file path_unittests.cc.

374 {
375 Path::Polyline polyline = PathBuilder{}
376 .AddLine({100, 100}, {200, 100})
377 .MoveTo({100, 200})
378 .LineTo({150, 250})
379 .LineTo({200, 200})
380 .Close()
381 .TakePath()
382 .CreatePolyline(1.0f);
383 ASSERT_EQ(polyline.points->size(), 6u);
384 ASSERT_EQ(polyline.contours.size(), 2u);
385 ASSERT_EQ(polyline.contours[0].is_closed, false);
386 ASSERT_EQ(polyline.contours[0].start_index, 0u);
387 ASSERT_EQ(polyline.contours[1].is_closed, true);
388 ASSERT_EQ(polyline.contours[1].start_index, 2u);
389 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::LineTo(), impeller::MoveTo(), and polyline.

## ◆ TEST() [258/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect |
| ) |  |

Definition at line 694 of file path_unittests.cc.

694 {
695 PathBuilder builder;
696 // Straight diagonal line.
697 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
698 auto path = builder.TakePath();
699 auto actual = path.GetBoundingBox();
700 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
701
702 ASSERT_TRUE(actual.has_value());
703 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
704 }

References impeller::PathBuilder::AddCubicCurve(), ASSERT_RECT_NEAR, impeller::Path::GetBoundingBox(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeMaximum(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [259/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathHorizontalLine |
| ) |  |

Definition at line 572 of file path_unittests.cc.

572 {
573 PathBuilder builder;
574 auto path = builder.HorizontalLineTo(10).TakePath();
575
576 auto it = path.begin();
577 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
578 ++it;
579
580 ASSERT_EQ(it.type(), Path::ComponentType::kLinear);
581 const LinearPathComponent* linear = it.linear();
582 ASSERT_NE(linear, nullptr);
583
584 EXPECT_EQ(linear->p1, Point(0, 0));
585 EXPECT_EQ(linear->p2, Point(10, 0));
586 }

References impeller::Path::begin(), impeller::PathBuilder::HorizontalLineTo(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, and impeller::PathBuilder::TakePath().

## ◆ TEST() [260/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathPolylineDuplicatesAreRemovedForSameContour |
| ) |  |

Definition at line 425 of file path_unittests.cc.

425 {
426 Path::Polyline polyline =
427 PathBuilder{}
428 .MoveTo({50, 50})
429 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
430 .LineTo({100, 50})
431 .LineTo({100, 50}) // Insert duplicate at contour join.
432 .LineTo({100, 100})
433 .Close() // Implicitly insert duplicate {50, 50} across contours.
434 .LineTo({0, 50})
435 .LineTo({0, 100})
436 .LineTo({0, 100}) // Insert duplicate at end of contour.
437 .TakePath()
438 .CreatePolyline(1.0f);
439 ASSERT_EQ(polyline.contours.size(), 2u);
440 ASSERT_EQ(polyline.contours[0].start_index, 0u);
441 ASSERT_TRUE(polyline.contours[0].is_closed);
442 ASSERT_EQ(polyline.contours[1].start_index, 4u);
443 ASSERT_FALSE(polyline.contours[1].is_closed);
444 ASSERT_EQ(polyline.points->size(), 7u);
445 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
446 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
447 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
448 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
449 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
450 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
451 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
452 }

References impeller::Close(), impeller::LineTo(), impeller::PathBuilder::MoveTo(), and polyline.

## ◆ TEST() [261/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathShifting |
| ) |  |

Definition at line 481 of file path_unittests.cc.

481 {
482 PathBuilder builder{};
483 auto path =
484 builder.AddLine(Point(0, 0), Point(10, 10))
485 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
486 .AddConicCurve(Point(10, 10), Point(15, 10), Point(15, 15), 0.75f)
487 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
488 Point(30, 30))
489 .Close()
490 .Shift(Point(1, 1))
491 .TakePath();
492
493 auto it = path.begin();
494
495 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
496 const ContourComponent* contour = it.contour();
497 ASSERT_NE(contour, nullptr);
498 ++it;
499
500 ASSERT_EQ(it.type(), Path::ComponentType::kLinear);
501 const LinearPathComponent* linear = it.linear();
502 ASSERT_NE(linear, nullptr);
503 ++it;
504
505 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
506 ++it;
507
508 ASSERT_EQ(it.type(), Path::ComponentType::kQuadratic);
509 const QuadraticPathComponent* quad = it.quadratic();
510 ASSERT_NE(quad, nullptr);
511 ++it;
512
513 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
514 ++it;
515
516 ASSERT_EQ(it.type(), Path::ComponentType::kConic);
517 const ConicPathComponent* conic = it.conic();
518 ASSERT_NE(conic, nullptr);
519 ++it;
520
521 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
522 ++it;
523
524 ASSERT_EQ(it.type(), Path::ComponentType::kCubic);
525 const CubicPathComponent* cubic = it.cubic();
526 ASSERT_NE(cubic, nullptr);
527 ++it;
528
529 // Close always opens a new contour, even if it isn't needed
530 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
531 ++it;
532
533 EXPECT_EQ(it, path.end());
534
535 EXPECT_EQ(contour->destination, Point(1, 1));
536
537 EXPECT_EQ(linear->p1, Point(1, 1));
538 EXPECT_EQ(linear->p2, Point(11, 11));
539
540 EXPECT_EQ(quad->cp, Point(16, 16));
541 EXPECT_EQ(quad->p1, Point(11, 11));
542 EXPECT_EQ(quad->p2, Point(21, 21));
543
544 EXPECT_EQ(cubic->cp1, Point(26, 26));
545 EXPECT_EQ(cubic->cp2, Point(-4, -4));
546 EXPECT_EQ(cubic->p1, Point(21, 21));
547 EXPECT_EQ(cubic->p2, Point(31, 31));
548 }

References impeller::PathBuilder::AddConicCurve(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddQuadraticCurve(), impeller::Path::begin(), impeller::PathBuilder::Close(), impeller::QuadraticPathComponent::cp, impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::ContourComponent::destination, impeller::Path::kConic, impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, impeller::LinearPathComponent::p1, impeller::QuadraticPathComponent::p1, impeller::CubicPathComponent::p1, impeller::LinearPathComponent::p2, impeller::QuadraticPathComponent::p2, impeller::CubicPathComponent::p2, impeller::PathBuilder::Shift(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [262/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathSingleContour |
| ) |  |

Definition at line 53 of file path_unittests.cc.

53 {
54 // Closed shapes.
55 {
56 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
57 EXPECT_TRUE(path.IsSingleContour());
58 }
59
60 {
61 Path path =
62 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
63
64 EXPECT_TRUE(path.IsSingleContour());
65 }
66
67 {
68 Path path =
69 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
70
71 EXPECT_TRUE(path.IsSingleContour());
72 }
73
74 {
75 Path path = PathBuilder{}
76 .AddRoundRect(RoundRect::MakeRectRadius(
77 Rect::MakeXYWH(100, 100, 100, 100), 10))
78 .TakePath();
79
80 EXPECT_TRUE(path.IsSingleContour());
81 }
82
83 {
84 Path path = PathBuilder{}
85 .AddRoundSuperellipse(RoundSuperellipse::MakeRectRadius(
86 Rect::MakeXYWH(100, 100, 100, 100), 10))
87 .TakePath();
88
89 EXPECT_TRUE(path.IsSingleContour());
90 }
91
92 // Open shapes.
93 {
94 Point p(100, 100);
95 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
96
97 EXPECT_TRUE(path.IsSingleContour());
98 }
99
100 {
101 Path path =
102 PathBuilder{}
103 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
104 .TakePath();
105
106 EXPECT_TRUE(path.IsSingleContour());
107 }
108
109 {
110 Path path = PathBuilder{}
111 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
112 .TakePath();
113
114 EXPECT_TRUE(path.IsSingleContour());
115 }
116
117 {
118 Path path = PathBuilder{}
119 .AddConicCurve({100, 100}, {100, 50}, {200, 100}, 0.75f)
120 .TakePath();
121
122 EXPECT_TRUE(path.IsSingleContour());
123 }
124 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddConicCurve(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::PathBuilder::AddRoundSuperellipse(), impeller::Path::IsSingleContour(), impeller::RoundRect::MakeRectRadius(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [263/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathSingleContourDoubleShapes |
| ) |  |

Definition at line 126 of file path_unittests.cc.

126 {
127 // Closed shapes.
128 {
129 Path path = PathBuilder{}
130 .AddCircle({100, 100}, 50)
131 .AddCircle({100, 100}, 50)
132 .TakePath();
133 EXPECT_FALSE(path.IsSingleContour());
134 }
135
136 {
137 Path path = PathBuilder{}
138 .AddOval(Rect::MakeXYWH(100, 100, 100, 100))
139 .AddOval(Rect::MakeXYWH(100, 100, 100, 100))
140 .TakePath();
141
142 EXPECT_FALSE(path.IsSingleContour());
143 }
144
145 {
146 Path path = PathBuilder{}
147 .AddRect(Rect::MakeXYWH(100, 100, 100, 100))
148 .AddRect(Rect::MakeXYWH(100, 100, 100, 100))
149 .TakePath();
150
151 EXPECT_FALSE(path.IsSingleContour());
152 }
153
154 {
155 Path path = PathBuilder{}
156 .AddRoundRect(RoundRect::MakeRectRadius(
157 Rect::MakeXYWH(100, 100, 100, 100), 10))
158 .AddRoundRect(RoundRect::MakeRectRadius(
159 Rect::MakeXYWH(100, 100, 100, 100), 10))
160 .TakePath();
161
162 EXPECT_FALSE(path.IsSingleContour());
163 }
164
165 {
166 Path path = PathBuilder{}
167 .AddRoundRect(RoundRect::MakeRectXY(
168 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
169 .AddRoundRect(RoundRect::MakeRectXY(
170 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
171 .TakePath();
172
173 EXPECT_FALSE(path.IsSingleContour());
174 }
175
176 {
177 Path path = PathBuilder{}
178 .AddRoundSuperellipse(RoundSuperellipse::MakeRectRadius(
179 Rect::MakeXYWH(100, 100, 100, 100), 10))
180 .AddRoundSuperellipse(RoundSuperellipse::MakeRectRadius(
181 Rect::MakeXYWH(100, 100, 100, 100), 10))
182 .TakePath();
183
184 EXPECT_FALSE(path.IsSingleContour());
185 }
186
187 {
188 Path path = PathBuilder{}
189 .AddRoundSuperellipse(RoundSuperellipse::MakeRectXY(
190 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
191 .AddRoundSuperellipse(RoundSuperellipse::MakeRectXY(
192 Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20)))
193 .TakePath();
194
195 EXPECT_FALSE(path.IsSingleContour());
196 }
197
198 // Open shapes.
199 {
200 Point p(100, 100);
201 Path path =
202 PathBuilder{}.AddLine(p, {200, 100}).AddLine(p, {200, 100}).TakePath();
203
204 EXPECT_FALSE(path.IsSingleContour());
205 }
206
207 {
208 Path path =
209 PathBuilder{}
210 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
211 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
212 .TakePath();
213
214 EXPECT_FALSE(path.IsSingleContour());
215 }
216
217 {
218 Path path = PathBuilder{}
219 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
220 .Close()
221 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
222 .TakePath();
223
224 EXPECT_FALSE(path.IsSingleContour());
225 }
226
227 {
228 Path path = PathBuilder{}
229 .AddConicCurve({100, 100}, {100, 50}, {200, 100}, 0.75f)
230 .Close()
231 .AddConicCurve({100, 100}, {100, 50}, {200, 100}, 0.75f)
232 .TakePath();
233
234 EXPECT_FALSE(path.IsSingleContour());
235 }
236 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddConicCurve(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundRect(), impeller::PathBuilder::AddRoundSuperellipse(), impeller::Close(), impeller::Path::IsSingleContour(), impeller::RoundRect::MakeRectRadius(), impeller::RoundSuperellipse::MakeRectRadius(), impeller::RoundRect::MakeRectXY(), impeller::RoundSuperellipse::MakeRectXY(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [264/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PathVerticalLine |
| ) |  |

Definition at line 588 of file path_unittests.cc.

588 {
589 PathBuilder builder;
590 auto path = builder.VerticalLineTo(10).TakePath();
591
592 auto it = path.begin();
593 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
594 ++it;
595
596 ASSERT_EQ(it.type(), Path::ComponentType::kLinear);
597 const LinearPathComponent* linear = it.linear();
598 ASSERT_NE(linear, nullptr);
599
600 EXPECT_EQ(linear->p1, Point(0, 0));
601 EXPECT_EQ(linear->p2, Point(0, 10));
602 }

References impeller::Path::begin(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, impeller::PathBuilder::TakePath(), and impeller::PathBuilder::VerticalLineTo().

## ◆ TEST() [265/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PolylineBufferReuse |
| ) |  |

Definition at line 454 of file path_unittests.cc.

454 {
455 auto point_buffer = std::make_unique<std::vector<Point>>();
456 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
457 Path::Polyline polyline =
458 PathBuilder{}
459 .MoveTo({50, 50})
460 .LineTo({100, 100})
461 .TakePath()
462 .CreatePolyline(
463 1.0f, std::move(point_buffer),
464 [point_buffer_address](
465 Path::Polyline::PointBufferPtr point_buffer) {
466 ASSERT_EQ(point_buffer->size(), 0u);
467 ASSERT_EQ(point_buffer_address,
468 reinterpret_cast<uintptr_t>(point_buffer.get()));
469 });
470 }

References impeller::LineTo(), impeller::PathBuilder::MoveTo(), and polyline.

## ◆ TEST() [266/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PolylineFailsWithNullptrBuffer |
| ) |  |

Definition at line 472 of file path_unittests.cc.

472 {
473 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
474 .MoveTo({50, 50})
475 .LineTo({100, 100})
476 .TakePath()
477 .CreatePolyline(1.0f, nullptr),
478 "");
479 }

References impeller::LineTo(), and impeller::PathBuilder::MoveTo().

## ◆ TEST() [267/501]

impeller::testing::TEST | ( | PathTest | ,
|  | PolylineGetContourPointBoundsReturnsCorrectRanges |
| ) |  |

Definition at line 391 of file path_unittests.cc.

391 {
392 Path::Polyline polyline = PathBuilder{}
393 .AddLine({100, 100}, {200, 100})
394 .MoveTo({100, 200})
395 .LineTo({150, 250})
396 .LineTo({200, 200})
397 .Close()
398 .TakePath()
399 .CreatePolyline(1.0f);
400 size_t a1, a2, b1, b2;
401 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
402 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
403 ASSERT_EQ(a1, 0u);
404 ASSERT_EQ(a2, 2u);
405 ASSERT_EQ(b1, 2u);
406 ASSERT_EQ(b2, 6u);
407 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::LineTo(), impeller::MoveTo(), and polyline.

## ◆ TEST() [268/501]

impeller::testing::TEST | ( | PathTest | ,
|  | QuadradicPath |
| ) |  |

Definition at line 604 of file path_unittests.cc.

604 {
605 PathBuilder builder;
606 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
607
608 auto it = path.begin();
609 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
610 ++it;
611
612 ASSERT_EQ(it.type(), Path::ComponentType::kQuadratic);
613 const QuadraticPathComponent* quad = it.quadratic();
614 ASSERT_NE(quad, nullptr);
615
616 EXPECT_EQ(quad->p1, Point(0, 0));
617 EXPECT_EQ(quad->cp, Point(10, 10));
618 EXPECT_EQ(quad->p2, Point(20, 20));
619 }

References impeller::Path::begin(), impeller::QuadraticPathComponent::cp, impeller::Path::kContour, impeller::Path::kQuadratic, impeller::QuadraticPathComponent::p1, impeller::QuadraticPathComponent::p2, impeller::PathBuilder::QuadraticCurveTo(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [269/501]

impeller::testing::TEST | ( | PathTest | ,
|  | RepeatCloseDoesNotAddNewLines |
| ) |  |

Definition at line 841 of file path_unittests.cc.

841 {
842 PathBuilder builder;
843 auto path = builder.LineTo({0, 10})
844 .LineTo({10, 10})
845 .Close() // Returns to (0, 0)
846 .Close() // No Op
847 .Close() // Still No op
848 .TakePath();
849
850 EXPECT_EQ(path.GetComponentCount(), 5u);
851 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
852 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
853 }

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), and impeller::PathBuilder::LineTo().

## ◆ TEST() [270/501]

impeller::testing::TEST | ( | PathTest | ,
|  | SimplePath |
| ) |  |

Definition at line 718 of file path_unittests.cc.

718 {
719 PathBuilder builder;
720
721 auto path = builder.AddLine({0, 0}, {100, 100})
722 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
723 .AddConicCurve({100, 100}, {200, 200}, {300, 300}, 0.75f)
724 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
725 .TakePath();
726
727 EXPECT_EQ(path.GetComponentCount(), 8u);
728 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
729 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
730 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kConic), 1u);
731 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
732 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 4u);
733
734 auto it = path.begin();
735
736 {
737 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
738 const ContourComponent* contour = it.contour();
739 ASSERT_NE(contour, nullptr);
740 ++it;
741
742 Point p1(0, 0);
743 EXPECT_EQ(contour->destination, p1);
744 EXPECT_FALSE(contour->IsClosed());
745 }
746
747 {
748 ASSERT_EQ(it.type(), Path::ComponentType::kLinear);
749 const LinearPathComponent* linear = it.linear();
750 ASSERT_NE(linear, nullptr);
751 ++it;
752
753 Point p1(0, 0);
754 Point p2(100, 100);
755 EXPECT_EQ(linear->p1, p1);
756 EXPECT_EQ(linear->p2, p2);
757 }
758
759 {
760 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
761 const ContourComponent* contour = it.contour();
762 ASSERT_NE(contour, nullptr);
763 ++it;
764
765 Point p1(100, 100);
766 EXPECT_EQ(contour->destination, p1);
767 EXPECT_FALSE(contour->IsClosed());
768 }
769
770 {
771 ASSERT_EQ(it.type(), Path::ComponentType::kQuadratic);
772 const QuadraticPathComponent* quad = it.quadratic();
773 ASSERT_NE(quad, nullptr);
774 ++it;
775
776 Point p1(100, 100);
777 Point cp(200, 200);
778 Point p2(300, 300);
779 EXPECT_EQ(quad->p1, p1);
780 EXPECT_EQ(quad->cp, cp);
781 EXPECT_EQ(quad->p2, p2);
782 }
783
784 {
785 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
786 const ContourComponent* contour = it.contour();
787 ASSERT_NE(contour, nullptr);
788 ++it;
789
790 Point p1(100, 100);
791 EXPECT_EQ(contour->destination, p1);
792 EXPECT_FALSE(contour->IsClosed());
793 }
794
795 {
796 ASSERT_EQ(it.type(), Path::ComponentType::kConic);
797 const ConicPathComponent* conic = it.conic();
798 ASSERT_NE(conic, nullptr);
799 ++it;
800
801 Point p1(100, 100);
802 Point cp(200, 200);
803 Point p2(300, 300);
804 Point weight(0.75f, 0.75f);
805 EXPECT_EQ(conic->p1, p1);
806 EXPECT_EQ(conic->cp, cp);
807 EXPECT_EQ(conic->p2, p2);
808 EXPECT_EQ(conic->weight, weight);
809 }
810
811 {
812 ASSERT_EQ(it.type(), Path::ComponentType::kContour);
813 const ContourComponent* contour = it.contour();
814 ASSERT_NE(contour, nullptr);
815 ++it;
816
817 Point p1(300, 300);
818 EXPECT_EQ(contour->destination, p1);
819 EXPECT_FALSE(contour->IsClosed());
820 }
821
822 {
823 ASSERT_EQ(it.type(), Path::ComponentType::kCubic);
824 const CubicPathComponent* cubic = it.cubic();
825 ASSERT_NE(cubic, nullptr);
826 ++it;
827
828 Point p1(300, 300);
829 Point cp1(400, 400);
830 Point cp2(500, 500);
831 Point p2(600, 600);
832 EXPECT_EQ(cubic->p1, p1);
833 EXPECT_EQ(cubic->cp1, cp1);
834 EXPECT_EQ(cubic->cp2, cp2);
835 EXPECT_EQ(cubic->p2, p2);
836 }
837
838 EXPECT_EQ(it, path.end());
839 }

References impeller::PathBuilder::AddLine(), impeller::QuadraticPathComponent::cp, impeller::ConicPathComponent::cp, impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::ContourComponent::destination, impeller::ContourComponent::IsClosed(), impeller::Path::kConic, impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, impeller::LinearPathComponent::p1, impeller::QuadraticPathComponent::p1, impeller::ConicPathComponent::p1, impeller::CubicPathComponent::p1, impeller::LinearPathComponent::p2, impeller::QuadraticPathComponent::p2, impeller::ConicPathComponent::p2, impeller::CubicPathComponent::p2, and impeller::ConicPathComponent::weight.

## ◆ TEST() [271/501]

impeller::testing::TEST | ( | PathTest | ,
|  | StripTessellation |
| ) |  |

Definition at line 1003 of file path_unittests.cc.

1003 {
1004 Path path = PathBuilder{}
1005 .AddRoundRect(RoundRect::MakeRectRadius(
1006 Rect::MakeLTRB(0, 0, 100, 100), 10))
1007 .TakePath();
1008 auto [points, contours] = path.CountStorage(1.0);
1009
1010 std::vector<Point> point_storage(points);
1011 std::vector<uint16_t> index_storage(points + (contours - 1));
1012
1013 StripVertexWriter writer(point_storage.data(), index_storage.data());
1014 path.WritePolyline(1.0, writer);
1015
1016 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
1017 EXPECT_EQ(point_storage[0], Point(10, 0));
1018 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::StripVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), impeller::PathBuilder::TakePath(), and impeller::Path::WritePolyline().

## ◆ TEST() [272/501]

impeller::testing::TEST | ( | PathTest | ,
|  | StripTessellationMultiContour |
| ) |  |

Definition at line 1020 of file path_unittests.cc.

1020 {
1021 PathBuilder builder{};
1022 for (auto i = 0; i < 10; i++) {
1023 builder.AddRoundRect(
1024 RoundRect::MakeRectRadius(Rect::MakeLTRB(0 + i, 0 + i, 100, 100), 10));
1025 }
1026 auto path = builder.TakePath();
1027 auto [points, contours] = path.CountStorage(1.0);
1028
1029 std::vector<Point> point_storage(points);
1030 std::vector<uint16_t> index_storage(points + (contours - 1));
1031
1032 StripVertexWriter writer(point_storage.data(), index_storage.data());
1033 path.WritePolyline(1.0, writer);
1034
1035 EXPECT_LE(writer.GetIndexCount(), index_storage.size());
1036 EXPECT_EQ(point_storage[0], Point(10, 0));
1037 }

References impeller::PathBuilder::AddRoundRect(), impeller::Path::CountStorage(), impeller::StripVertexWriter::GetIndexCount(), impeller::TRect< Scalar >::MakeLTRB(), impeller::RoundRect::MakeRectRadius(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [273/501]

impeller::testing::TEST | ( | PathTest | ,
|  | StripTessellationUnclosedPath |
| ) |  |

Definition at line 960 of file path_unittests.cc.

960 {
961 // Create a rectangle that lacks an explicit close.
962 Path path = PathBuilder{}
963 .LineTo({100, 0})
964 .LineTo({100, 100})
965 .LineTo({0, 100})
966 .TakePath();
967
968 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100},
969 {0, 100}, {0, 0}, {0, 0}};
970 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 0xFFFF, 0};
971
972 auto [points, contours] = path.CountStorage(1.0);
973
974 std::vector<Point> point_storage(points);
975 std::vector<uint16_t> index_storage(points + (contours - 1));
976
977 StripVertexWriter writer(point_storage.data(), index_storage.data());
978 path.WritePolyline(1.0, writer);
979
980 EXPECT_LE(index_storage, expected_indices);
981 EXPECT_EQ(point_storage, expected);
982 }

References impeller::Path::CountStorage(), impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::Path::WritePolyline().

## ◆ TEST() [274/501]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanCreateFromDeviceProperties |
| ) |  |

Definition at line 76 of file pipeline_cache_data_vk_unittests.cc.

76 {
77 vk::PhysicalDeviceProperties props;
78 std::array<uint8_t, 16> uuid{
79 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
80 };
81 props.pipelineCacheUUID = uuid;
82 props.deviceID = 10;
83 props.vendorID = 11;
84 props.driverVersion = 12;
85 PipelineCacheHeaderVK header(props, 99);
86 EXPECT_EQ(uuid.size(), std::size(header.uuid));
87 EXPECT_EQ(props.deviceID, header.device_id);
88 EXPECT_EQ(props.vendorID, header.vendor_id);
89 EXPECT_EQ(props.driverVersion, header.driver_version);
90 for (size_t i = 0; i < uuid.size(); i++) {
91 EXPECT_EQ(header.uuid[i], uuid.at(i));
92 }
93 }

References impeller::PipelineCacheHeaderVK::device_id, impeller::PipelineCacheHeaderVK::driver_version, impeller::PipelineCacheHeaderVK::uuid, and impeller::PipelineCacheHeaderVK::vendor_id.

## ◆ TEST() [275/501]

impeller::testing::TEST | ( | PipelineCacheDataVKTest | ,
|  | CanTestHeaderCompatibility |
| ) |  |

Definition at line 16 of file pipeline_cache_data_vk_unittests.cc.

16 {
17 {
18 PipelineCacheHeaderVK a;
19 PipelineCacheHeaderVK b;
20 EXPECT_EQ(a.abi, sizeof(void*));
21 #ifdef FML_ARCH_CPU_64_BITS
22 EXPECT_EQ(a.abi, 8u);
23 #elif FML_ARCH_CPU_32_BITS
24 EXPECT_EQ(a.abi, 4u);
25 #endif
26 EXPECT_TRUE(a.IsCompatibleWith(b));
27 }
28 // Different data sizes don't matter.
29 {
30 PipelineCacheHeaderVK a;
31 PipelineCacheHeaderVK b;
32 a.data_size = b.data_size + 100u;
33 EXPECT_TRUE(a.IsCompatibleWith(b));
34 }
35 // Magic, Driver, vendor, ABI, and UUID matter.
36 {
37 PipelineCacheHeaderVK a;
38 PipelineCacheHeaderVK b;
39 b.magic = 100;
40 EXPECT_FALSE(a.IsCompatibleWith(b));
41 }
42 {
43 PipelineCacheHeaderVK a;
44 PipelineCacheHeaderVK b;
45 b.driver_version = 100;
46 EXPECT_FALSE(a.IsCompatibleWith(b));
47 }
48 {
49 PipelineCacheHeaderVK a;
50 PipelineCacheHeaderVK b;
51 b.vendor_id = 100;
52 EXPECT_FALSE(a.IsCompatibleWith(b));
53 }
54 {
55 PipelineCacheHeaderVK a;
56 PipelineCacheHeaderVK b;
57 b.device_id = 100;
58 EXPECT_FALSE(a.IsCompatibleWith(b));
59 }
60 {
61 PipelineCacheHeaderVK a;
62 PipelineCacheHeaderVK b;
63 b.abi = a.abi / 2u;
64 EXPECT_FALSE(a.IsCompatibleWith(b));
65 }
66 {
67 PipelineCacheHeaderVK a;
68 PipelineCacheHeaderVK b;
69 for (size_t i = 0; i < VK_UUID_SIZE; i++) {
70 b.uuid[i] = a.uuid[i] + 1;
71 }
72 EXPECT_FALSE(a.IsCompatibleWith(b));
73 }
74 }

References impeller::PipelineCacheHeaderVK::abi, impeller::saturated::b, impeller::PipelineCacheHeaderVK::data_size, impeller::PipelineCacheHeaderVK::IsCompatibleWith(), and impeller::PipelineCacheHeaderVK::uuid.

## ◆ TEST() [276/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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(), scale, and impeller::TRect< T >::Scale().

## ◆ TEST() [304/501]

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

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

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

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

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

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

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
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:332

References impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakePointBounds(), and RectNear().

## ◆ TEST() [311/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [330/501]

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

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(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [332/501]

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

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

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

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(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [336/501]

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

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

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

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

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

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

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

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

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

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

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(), scale, and impeller::TRect< T >::Scale().

## ◆ TEST() [347/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 }
impeller::kSqrt2
constexpr float kSqrt2
Definition: constants.h:47

References impeller::kEhCloseEnough, impeller::kSqrt2, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundRect::MakeRectRadii().

## ◆ TEST() [382/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 500 of file round_superellipse_unittests.cc.

500 {
501 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
502 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.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 RoundSuperellipse expanded = rse.Expand(-12.0);
510 // Largest sum of paired radii sizes are the bottom and right edges
511 // both of which sum to 12
512 // Rect was 30x30 reduced by 12 on all sides leaving only 6x6, so all
513 // radii are scaled by half to avoid overflowing the contracted rect
514
515 EXPECT_FALSE(expanded.IsEmpty());
516 EXPECT_FALSE(expanded.IsRect());
517 EXPECT_FALSE(expanded.IsOval());
518 EXPECT_TRUE(expanded.IsFinite());
519 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
520 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(22.0f, 22.0f, 28.0f, 28.0f));
521 EXPECT_EQ(expanded.GetRadii().top_left, Size(0.5f, 1.0f));
522 EXPECT_EQ(expanded.GetRadii().top_right, Size(1.5f, 2.0f));
523 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(2.5f, 3.0f));
524 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(3.5f, 4.0f));
525
526 // In this test, the MakeRectRadii constructor will make the same
527 // adjustment to the radii that the Expand method applied.
528 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
529 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
530 {
531 .top_left = Size(1.0f, 2.0f),
532 .top_right = Size(3.0f, 4.0f),
533 .bottom_left = Size(5.0f, 6.0f),
534 .bottom_right = Size(7.0f, 8.0f),
535 }));
536
537 // In this test, the arguments to the constructor supply the correctly
538 // adjusted radii (though there is no real way to tell other than
539 // the result is the same).
540 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
541 Rect::MakeXYWH(22.0f, 22.0f, 6.0f, 6.0f),
542 {
543 .top_left = Size(0.5f, 1.0f),
544 .top_right = Size(1.5f, 2.0f),
545 .bottom_left = Size(2.5f, 3.0f),
546 .bottom_right = Size(3.5f, 4.0f),
547 }));
548 }

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

## ◆ TEST() [404/501]

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

Definition at line 468 of file round_superellipse_unittests.cc.

468 {
469 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
470 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.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 RoundSuperellipse expanded = rse.Expand(-1.0, -1.5, -2.0, -2.5);
478
479 EXPECT_FALSE(expanded.IsEmpty());
480 EXPECT_FALSE(expanded.IsRect());
481 EXPECT_FALSE(expanded.IsOval());
482 EXPECT_TRUE(expanded.IsFinite());
483 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
484 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 11.5f, 38.0f, 37.5f));
485 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
486 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
487 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
488 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
489
490 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
491 Rect::MakeXYWH(11.0f, 11.5f, 27.0f, 26.0f),
492 {
493 .top_left = Size(1.0f, 2.0f),
494 .top_right = Size(3.0f, 4.0f),
495 .bottom_left = Size(5.0f, 6.0f),
496 .bottom_right = Size(7.0f, 8.0f),
497 }));
498 }

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

## ◆ TEST() [405/501]

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

Definition at line 404 of file round_superellipse_unittests.cc.

404 {
405 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
406 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.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 RoundSuperellipse expanded = rse.Expand(-2.0);
414
415 EXPECT_FALSE(expanded.IsEmpty());
416 EXPECT_FALSE(expanded.IsRect());
417 EXPECT_FALSE(expanded.IsOval());
418 EXPECT_TRUE(expanded.IsFinite());
419 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
420 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(12.0f, 12.0f, 38.0f, 38.0f));
421 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
422 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
423 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
424 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
425
426 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
427 Rect::MakeXYWH(12.0f, 12.0f, 26.0f, 26.0f),
428 {
429 .top_left = Size(1.0f, 2.0f),
430 .top_right = Size(3.0f, 4.0f),
431 .bottom_left = Size(5.0f, 6.0f),
432 .bottom_right = Size(7.0f, 8.0f),
433 }));
434 }

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

## ◆ TEST() [406/501]

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

Definition at line 436 of file round_superellipse_unittests.cc.

436 {
437 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
438 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.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 RoundSuperellipse expanded = rse.Expand(-1.0, -2.0);
446
447 EXPECT_FALSE(expanded.IsEmpty());
448 EXPECT_FALSE(expanded.IsRect());
449 EXPECT_FALSE(expanded.IsOval());
450 EXPECT_TRUE(expanded.IsFinite());
451 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
452 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(11.0f, 12.0f, 39.0f, 38.0f));
453 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
454 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
455 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
456 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
457
458 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
459 Rect::MakeXYWH(11.0f, 12.0f, 28.0f, 26.0f),
460 {
461 .top_left = Size(1.0f, 2.0f),
462 .top_right = Size(3.0f, 4.0f),
463 .bottom_left = Size(5.0f, 6.0f),
464 .bottom_right = Size(7.0f, 8.0f),
465 }));
466 }

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

## ◆ TEST() [407/501]

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

Definition at line 45 of file round_superellipse_unittests.cc.

45 {
46 RoundSuperellipse rse = RoundSuperellipse();
47
48 EXPECT_TRUE(rse.IsEmpty());
49 EXPECT_FALSE(rse.IsRect());
50 EXPECT_FALSE(rse.IsOval());
51 EXPECT_TRUE(rse.IsFinite());
52 EXPECT_TRUE(rse.GetBounds().IsEmpty());
53 EXPECT_EQ(rse.GetBounds(), Rect());
54 EXPECT_EQ(rse.GetRadii().top_left, Size());
55 EXPECT_EQ(rse.GetRadii().top_right, Size());
56 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
57 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
58 }

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

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

Definition at line 18 of file round_superellipse_unittests.cc.

18 {
19 RoundSuperellipse rse;
20
21 EXPECT_TRUE(rse.IsEmpty());
22 EXPECT_FALSE(rse.IsRect());
23 EXPECT_FALSE(rse.IsOval());
24 EXPECT_TRUE(rse.IsFinite());
25 EXPECT_TRUE(rse.GetBounds().IsEmpty());
26 EXPECT_EQ(rse.GetBounds(), Rect());
27 EXPECT_EQ(rse.GetBounds().GetLeft(), 0.0f);
28 EXPECT_EQ(rse.GetBounds().GetTop(), 0.0f);
29 EXPECT_EQ(rse.GetBounds().GetRight(), 0.0f);
30 EXPECT_EQ(rse.GetBounds().GetBottom(), 0.0f);
31 EXPECT_EQ(rse.GetRadii().top_left, Size());
32 EXPECT_EQ(rse.GetRadii().top_right, Size());
33 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
34 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
35 EXPECT_EQ(rse.GetRadii().top_left.width, 0.0f);
36 EXPECT_EQ(rse.GetRadii().top_left.height, 0.0f);
37 EXPECT_EQ(rse.GetRadii().top_right.width, 0.0f);
38 EXPECT_EQ(rse.GetRadii().top_right.height, 0.0f);
39 EXPECT_EQ(rse.GetRadii().bottom_left.width, 0.0f);
40 EXPECT_EQ(rse.GetRadii().bottom_left.height, 0.0f);
41 EXPECT_EQ(rse.GetRadii().bottom_right.width, 0.0f);
42 EXPECT_EQ(rse.GetRadii().bottom_right.height, 0.0f);
43 }

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

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

Definition at line 108 of file round_superellipse_unittests.cc.

108 {
109 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
110 Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f), 10.0f, 10.0f);
111
112 EXPECT_TRUE(rse.IsEmpty());
113 EXPECT_FALSE(rse.IsRect());
114 EXPECT_FALSE(rse.IsOval());
115 EXPECT_TRUE(rse.IsFinite());
116 EXPECT_TRUE(rse.GetBounds().IsEmpty());
117 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
118 EXPECT_EQ(rse.GetRadii().top_left, Size());
119 EXPECT_EQ(rse.GetRadii().top_right, Size());
120 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
121 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
122 }

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

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

Definition at line 60 of file round_superellipse_unittests.cc.

60 {
61 RoundSuperellipse rse =
62 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
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::MakeLTRB(20.0f, 20.0f, 20.0f, 20.0f));
70 EXPECT_EQ(rse.GetRadii().top_left, Size());
71 EXPECT_EQ(rse.GetRadii().top_right, Size());
72 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
73 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
74 }

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

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

Definition at line 372 of file round_superellipse_unittests.cc.

372 {
373 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
374 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.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 RoundSuperellipse expanded = rse.Expand(5.0, 6.0, 7.0, 8.0);
382
383 EXPECT_FALSE(expanded.IsEmpty());
384 EXPECT_FALSE(expanded.IsRect());
385 EXPECT_FALSE(expanded.IsOval());
386 EXPECT_TRUE(expanded.IsFinite());
387 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
388 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 47.0f, 48.0f));
389 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
390 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
391 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
392 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
393
394 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
395 Rect::MakeXYWH(5.0f, 4.0f, 42.0f, 44.0f),
396 {
397 .top_left = Size(1.0f, 2.0f),
398 .top_right = Size(3.0f, 4.0f),
399 .bottom_left = Size(5.0f, 6.0f),
400 .bottom_right = Size(7.0f, 8.0f),
401 }));
402 }

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

## ◆ TEST() [412/501]

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

Definition at line 308 of file round_superellipse_unittests.cc.

308 {
309 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
310 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
311 {
312 .top_left = Size(1.0f, 2.0f),
313 .top_right = Size(3.0f, 4.0f),
314 .bottom_left = Size(5.0f, 6.0f),
315 .bottom_right = Size(7.0f, 8.0f),
316 });
317 RoundSuperellipse expanded = rse.Expand(5.0);
318
319 EXPECT_FALSE(expanded.IsEmpty());
320 EXPECT_FALSE(expanded.IsRect());
321 EXPECT_FALSE(expanded.IsOval());
322 EXPECT_TRUE(expanded.IsFinite());
323 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
324 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 5.0f, 45.0f, 45.0f));
325 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
326 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
327 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
328 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
329
330 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
331 Rect::MakeXYWH(5.0f, 5.0f, 40.0f, 40.0f),
332 {
333 .top_left = Size(1.0f, 2.0f),
334 .top_right = Size(3.0f, 4.0f),
335 .bottom_left = Size(5.0f, 6.0f),
336 .bottom_right = Size(7.0f, 8.0f),
337 }));
338 }

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

## ◆ TEST() [413/501]

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

Definition at line 340 of file round_superellipse_unittests.cc.

340 {
341 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
342 Rect::MakeXYWH(10.0f, 10.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 RoundSuperellipse expanded = rse.Expand(5.0, 6.0);
350
351 EXPECT_FALSE(expanded.IsEmpty());
352 EXPECT_FALSE(expanded.IsRect());
353 EXPECT_FALSE(expanded.IsOval());
354 EXPECT_TRUE(expanded.IsFinite());
355 EXPECT_FALSE(expanded.GetBounds().IsEmpty());
356 EXPECT_EQ(expanded.GetBounds(), Rect::MakeLTRB(5.0f, 4.0f, 45.0f, 46.0f));
357 EXPECT_EQ(expanded.GetRadii().top_left, Size(1.0f, 2.0f));
358 EXPECT_EQ(expanded.GetRadii().top_right, Size(3.0f, 4.0f));
359 EXPECT_EQ(expanded.GetRadii().bottom_left, Size(5.0f, 6.0f));
360 EXPECT_EQ(expanded.GetRadii().bottom_right, Size(7.0f, 8.0f));
361
362 EXPECT_EQ(expanded, RoundSuperellipse::MakeRectRadii(
363 Rect::MakeXYWH(5.0f, 4.0f, 40.0f, 42.0f),
364 {
365 .top_left = Size(1.0f, 2.0f),
366 .top_right = Size(3.0f, 4.0f),
367 .bottom_left = Size(5.0f, 6.0f),
368 .bottom_right = Size(7.0f, 8.0f),
369 }));
370 }

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

## ◆ TEST() [414/501]

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

Definition at line 140 of file round_superellipse_unittests.cc.

140 {
141 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
142 Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f), 10.0f, 10.0f);
143
144 EXPECT_FALSE(rse.IsEmpty());
145 EXPECT_FALSE(rse.IsRect());
146 EXPECT_TRUE(rse.IsOval());
147 EXPECT_TRUE(rse.IsFinite());
148 EXPECT_FALSE(rse.GetBounds().IsEmpty());
149 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
150 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
151 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
152 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
153 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
154 }

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

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

Definition at line 92 of file round_superellipse_unittests.cc.

92 {
93 RoundSuperellipse rse =
94 RoundSuperellipse::MakeRect(Rect::MakeLTRB(20.0f, 20.0f, 10.0f, 10.0f));
95
96 EXPECT_FALSE(rse.IsEmpty());
97 EXPECT_TRUE(rse.IsRect());
98 EXPECT_FALSE(rse.IsOval());
99 EXPECT_TRUE(rse.IsFinite());
100 EXPECT_FALSE(rse.GetBounds().IsEmpty());
101 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
102 EXPECT_EQ(rse.GetRadii().top_left, Size());
103 EXPECT_EQ(rse.GetRadii().top_right, Size());
104 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
105 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
106 }

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

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

Definition at line 550 of file round_superellipse_unittests.cc.

550 {
551 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
552 // Rounded superellipses of bounds with no corners contains corners just
553 // barely.
554 auto no_corners = RoundSuperellipse::MakeRectRadii(
555 bounds, RoundingRadii::MakeRadii({0.0f, 0.0f}));
556
557 EXPECT_TRUE(no_corners.Contains({-50, -50}));
558 // Rectangles have half-in, half-out containment so we need
559 // to be careful about testing containment of right/bottom corners.
560 EXPECT_TRUE(no_corners.Contains({-50, 49.99}));
561 EXPECT_TRUE(no_corners.Contains({49.99, -50}));
562 EXPECT_TRUE(no_corners.Contains({49.99, 49.99}));
563 EXPECT_FALSE(no_corners.Contains({-50.01, -50}));
564 EXPECT_FALSE(no_corners.Contains({-50, -50.01}));
565 EXPECT_FALSE(no_corners.Contains({-50.01, 50}));
566 EXPECT_FALSE(no_corners.Contains({-50, 50.01}));
567 EXPECT_FALSE(no_corners.Contains({50.01, -50}));
568 EXPECT_FALSE(no_corners.Contains({50, -50.01}));
569 EXPECT_FALSE(no_corners.Contains({50.01, 50}));
570 EXPECT_FALSE(no_corners.Contains({50, 50.01}));
571 }

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

## ◆ TEST() [417/501]

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

Definition at line 124 of file round_superellipse_unittests.cc.

124 {
125 RoundSuperellipse rse =
126 RoundSuperellipse::MakeOval(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
127
128 EXPECT_FALSE(rse.IsEmpty());
129 EXPECT_FALSE(rse.IsRect());
130 EXPECT_TRUE(rse.IsOval());
131 EXPECT_TRUE(rse.IsFinite());
132 EXPECT_FALSE(rse.GetBounds().IsEmpty());
133 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
134 EXPECT_EQ(rse.GetRadii().top_left, Size(5.0f, 5.0f));
135 EXPECT_EQ(rse.GetRadii().top_right, Size(5.0f, 5.0f));
136 EXPECT_EQ(rse.GetRadii().bottom_left, Size(5.0f, 5.0f));
137 EXPECT_EQ(rse.GetRadii().bottom_right, Size(5.0f, 5.0f));
138 }

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

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

Definition at line 76 of file round_superellipse_unittests.cc.

76 {
77 RoundSuperellipse rse =
78 RoundSuperellipse::MakeRect(Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
79
80 EXPECT_FALSE(rse.IsEmpty());
81 EXPECT_TRUE(rse.IsRect());
82 EXPECT_FALSE(rse.IsOval());
83 EXPECT_TRUE(rse.IsFinite());
84 EXPECT_FALSE(rse.GetBounds().IsEmpty());
85 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
86 EXPECT_EQ(rse.GetRadii().top_left, Size());
87 EXPECT_EQ(rse.GetRadii().top_right, Size());
88 EXPECT_EQ(rse.GetRadii().bottom_left, Size());
89 EXPECT_EQ(rse.GetRadii().bottom_right, Size());
90 }

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

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

Definition at line 204 of file round_superellipse_unittests.cc.

204 {
205 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
206 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f),
207 {
208 .top_left = Size(1.0, 1.5),
209 .top_right = Size(2.0, 2.5f),
210 .bottom_left = Size(3.0, 3.5f),
211 .bottom_right = Size(4.0, 4.5f),
212 });
213
214 EXPECT_FALSE(rse.IsEmpty());
215 EXPECT_FALSE(rse.IsRect());
216 EXPECT_FALSE(rse.IsOval());
217 EXPECT_TRUE(rse.IsFinite());
218 EXPECT_FALSE(rse.GetBounds().IsEmpty());
219 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
220 EXPECT_EQ(rse.GetRadii().top_left, Size(1.0f, 1.5f));
221 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.5f));
222 EXPECT_EQ(rse.GetRadii().bottom_left, Size(3.0f, 3.5f));
223 EXPECT_EQ(rse.GetRadii().bottom_right, Size(4.0f, 4.5f));
224 }

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

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

Definition at line 251 of file round_superellipse_unittests.cc.

251 {
252 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
253 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 6.0f),
254 {
255 .top_left = Size(1.0f, 2.0f),
256 .top_right = Size(3.0f, 4.0f),
257 .bottom_left = Size(5.0f, 6.0f),
258 .bottom_right = Size(7.0f, 8.0f),
259 });
260 // Largest sum of paired radii heights is the right edge which sums to 12
261 // Rect is only 6 tall so all radii are scaled by half
262 // Rect is 30 wide so no scaling should happen due to radii widths
263
264 EXPECT_FALSE(rse.IsEmpty());
265 EXPECT_FALSE(rse.IsRect());
266 EXPECT_FALSE(rse.IsOval());
267 EXPECT_TRUE(rse.IsFinite());
268 EXPECT_FALSE(rse.GetBounds().IsEmpty());
269 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 40.0f, 16.0f));
270 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
271 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
272 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
273 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
274 }

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

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

Definition at line 226 of file round_superellipse_unittests.cc.

226 {
227 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
228 Rect::MakeXYWH(10.0f, 10.0f, 6.0f, 30.0f),
229 {
230 .top_left = Size(1.0f, 2.0f),
231 .top_right = Size(3.0f, 4.0f),
232 .bottom_left = Size(5.0f, 6.0f),
233 .bottom_right = Size(7.0f, 8.0f),
234 });
235 // Largest sum of paired radii widths is the bottom edge which sums to 12
236 // Rect is only 6 wide so all radii are scaled by half
237 // Rect is 30 tall so no scaling should happen due to radii heights
238
239 EXPECT_FALSE(rse.IsEmpty());
240 EXPECT_FALSE(rse.IsRect());
241 EXPECT_FALSE(rse.IsOval());
242 EXPECT_TRUE(rse.IsFinite());
243 EXPECT_FALSE(rse.GetBounds().IsEmpty());
244 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 16.0f, 40.0f));
245 EXPECT_EQ(rse.GetRadii().top_left, Size(0.5f, 1.0f));
246 EXPECT_EQ(rse.GetRadii().top_right, Size(1.5f, 2.0f));
247 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.5f, 3.0f));
248 EXPECT_EQ(rse.GetRadii().bottom_right, Size(3.5f, 4.0f));
249 }

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

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

Definition at line 156 of file round_superellipse_unittests.cc.

156 {
157 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadius(
158 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f);
159
160 EXPECT_FALSE(rse.IsEmpty());
161 EXPECT_FALSE(rse.IsRect());
162 EXPECT_FALSE(rse.IsOval());
163 EXPECT_TRUE(rse.IsFinite());
164 EXPECT_FALSE(rse.GetBounds().IsEmpty());
165 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
166 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 2.0f));
167 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 2.0f));
168 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 2.0f));
169 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 2.0f));
170 }

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

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

Definition at line 188 of file round_superellipse_unittests.cc.

188 {
189 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
190 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), Size(2.0f, 3.0f));
191
192 EXPECT_FALSE(rse.IsEmpty());
193 EXPECT_FALSE(rse.IsRect());
194 EXPECT_FALSE(rse.IsOval());
195 EXPECT_TRUE(rse.IsFinite());
196 EXPECT_FALSE(rse.GetBounds().IsEmpty());
197 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
198 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
199 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
200 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
201 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
202 }

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

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

Definition at line 172 of file round_superellipse_unittests.cc.

172 {
173 RoundSuperellipse rse = RoundSuperellipse::MakeRectXY(
174 Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f), 2.0f, 3.0f);
175
176 EXPECT_FALSE(rse.IsEmpty());
177 EXPECT_FALSE(rse.IsRect());
178 EXPECT_FALSE(rse.IsOval());
179 EXPECT_TRUE(rse.IsFinite());
180 EXPECT_FALSE(rse.GetBounds().IsEmpty());
181 EXPECT_EQ(rse.GetBounds(), Rect::MakeLTRB(10.0f, 10.0f, 20.0f, 20.0f));
182 EXPECT_EQ(rse.GetRadii().top_left, Size(2.0f, 3.0f));
183 EXPECT_EQ(rse.GetRadii().top_right, Size(2.0f, 3.0f));
184 EXPECT_EQ(rse.GetRadii().bottom_left, Size(2.0f, 3.0f));
185 EXPECT_EQ(rse.GetRadii().bottom_right, Size(2.0f, 3.0f));
186 }

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

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

Definition at line 276 of file round_superellipse_unittests.cc.

276 {
277 RoundSuperellipse rse = RoundSuperellipse::MakeRectRadii(
278 Rect::MakeXYWH(10.0f, 10.0f, 30.0f, 30.0f),
279 {
280 .top_left = Size(1.0f, 2.0f),
281 .top_right = Size(3.0f, 4.0f),
282 .bottom_left = Size(5.0f, 6.0f),
283 .bottom_right = Size(7.0f, 8.0f),
284 });
285 RoundSuperellipse shifted = rse.Shift(5.0, 6.0);
286
287 EXPECT_FALSE(shifted.IsEmpty());
288 EXPECT_FALSE(shifted.IsRect());
289 EXPECT_FALSE(shifted.IsOval());
290 EXPECT_TRUE(shifted.IsFinite());
291 EXPECT_FALSE(shifted.GetBounds().IsEmpty());
292 EXPECT_EQ(shifted.GetBounds(), Rect::MakeLTRB(15.0f, 16.0f, 45.0f, 46.0f));
293 EXPECT_EQ(shifted.GetRadii().top_left, Size(1.0f, 2.0f));
294 EXPECT_EQ(shifted.GetRadii().top_right, Size(3.0f, 4.0f));
295 EXPECT_EQ(shifted.GetRadii().bottom_left, Size(5.0f, 6.0f));
296 EXPECT_EQ(shifted.GetRadii().bottom_right, Size(7.0f, 8.0f));
297
298 EXPECT_EQ(shifted, RoundSuperellipse::MakeRectRadii(
299 Rect::MakeXYWH(15.0f, 16.0f, 30.0f, 30.0f),
300 {
301 .top_left = Size(1.0f, 2.0f),
302 .top_right = Size(3.0f, 4.0f),
303 .bottom_left = Size(5.0f, 6.0f),
304 .bottom_right = Size(7.0f, 8.0f),
305 }));
306 }

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

## ◆ TEST() [426/501]

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

Definition at line 658 of file round_superellipse_unittests.cc.

658 {
659 // This shape has large radii on one diagnal and tiny radii on the other,
660 // resulting in a almond-like shape placed diagnally (NW to SE).
661 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
662 auto rr = RoundSuperellipse::MakeRectRadii(
663 bounds, {
664 .top_left = Size(1.0, 1.0),
665 .top_right = Size(99.0, 99.0),
666 .bottom_left = Size(99.0, 99.0),
667 .bottom_right = Size(1.0, 1.0),
668 });
669
670 EXPECT_TRUE(rr.Contains(Point{0, 0}));
671 EXPECT_FALSE(rr.Contains(Point{-49.999, -49.999}));
672 EXPECT_FALSE(rr.Contains(Point{-49.999, 49.999}));
673 EXPECT_FALSE(rr.Contains(Point{49.999, 49.999}));
674 EXPECT_FALSE(rr.Contains(Point{49.999, -49.999}));
675
676 // The pointy ends at the NE and SW corners
677 CHECK_POINT_WITH_OFFSET(rr, Point(-49.70, -49.70), Point(-0.02, -0.02));
678 CHECK_POINT_WITH_OFFSET(rr, Point(49.70, 49.70), Point(0.02, 0.02));
679
680 // Checks two points symmetrical to the origin.
681 #define CHECK_DIAGNAL_POINTS(p) \
682 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, -0.02)); \
683 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, 0.02));
684
685 // A few other points along the edge
686 CHECK_DIAGNAL_POINTS(Point(-40.0, -49.59));
687 CHECK_DIAGNAL_POINTS(Point(-20.0, -45.64));
688 CHECK_DIAGNAL_POINTS(Point(0.0, -37.01));
689 CHECK_DIAGNAL_POINTS(Point(20.0, -21.96));
690 CHECK_DIAGNAL_POINTS(Point(21.05, -20.92));
691 CHECK_DIAGNAL_POINTS(Point(40.0, 5.68));
692 #undef CHECK_POINT_AND_MIRRORS
693 }
CHECK_DIAGNAL_POINTS
#define CHECK_DIAGNAL_POINTS(p)
CHECK_POINT_WITH_OFFSET
#define CHECK_POINT_WITH_OFFSET(rr, p, outward_offset)
Definition: round_superellipse_unittests.cc:11

References CHECK_DIAGNAL_POINTS, CHECK_POINT_WITH_OFFSET, impeller::TRect< Scalar >::MakeLTRB(), and impeller::RoundSuperellipse::MakeRectRadii().

## ◆ TEST() [427/501]

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

Definition at line 573 of file round_superellipse_unittests.cc.

573 {
574 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
575 // Rounded superellipses of bounds with even the tiniest corners does not
576 // contain corners.
577 auto tiny_corners = RoundSuperellipse::MakeRectRadii(
578 bounds, RoundingRadii::MakeRadii({0.01f, 0.01f}));
579
580 EXPECT_FALSE(tiny_corners.Contains({-50, -50}));
581 EXPECT_FALSE(tiny_corners.Contains({-50, 50}));
582 EXPECT_FALSE(tiny_corners.Contains({50, -50}));
583 EXPECT_FALSE(tiny_corners.Contains({50, 50}));
584 }

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

## ◆ TEST() [428/501]

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

Definition at line 607 of file round_superellipse_unittests.cc.

607 {
608 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
609 auto rr = RoundSuperellipse::MakeRectRadii(
610 bounds, RoundingRadii::MakeRadii({5.0f, 10.0f}));
611
612 #define CHECK_POINT_AND_MIRRORS(p) \
613 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
614 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
615 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
616 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
617
618 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
619 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.911)); // Top curve start
620 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.75)); // Top joint
621 CHECK_POINT_AND_MIRRORS(Point(48.51, 47.07)); // Circular arc mid
622 CHECK_POINT_AND_MIRRORS(Point(49.87, 41.44)); // Right joint
623 CHECK_POINT_AND_MIRRORS(Point(49.95, 38.49)); // Right curve start
624 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
625 #undef CHECK_POINT_AND_MIRRORS
626 }
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() [429/501]

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

Definition at line 628 of file round_superellipse_unittests.cc.

628 {
629 // The bounds is not centered at the origin and has unequal height and width.
630 Rect bounds = Rect::MakeLTRB(0.0f, 0.0f, 50.0f, 100.0f);
631 auto rr = RoundSuperellipse::MakeRectRadii(
632 bounds, RoundingRadii::MakeRadii({23.0f, 30.0f}));
633
634 Point center = bounds.GetCenter();
635 #define CHECK_POINT_AND_MIRRORS(p) \
636 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, 1) + center, \
637 Point(0.02, 0.02)); \
638 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(1, -1) + center, \
639 Point(0.02, -0.02)); \
640 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, 1) + center, \
641 Point(-0.02, 0.02)); \
642 CHECK_POINT_WITH_OFFSET(rr, (p - center) * Point(-1, -1) + center, \
643 Point(-0.02, -0.02));
644
645 CHECK_POINT_AND_MIRRORS(Point(24.99, 99.99)); // Bottom mid edge
646 CHECK_POINT_AND_MIRRORS(Point(29.99, 99.64));
647 CHECK_POINT_AND_MIRRORS(Point(34.99, 98.06));
648 CHECK_POINT_AND_MIRRORS(Point(39.99, 94.73));
649 CHECK_POINT_AND_MIRRORS(Point(44.13, 89.99));
650 CHECK_POINT_AND_MIRRORS(Point(48.46, 79.99));
651 CHECK_POINT_AND_MIRRORS(Point(49.70, 69.99));
652 CHECK_POINT_AND_MIRRORS(Point(49.97, 59.99));
653 CHECK_POINT_AND_MIRRORS(Point(49.99, 49.99)); // Right mid edge
654
655 #undef CHECK_POINT_AND_MIRRORS
656 }

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

## ◆ TEST() [430/501]

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

Definition at line 586 of file round_superellipse_unittests.cc.

586 {
587 Rect bounds = Rect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f);
588 auto rr = RoundSuperellipse::MakeRectRadii(
589 bounds, RoundingRadii::MakeRadii({5.0f, 5.0f}));
590
591 #define CHECK_POINT_AND_MIRRORS(p) \
592 CHECK_POINT_WITH_OFFSET(rr, (p), Point(0.02, 0.02)); \
593 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(1, -1), Point(0.02, -0.02)); \
594 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, 1), Point(-0.02, 0.02)); \
595 CHECK_POINT_WITH_OFFSET(rr, (p) * Point(-1, -1), Point(-0.02, -0.02));
596
597 CHECK_POINT_AND_MIRRORS(Point(0, 49.995)); // Top
598 CHECK_POINT_AND_MIRRORS(Point(44.245, 49.95)); // Top curve start
599 CHECK_POINT_AND_MIRRORS(Point(45.72, 49.87)); // Top joint
600 CHECK_POINT_AND_MIRRORS(Point(48.53, 48.53)); // Circular arc mid
601 CHECK_POINT_AND_MIRRORS(Point(49.87, 45.72)); // Right joint
602 CHECK_POINT_AND_MIRRORS(Point(49.95, 44.245)); // Right curve start
603 CHECK_POINT_AND_MIRRORS(Point(49.995, 0)); // Right
604 #undef CHECK_POINT_AND_MIRRORS
605 }

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

## ◆ TEST() [431/501]

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(), scale, and x.

## ◆ TEST() [432/501]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | ToColor |
| ) |  |

Definition at line 48 of file skia_conversions_unittests.cc.

48 {
49 // Create a color with alpha, red, green, and blue values that are all
50 // trivially divisible by 255 so that we can test the conversion results in
51 // correct scalar values.
52 // AARRGGBB
53 const flutter::DlColor color = flutter::DlColor(0x8040C020);
54 auto converted_color = skia_conversions::ToColor(color);
55
56 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
57 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
58 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
59 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
60 }
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:13

References impeller::ScalarNearlyEqual(), and impeller::skia_conversions::ToColor().

## ◆ TEST() [479/501]

impeller::testing::TEST | ( | SkiaConversionTest | ,
|  | ToSamplerDescriptor |
| ) |  |

Definition at line 19 of file skia_conversions_unittests.cc.

19 {
20 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
21 flutter::DlImageSampling::kNearestNeighbor)
22 .min_filter,
23 impeller::MinMagFilter::kNearest);
24 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
25 flutter::DlImageSampling::kNearestNeighbor)
26 .mip_filter,
27 impeller::MipFilter::kBase);
28
29 EXPECT_EQ(
30 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
31 .min_filter,
32 impeller::MinMagFilter::kLinear);
33 EXPECT_EQ(
34 skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
35 .mip_filter,
36 impeller::MipFilter::kBase);
37
38 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
39 flutter::DlImageSampling::kMipmapLinear)
40 .min_filter,
41 impeller::MinMagFilter::kLinear);
42 EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
43 flutter::DlImageSampling::kMipmapLinear)
44 .mip_filter,
45 impeller::MipFilter::kLinear);
46 }
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:123
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() [480/501]

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

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

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

Definition at line 515 of file tessellator_unittests.cc.

515 {
516 auto tessellator = std::make_shared<Tessellator>();
517 PathBuilder builder;
518 builder.AddLine({0, 0}, {100, 100});
519 auto path = builder.TakePath();
520
521 auto polyline = tessellator->CreateTempPolyline(path, 0.1);
522 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(path, 0.1),
523 "point_buffer_");
524 }

References impeller::PathBuilder::AddLine(), polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [483/501]

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

Definition at line 139 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [484/501]

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

Definition at line 499 of file tessellator_unittests.cc.

499 {
500 // This path is not technically empty (it has a size in one dimension),
501 // but is otherwise completely flat.
502 PathBuilder builder;
503 builder.MoveTo({0, 0});
504 builder.MoveTo({10, 10}, /*relative=*/true);
505
506 std::vector<Point> points;
507 std::vector<uint16_t> indices;
508 Tessellator::TessellateConvexInternal(builder.TakePath(), points, indices,
509 3.0);
510
511 EXPECT_TRUE(points.empty());
512 }

References impeller::PathBuilder::MoveTo(), impeller::PathBuilder::TakePath(), and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [485/501]

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

Definition at line 175 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [486/501]

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

Definition at line 364 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [487/501]

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

Definition at line 425 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [488/501]

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

Definition at line 291 of file tessellator_unittests.cc.

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

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

Definition at line 219 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [490/501]

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

Definition at line 84 of file tessellator_unittests.cc.

84 {
85 {
86 std::vector<Point> points;
87 std::vector<uint16_t> indices;
88 // Sanity check simple rectangle.
89 Tessellator::TessellateConvexInternal(
90 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 10, 10)).TakePath(), points,
91 indices, 1.0);
92
93 // Note: the origin point is repeated but not referenced in the indices
94 // below
95 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
96 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
97 EXPECT_EQ(points, expected);
98 EXPECT_EQ(indices, expected_indices);
99 }
100
101 {
102 std::vector<Point> points;
103 std::vector<uint16_t> indices;
104 Tessellator::TessellateConvexInternal(
105 PathBuilder{}
106 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
107 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
108 .TakePath(),
109 points, indices, 1.0);
110
111 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
112 {0, 0}, {20, 20}, {30, 20}, {30, 30},
113 {20, 30}, {20, 20}};
114 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
115 EXPECT_EQ(points, expected);
116 EXPECT_EQ(indices, expected_indices);
117 }
118 }

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

## ◆ TEST() [491/501]

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

Definition at line 121 of file tessellator_unittests.cc.

121 {
122 std::vector<Point> points;
123 std::vector<uint16_t> indices;
124
125 // Create a rectangle that lacks an explicit close.
126 Path path = PathBuilder{}
127 .LineTo({100, 0})
128 .LineTo({100, 100})
129 .LineTo({0, 100})
130 .TakePath();
131 Tessellator::TessellateConvexInternal(path, points, indices, 1.0);
132
133 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100}, {0, 100}};
134 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
135 EXPECT_EQ(points, expected);
136 EXPECT_EQ(indices, expected_indices);
137 }

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

## ◆ TEST() [492/501]

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

Definition at line 17 of file tessellator_unittests.cc.

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

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

## ◆ TEST() [493/501]

impeller::testing::TEST | ( | TextureMTL | ,
|  | CreateFromDrawable |
| ) |  |

Definition at line 21 of file texture_mtl_unittests.mm.

21 {
22 auto device = MTLCreateSystemDefaultDevice();
23 auto layer = [[CAMetalLayer alloc] init];
24 layer.device = device;
25 layer.drawableSize = CGSize{100, 100};
26 layer.pixelFormat = ToMTLPixelFormat(PixelFormat::kB8G8R8A8UNormInt);
27
28 TextureDescriptor desc;
29 desc.size = {100, 100};
30 desc.format = PixelFormat::kB8G8R8A8UNormInt;
31 auto drawable_future = GetDrawableDeferred(layer);
32 auto drawable_texture =
33 CreateTextureFromDrawableFuture(desc, drawable_future);
34
35 ASSERT_TRUE(drawable_texture->IsValid());
36 EXPECT_TRUE(drawable_texture->IsDrawable());
37
38 // Spawn a thread and acquire the drawable in the thread.
39 auto thread = std::thread([&drawable_texture]() {
40 // Force the drawable to be acquired.
41 drawable_texture->GetMTLTexture();
42 });
43 thread.join();
44 // Block until drawable is acquired.
45 EXPECT_TRUE(drawable_future.get() != nil);
46 // Drawable is cached.
47 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
48 // Once more for good measure.
49 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
50 }
impeller::CreateTextureFromDrawableFuture
std::shared_ptr< TextureMTL > CreateTextureFromDrawableFuture(TextureDescriptor desc, const std::shared_future< id< CAMetalDrawable >> &drawble_future)
Create a TextureMTL from a deferred drawable.
Definition: lazy_drawable_holder.mm:41
impeller::ToMTLPixelFormat
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
Definition: formats_mtl.h:76
impeller::GetDrawableDeferred
std::shared_future< id< CAMetalDrawable > > GetDrawableDeferred(CAMetalLayer *layer)
Create a deferred drawable from a CAMetalLayer.
Definition: lazy_drawable_holder.mm:23

References impeller::CreateTextureFromDrawableFuture(), impeller::TextureDescriptor::format, impeller::GetDrawableDeferred(), impeller::kB8G8R8A8UNormInt, impeller::TextureDescriptor::size, and impeller::ToMTLPixelFormat().

## ◆ TEST() [494/501]

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

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

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

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

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

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

impeller::testing::TEST | ( | TypographerTest | ,
|  | RectanglePackerFillsRows |
| ) |  |

Definition at line 405 of file typographer_unittests.cc.

405 {
406 auto skyline = RectanglePacker::Factory(257, 256);
407
408 // Fill up the first row.
409 IPoint16 loc;
410 for (auto i = 0u; i < 16; i++) {
411 skyline->AddRect(16, 16, &loc);
412 }
413 // Last rectangle still in first row.
414 EXPECT_EQ(loc.x(), 256 - 16);
415 EXPECT_EQ(loc.y(), 0);
416
417 // Fill up second row.
418 for (auto i = 0u; i < 16; i++) {
419 skyline->AddRect(16, 16, &loc);
420 }
421
422 EXPECT_EQ(loc.x(), 256 - 16);
423 EXPECT_EQ(loc.y(), 16);
424 }

References impeller::RectanglePacker::Factory(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST() [501/501]

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

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

## ◆ TEST_P() [1/525]

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

Definition at line 906 of file aiks_dl_blend_unittests.cc.

906 {
907 DisplayListBuilder builder;
908
909 builder.DrawPaint(DlPaint(DlColor::kWhite()));
910
911 DlPaint save_paint;
912 save_paint.setOpacity(0.3);
913 save_paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kTransparent(),
914 DlBlendMode::kSaturation));
915 builder.SaveLayer(std::nullopt, &save_paint);
916 builder.DrawRect(DlRect::MakeXYWH(100, 100, 300, 300),
917 DlPaint(DlColor::kMaroon()));
918 builder.DrawRect(DlRect::MakeXYWH(200, 200, 300, 300),
919 DlPaint(DlColor::kBlue()));
920 builder.Restore();
921
922 // Should be solid red as the destructive color filter floods the clip.
923 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
924 }

## ◆ TEST_P() [2/525]

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

Definition at line 835 of file aiks_dl_path_unittests.cc.

835 {
836 DisplayListBuilder builder;
837 builder.Scale(GetContentScale().x, GetContentScale().y);
838
839 DlPaint paint;
840 paint.setColor(DlColor::kRed());
841
842 std::vector<DlColor> colors = {DlColor::RGBA(1.0, 0.0, 0.0, 1.0),
843 DlColor::RGBA(0.0, 0.0, 0.0, 1.0)};
844 std::vector<Scalar> stops = {0.0, 1.0};
845
846 paint.setColorSource(
847 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
848 stops.data(), DlTileMode::kMirror));
849 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
850
851 DlPathBuilder path_builder;
852 path_builder.AddArc(DlRect::MakeXYWH(10, 10, 100, 100), //
853 DlDegrees(0), DlDegrees(0));
854 builder.DrawPath(DlPath(path_builder), paint);
855
856 // Check that this empty picture can be created without crashing.
857 builder.Build();
858 }

References x.

## ◆ TEST_P() [3/525]

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

Definition at line 174 of file canvas_unittests.cc.

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

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

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

Definition at line 214 of file canvas_unittests.cc.

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

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

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

Definition at line 139 of file canvas_unittests.cc.

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

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

Definition at line 251 of file canvas_unittests.cc.

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

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

## ◆ TEST_P() [7/525]

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

Definition at line 1613 of file aiks_dl_basic_unittests.cc.

1613 {
1614 DisplayListBuilder builder;
1615
1616 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
1617 builder.Save();
1618 {
1619 builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
1620
1621 builder.Save();
1622 {
1623 builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
1624 builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
1625 builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
1626 builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
1627 builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
1628 }
1629 builder.Restore();
1630
1631 auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
1632 builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
1633 }
1634 builder.Restore();
1635 builder.DrawCircle(DlPoint(100, 100), 100,
1636 DlPaint().setColor(DlColor::kAqua()));
1637
1638 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1639 }

## ◆ TEST_P() [8/525]

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

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

Definition at line 431 of file aiks_dl_blend_unittests.cc.

431 {
432 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
433 PixelFormat::kB10G10R10A10XR);
434 auto texture = CreateTextureForFixture("airplane.jpg",
435 /*enable_mipmapping=*/true);
436
437 DisplayListBuilder builder;
438 builder.Scale(GetContentScale().x, GetContentScale().y);
439
440 DlPaint paint;
441 paint.setColor(DlColor::RGBA(0.1, 0.2, 0.1, 1.0));
442 builder.DrawPaint(paint);
443
444 DlPaint save_paint;
445 save_paint.setColorFilter(
446 DlColorFilter::MakeBlend(DlColor::RGBA(1, 0, 0, 1), DlBlendMode::kPlus));
447 builder.SaveLayer(std::nullopt, &save_paint);
448
449 paint.setColor(DlColor::kRed());
450 builder.DrawRect(DlRect::MakeXYWH(100, 100, 400, 400), paint);
451
452 paint.setColor(DlColor::kWhite());
453
454 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
455 builder.DrawImageRect(
456 DlImageImpeller::Make(texture),
457 DlRect::MakeWH(texture->GetSize().width, texture->GetSize().height),
458 DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), //
459 rect.GetRight(), rect.GetBottom()),
460 DlImageSampling::kMipmapLinear, &paint);
461 builder.Restore();
462
463 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
464 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [10/525]

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

Definition at line 399 of file aiks_dl_blend_unittests.cc.

399 {
400 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
401 PixelFormat::kB10G10R10A10XR);
402 auto texture = CreateTextureForFixture("airplane.jpg",
403 /*enable_mipmapping=*/true);
404
405 DisplayListBuilder builder;
406 DlPaint paint;
407 builder.Scale(GetContentScale().x, GetContentScale().y);
408
409 paint.setColor(DlColor::RGBA(0.9, 1, 0.9, 1.0));
410 builder.DrawPaint(paint);
411 builder.SaveLayer(std::nullopt);
412
413 paint.setBlendMode(DlBlendMode::kPlus);
414 paint.setColor(DlColor::kRed());
415
416 builder.DrawRect(DlRect::MakeXYWH(100, 100, 400, 400), paint);
417 paint.setColor(DlColor::kWhite());
418
419 auto rect = Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100);
420 builder.DrawImageRect(
421 DlImageImpeller::Make(texture),
422 DlRect::MakeWH(texture->GetSize().width, texture->GetSize().height),
423 DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), //
424 rect.GetRight(), rect.GetBottom()),
425 DlImageSampling::kMipmapLinear, &paint);
426 builder.Restore();
427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
428 }

References impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), and x.

## ◆ TEST_P() [11/525]

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

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

Definition at line 1343 of file aiks_dl_blur_unittests.cc.

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

References x.

## ◆ TEST_P() [13/525]

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

Definition at line 437 of file aiks_dl_blur_unittests.cc.

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

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

## ◆ TEST_P() [14/525]

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

Definition at line 1196 of file aiks_dl_blur_unittests.cc.

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

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

## ◆ TEST_P() [15/525]

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

Definition at line 156 of file aiks_dl_vertices_unittests.cc.

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

## ◆ TEST_P() [16/525]

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

Definition at line 424 of file aiks_dl_path_unittests.cc.

424 {
425 DisplayListBuilder builder;
426
427 // Starting at (50, 50), draw lines from:
428 // 1. (50, height)
429 // 2. (width, height)
430 // 3. (width, 50)
431 DlPathBuilder path_builder;
432 path_builder.MoveTo(DlPoint(50, 50));
433 path_builder.LineTo(DlPoint(50, 100));
434 path_builder.LineTo(DlPoint(100, 100));
435 path_builder.LineTo(DlPoint(100, 50));
436
437 DlPaint paint;
438 paint.setColor(DlColor::kRed());
439 paint.setDrawStyle(DlDrawStyle::kStroke);
440 paint.setStrokeWidth(10);
441
442 builder.DrawPath(DlPath(path_builder), paint);
443
444 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
445 }

## ◆ TEST_P() [17/525]

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

Definition at line 447 of file aiks_dl_path_unittests.cc.

447 {
448 DisplayListBuilder builder;
449
450 // Draw a stroked path that is explicitly closed to verify
451 // It doesn't become a rectangle.
452 DlPathBuilder path_builder;
453 path_builder.MoveTo(DlPoint(50, 50));
454 path_builder.LineTo(DlPoint(520, 120));
455 path_builder.LineTo(DlPoint(300, 310));
456 path_builder.LineTo(DlPoint(100, 50));
457 path_builder.Close();
458
459 DlPaint paint;
460 paint.setColor(DlColor::kRed());
461 paint.setDrawStyle(DlDrawStyle::kStroke);
462 paint.setStrokeWidth(10);
463
464 builder.DrawPath(DlPath(path_builder), paint);
465
466 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
467 }

## ◆ TEST_P() [18/525]

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

Definition at line 807 of file aiks_dl_path_unittests.cc.

807 {
808 DlPathBuilder path_builder;
809 for (auto i = 0; i < 10; i++) {
810 if (i % 2 == 0) {
811 // We use the factory method to convert the circle to a path so that it
812 // uses the legacy conics for legacy golden output.
813 DlPath circle =
814 DlPath::MakeCircle(DlPoint(100 + 50 * i, 100 + 50 * i), 100);
815 path_builder.AddPath(circle.GetPath());
816 path_builder.Close();
817 } else {
818 path_builder.MoveTo(DlPoint(100.f + 50.f * i - 100, 100.f + 50.f * i));
819 path_builder.LineTo(DlPoint(100.f + 50.f * i, 100.f + 50.f * i - 100));
820 path_builder.LineTo(DlPoint(100.f + 50.f * i - 100, //
821 100.f + 50.f * i - 100));
822 path_builder.Close();
823 }
824 }
825 DlPath path(path_builder);
826
827 DisplayListBuilder builder;
828 DlPaint paint;
829 paint.setColor(DlColor::kRed().withAlpha(102));
830 builder.DrawPath(path, paint);
831
832 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
833 }

## ◆ TEST_P() [19/525]

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

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

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

Definition at line 681 of file aiks_dl_blend_unittests.cc.

681 {
682 auto modes = GetBlendModeSelection();
683
684 auto callback = [&]() -> sk_sp<DisplayList> {
685 static Color background = Color::MediumTurquoise();
686 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
687 static int current_blend_index = 3;
688
689 if (AiksTest::ImGuiBegin("Controls", nullptr,
690 ImGuiWindowFlags_AlwaysAutoResize)) {
691 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
692 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
693 ImGui::ListBox("Blend mode", &current_blend_index,
694 modes.blend_mode_names.data(),
695 modes.blend_mode_names.size());
696 ImGui::End();
697 }
698
699 DisplayListBuilder builder;
700 builder.Scale(0.2, 0.2);
701 DlPaint paint;
702 paint.setColor(DlColor(background.ToARGB()));
703 builder.DrawPaint(paint);
704
705 paint.setColor(DlColor(foreground.ToARGB()));
706 paint.setBlendMode(static_cast<DlBlendMode>(current_blend_index));
707 builder.DrawPaint(paint);
708 return builder.Build();
709 };
710 ASSERT_TRUE(OpenPlaygroundHere(callback));
711 }
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() [22/525]

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

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

Definition at line 839 of file aiks_dl_basic_unittests.cc.

839 {
840 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
841 int time = 0;
842 auto callback = [&]() -> sk_sp<DisplayList> {
843 DisplayListBuilder builder;
844
845 builder.Save();
846 {
847 builder.Translate(300, 300);
848
849 // 1. Draw/restore a clip before drawing the image, which will get drawn
850 // to the depth buffer behind the image.
851 builder.Save();
852 {
853 DlPaint paint;
854 paint.setColor(DlColor::kGreen());
855 builder.DrawPaint(paint);
856 builder.ClipRect(DlRect::MakeLTRB(-180, -180, 180, 180),
857 DlClipOp::kDifference);
858
859 paint.setColor(DlColor::kBlack());
860 builder.DrawPaint(paint);
861 }
862 builder.Restore(); // Restore rectangle difference clip.
863
864 builder.Save();
865 {
866 // 2. Draw an oval clip that applies to the image, which will get drawn
867 // in front of the image on the depth buffer.
868 builder.ClipOval(DlRect::MakeLTRB(-200, -200, 200, 200));
869
870 Matrix result =
871 Matrix(1.0, 0.0, 0.0, 0.0, //
872 0.0, 1.0, 0.0, 0.0, //
873 0.0, 0.0, 1.0, 0.003, //
874 0.0, 0.0, 0.0, 1.0) *
875 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}});
876
877 // 3. Draw the rotating image with a perspective transform.
878 builder.Transform(result);
879
880 auto image =
881 DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
882 auto position =
883 -DlPoint(image->dimensions().fWidth, image->dimensions().fHeight) *
884 0.5;
885 builder.DrawImage(image, position, {});
886 }
887 builder.Restore(); // Restore oval intersect clip.
888
889 // 4. Draw a semi-translucent blue circle atop all previous draws.
890 DlPaint paint;
891 paint.setColor(DlColor::kBlue().modulateOpacity(0.4));
892 builder.DrawCircle(DlPoint(), 230, paint);
893 }
894 builder.Restore(); // Restore translation.
895
896 return builder.Build();
897 };
898 ASSERT_TRUE(OpenPlaygroundHere(callback));
899 }

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

## ◆ TEST_P() [24/525]

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 }

## ◆ TEST_P() [25/525]

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().

## ◆ TEST_P() [26/525]

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

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

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

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

Definition at line 1181 of file aiks_dl_basic_unittests.cc.

1181 {
1182 DisplayListBuilder builder;
1183
1184 DlPaint paint;
1185 paint.setColor(DlColor::kRed());
1186 builder.DrawCircle(DlPoint(250, 250), 125, paint);
1187
1188 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1189 }

## ◆ TEST_P() [30/525]

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

Definition at line 1202 of file aiks_dl_basic_unittests.cc.

1202 {
1203 DisplayListBuilder builder;
1204
1205 DlPaint save;
1206 save.setColor(DlColor::kBlack());
1207
1208 DlRect save_bounds = DlRect::MakeXYWH(0, 0, 50, 50);
1209 builder.SaveLayer(save_bounds, &save);
1210
1211 DlPaint paint;
1212 paint.setColor(DlColor::kRed());
1213 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1214 paint.setColor(DlColor::kGreen());
1215 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), paint);
1216 paint.setColor(DlColor::kBlue());
1217 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), paint);
1218
1219 builder.Restore();
1220
1221 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1222 }

## ◆ TEST_P() [31/525]

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

Definition at line 1103 of file aiks_dl_basic_unittests.cc.

1104 {
1105 DisplayListBuilder builder;
1106
1107 DlPaint red;
1108 red.setColor(DlColor::kRed());
1109
1110 DlPaint green;
1111 green.setColor(DlColor::kGreen());
1112
1113 DlPaint blue;
1114 blue.setColor(DlColor::kBlue());
1115
1116 DlPaint save;
1117 save.setColor(DlColor::kBlack().modulateOpacity(0.5));
1118
1119 DlRect huge_bounds = DlRect::MakeXYWH(0, 0, 100000, 100000);
1120 builder.SaveLayer(huge_bounds, &save);
1121
1122 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1123 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100), green);
1124 builder.DrawRect(DlRect::MakeXYWH(20, 20, 100, 100), blue);
1125
1126 builder.Restore();
1127
1128 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1129 }

## ◆ TEST_P() [32/525]

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

Definition at line 1191 of file aiks_dl_basic_unittests.cc.

1191 {
1192 DisplayListBuilder builder;
1193
1194 DlPaint red;
1195 red.setColor(DlColor::kRed());
1196 builder.Skew(2, 5);
1197 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), red);
1198
1199 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1200 }

## ◆ TEST_P() [33/525]

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

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

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

Definition at line 240 of file aiks_dl_blur_unittests.cc.

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

## ◆ TEST_P() [36/525]

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

Definition at line 350 of file aiks_dl_blur_unittests.cc.

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

## ◆ TEST_P() [37/525]

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

Definition at line 203 of file aiks_dl_blur_unittests.cc.

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

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

Definition at line 269 of file aiks_dl_blur_unittests.cc.

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

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [39/525]

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

Definition at line 800 of file aiks_dl_basic_unittests.cc.

800 {
801 DisplayListBuilder builder;
802
803 builder.Scale(GetContentScale().x, GetContentScale().y);
804
805 // Draw something interesting in the background.
806 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
807 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
808 std::vector<Scalar> stops = {
809 0.0,
810 1.0,
811 };
812 DlPaint paint;
813 paint.setColorSource(DlColorSource::MakeLinear(
814 /*start_point=*/DlPoint(0, 0), //
815 /*end_point=*/DlPoint(100, 100), //
816 /*stop_count=*/2, //
817 /*colors=*/colors.data(), //
818 /*stops=*/stops.data(), //
819 /*tile_mode=*/DlTileMode::kRepeat //
820 ));
821
822 builder.DrawPaint(paint);
823
824 DlRect clip_rect = DlRect::MakeLTRB(50, 50, 400, 300);
825 DlRoundRect clip_rrect = DlRoundRect::MakeRectXY(clip_rect, 100, 100);
826
827 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
828 // the same.
829 builder.ClipRoundRect(clip_rrect, DlClipOp::kIntersect);
830
831 DlPaint save_paint;
832 auto backdrop_filter = DlImageFilter::MakeColorFilter(
833 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kExclusion));
834 builder.SaveLayer(clip_rect, &save_paint, backdrop_filter.get());
835
836 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }

References x.

## ◆ TEST_P() [40/525]

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

Definition at line 368 of file aiks_dl_blur_unittests.cc.

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

## ◆ TEST_P() [41/525]

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

Definition at line 1436 of file aiks_dl_basic_unittests.cc.

1436 {
1437 DisplayListBuilder builder;
1438
1439 DlPaint paint;
1440 paint.setColor(DlColor::kWhite());
1441 builder.DrawPaint(paint);
1442
1443 // Draw a green circle on the screen.
1444 {
1445 // Increase the clip depth for the savelayer to contend with.
1446 DlPath path = DlPath::MakeCircle(DlPoint(100, 100), 50);
1447 builder.ClipPath(path);
1448
1449 DlRect bounds = DlRect::MakeXYWH(50, 50, 100, 100);
1450 DlPaint save_paint;
1451 builder.SaveLayer(bounds, &save_paint);
1452
1453 // Fill the layer with white.
1454 paint.setColor(DlColor::kWhite());
1455 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1456 // Fill the layer with green, but do so with a color blend that can't be
1457 // collapsed into the parent pass.
1458 paint.setColor(DlColor::kGreen());
1459 paint.setBlendMode(DlBlendMode::kHardLight);
1460 builder.DrawRect(DlRect::MakeSize(DlSize(400, 400)), paint);
1461 }
1462
1463 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1464 }

## ◆ TEST_P() [42/525]

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

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

Definition at line 860 of file aiks_dl_path_unittests.cc.

860 {
861 DisplayListBuilder builder;
862 DlPaint paint;
863 paint.setColor(DlColor::kFuchsia());
864
865 builder.ClipPath(DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 500, 500)));
866 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
867
868 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
869 }

## ◆ TEST_P() [44/525]

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

Definition at line 29 of file aiks_dl_basic_unittests.cc.

29 {
30 DisplayListBuilder builder;
31 DlPaint paint;
32 paint.setColor(DlColor::kBlue());
33 builder.DrawPath(DlPath::MakeRectXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
34 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
35 }

## ◆ TEST_P() [45/525]

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

Definition at line 61 of file aiks_dl_basic_unittests.cc.

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

## ◆ TEST_P() [46/525]

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

Definition at line 73 of file aiks_dl_basic_unittests.cc.

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

## ◆ TEST_P() [47/525]

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

Definition at line 654 of file aiks_dl_gradient_unittests.cc.

654 {
655 Scalar size = 256;
656 DisplayListBuilder builder;
657 DlPaint paint;
658 paint.setColor(DlColor::kWhite());
659 builder.DrawRect(DlRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
660 std::vector<DlColor> colors = {
661 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
662 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
663 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
664 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
665 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
666 std::array<std::tuple<DlPoint, float, DlPoint, float>, 8> array{
667 std::make_tuple(DlPoint(size / 2.f, size / 2.f), 0.f,
668 DlPoint(size / 2.f, size / 2.f), size / 2.f),
669 std::make_tuple(DlPoint(size / 2.f, size / 2.f), size / 4.f,
670 DlPoint(size / 2.f, size / 2.f), size / 2.f),
671 std::make_tuple(DlPoint(size / 4.f, size / 4.f), 0.f,
672 DlPoint(size / 2.f, size / 2.f), size / 2.f),
673 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 2.f,
674 DlPoint(size / 2.f, size / 2.f), 0),
675 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 4.f,
676 DlPoint(size / 2.f, size / 2.f), size / 2.f),
677 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 16.f,
678 DlPoint(size / 2.f, size / 2.f), size / 8.f),
679 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 8.f,
680 DlPoint(size / 2.f, size / 2.f), size / 16.f),
681 std::make_tuple(DlPoint(size / 8.f, size / 8.f), size / 8.f,
682 DlPoint(size / 2.f, size / 2.f), size / 8.f),
683 };
684 for (int i = 0; i < 8; i++) {
685 builder.Save();
686 builder.Translate((i % 3) * size, i / 3 * size);
687 paint.setColorSource(DlColorSource::MakeConical(
688 /*start_center=*/std::get<2>(array[i]),
689 /*start_radius=*/std::get<3>(array[i]),
690 /*end_center=*/std::get<0>(array[i]),
691 /*end_radius=*/std::get<1>(array[i]),
692 /*stop_count=*/stops.size(),
693 /*colors=*/colors.data(),
694 /*stops=*/stops.data(),
695 /*tile_mode=*/DlTileMode::kClamp));
696 builder.DrawRect(DlRect::MakeXYWH(0, 0, size, size), paint);
697 builder.Restore();
698 }
699 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
700 }

## ◆ TEST_P() [48/525]

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

Definition at line 173 of file aiks_dl_gradient_unittests.cc.

173 {
174 CanRenderConicalGradientWithDithering(this);
175 }
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:154

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [49/525]

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

Definition at line 315 of file aiks_dl_gradient_unittests.cc.

315 {
316 CanRenderGradientWithIncompleteStops(this,
317 DlColorSourceType::kConicalGradient);
318 }

## ◆ TEST_P() [50/525]

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

Definition at line 68 of file aiks_dl_path_unittests.cc.

68 {
69 DisplayListBuilder builder;
70 DlPaint paint;
71 paint.setColor(DlColor::kRed());
72 paint.setStrokeWidth(25);
73 paint.setDrawStyle(DlDrawStyle::kStroke);
74
75 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
76
77 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
78 }

## ◆ TEST_P() [51/525]

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

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

Definition at line 34 of file aiks_dl_clip_unittests.cc.

34 {
35 DisplayListBuilder builder;
36 builder.Translate(400, 400);
37
38 // Limit drawing to face circle with a clip.
39 builder.ClipPath(DlPath::MakeCircle(DlPoint(0, 0), 200));
40 builder.Save();
41
42 // Cut away eyes/mouth using difference clips.
43 builder.ClipPath(DlPath::MakeCircle(DlPoint(-100, -50), 30),
44 DlClipOp::kDifference);
45 builder.ClipPath(DlPath::MakeCircle(DlPoint(100, -50), 30),
46 DlClipOp::kDifference);
47
48 DlPathBuilder path_builder;
49 path_builder.MoveTo(DlPoint(-100, 50));
50 path_builder.QuadraticCurveTo(DlPoint(0, 150), DlPoint(100, 50));
51 builder.ClipPath(DlPath(path_builder), DlClipOp::kDifference);
52
53 // Draw a huge yellow rectangle to prove the clipping works.
54 DlPaint paint;
55 paint.setColor(DlColor::kYellow());
56 builder.DrawRect(DlRect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
57
58 // Remove the difference clips and draw hair that partially covers the eyes.
59 builder.Restore();
60 paint.setColor(DlColor::kMaroon());
61 DlPathBuilder path_builder_2;
62 path_builder_2.MoveTo(DlPoint(200, -200));
63 path_builder_2.LineTo(DlPoint(-200, -200));
64 path_builder_2.LineTo(DlPoint(-200, -40));
65 path_builder_2.CubicCurveTo(DlPoint(0, -40), DlPoint(0, -80),
66 DlPoint(200, -80));
67
68 builder.DrawPath(DlPath(path_builder_2), paint);
69
70 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
71 }

## ◆ TEST_P() [53/525]

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

Definition at line 392 of file aiks_dl_path_unittests.cc.

392 {
393 DisplayListBuilder builder;
394
395 DlPaint paint;
396 paint.setColor(DlColor::kRed());
397
398 RoundingRadii radii = {
399 .top_left = {50, 25},
400 .top_right = {25, 50},
401 .bottom_left = {25, 50},
402 .bottom_right = {50, 25},
403 };
404 PathBuilder path_builder;
405 DlRoundRect rrect =
406 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 200, 200), radii);
407 // We use the factory method to convert the rrect and circle to a path so
408 // that they use the legacy conics for legacy golden output.
409 path_builder.AddPath(DlPath::MakeRoundRect(rrect).GetPath());
410 path_builder.AddPath(DlPath::MakeCircle(DlPoint(200, 200), 50).GetPath());
411 DlPath path(path_builder, DlPathFillType::kOdd);
412
413 builder.DrawImage(
414 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
415 DlPoint{10, 10}, {});
416 builder.DrawPath(path, paint);
417
418 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
419 }

References impeller::PathBuilder::AddPath(), impeller::DlImageImpeller::Make(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [54/525]

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

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

Definition at line 381 of file aiks_dl_text_unittests.cc.

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

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [56/525]

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

Definition at line 409 of file aiks_dl_text_unittests.cc.

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

References kFontFixture, and RenderTextInCanvasSkia().

## ◆ TEST_P() [57/525]

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

Definition at line 393 of file aiks_dl_text_unittests.cc.

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

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

## ◆ TEST_P() [58/525]

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

Definition at line 156 of file aiks_dl_path_unittests.cc.

156 {
157 DisplayListBuilder builder;
158 builder.Scale(GetContentScale().x, GetContentScale().y);
159
160 DlPaint paint;
161 paint.setColor(DlColor::kRed());
162 paint.setDrawStyle(DlDrawStyle::kFill);
163
164 DlPaint reference_paint;
165 reference_paint.setColor(DlColor::kGreen());
166 reference_paint.setDrawStyle(DlDrawStyle::kFill);
167
168 DlPathBuilder path_builder;
169 DlPathBuilder reference_builder;
170
171 // weight of 1.0 is just a quadratic bezier
172 path_builder.MoveTo(DlPoint(100, 100));
173 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
174 reference_builder.MoveTo(DlPoint(300, 100));
175 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
176
177 // weight of sqrt(2)/2 is a circular section
178 path_builder.MoveTo(DlPoint(100, 200));
179 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
180 reference_builder.MoveTo(DlPoint(300, 200));
181 auto magic = DlPathBuilder::kArcApproximationMagic;
182 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
183 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
184 DlPoint(400, 200));
185
186 // weight of .01 is nearly a straight line
187 path_builder.MoveTo(DlPoint(100, 300));
188 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.01f);
189 reference_builder.MoveTo(DlPoint(300, 300));
190 reference_builder.LineTo(DlPoint(350, 300.5));
191 reference_builder.LineTo(DlPoint(400, 300));
192
193 // weight of 100.0 is nearly a triangle
194 path_builder.MoveTo(DlPoint(100, 400));
195 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
196 reference_builder.MoveTo(DlPoint(300, 400));
197 reference_builder.LineTo(DlPoint(350, 450));
198 reference_builder.LineTo(DlPoint(400, 400));
199
200 builder.DrawPath(DlPath(path_builder), paint);
201 builder.DrawPath(DlPath(reference_builder), reference_paint);
202
203 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
204 }
impeller::kSqrt2Over2
constexpr float kSqrt2Over2
Definition: constants.h:51

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [59/525]

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

Definition at line 182 of file aiks_dl_blur_unittests.cc.

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

References impeller::Sigma::sigma.

## ◆ TEST_P() [60/525]

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

Definition at line 163 of file aiks_dl_blur_unittests.cc.

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

References impeller::Sigma::sigma.

## ◆ TEST_P() [61/525]

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

Definition at line 702 of file aiks_dl_gradient_unittests.cc.

702 {
703 std::vector<DlColor> colors = {
704 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
705 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
706 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
707 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
708 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
709
710 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
711 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
712 stops.data(), DlTileMode::kDecal),
713 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
714 stops.data(), DlTileMode::kDecal),
715 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
716 stops.data(), DlTileMode::kDecal),
717 };
718
719 DisplayListBuilder builder;
720 DlPaint paint;
721 paint.setColor(DlColor::kWhite());
722 builder.DrawRect(DlRect::MakeLTRB(0, 0, 605, 205), paint);
723 for (int i = 0; i < 3; i++) {
724 builder.Save();
725 builder.Translate(i * 200.0f, 0);
726 paint.setColorSource(color_sources[i]);
727 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
728 builder.Restore();
729 }
730 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
731 }

## ◆ TEST_P() [62/525]

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

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

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

Definition at line 37 of file aiks_dl_basic_unittests.cc.

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

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [65/525]

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 = DlISize(image->dimensions().fWidth * 0.5f,
216 image->dimensions().fHeight * 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() [66/525]

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

Definition at line 47 of file aiks_dl_basic_unittests.cc.

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

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [67/525]

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

Definition at line 361 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [68/525]

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

Definition at line 54 of file aiks_dl_gradient_unittests.cc.

54 {
55 CanRenderLinearGradient(this, DlTileMode::kClamp);
56 }

## ◆ TEST_P() [69/525]

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

Definition at line 63 of file aiks_dl_gradient_unittests.cc.

63 {
64 CanRenderLinearGradient(this, DlTileMode::kDecal);
65 }

## ◆ TEST_P() [70/525]

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

Definition at line 67 of file aiks_dl_gradient_unittests.cc.

67 {
68 DisplayListBuilder builder;
69 Point scale = GetContentScale();
70 builder.Scale(scale.x, scale.y);
71 DlPaint paint;
72 builder.Translate(100.0f, 0);
73
74 std::vector<DlColor> colors = {
75 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
76 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
77 std::vector<Scalar> stops = {0.0, 1.0};
78
79 paint.setColorSource(DlColorSource::MakeLinear(
80 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kDecal));
81 // Overlay the gradient with 25% green. This should appear as the entire
82 // rectangle being drawn with 25% green, including the border area outside the
83 // decal gradient.
84 paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kGreen().withAlpha(64),
85 DlBlendMode::kSrcOver));
86 paint.setColor(DlColor::kWhite());
87 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
88 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
89 }

References scale, and impeller::Color::ToARGB().

## ◆ TEST_P() [71/525]

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

Definition at line 360 of file aiks_dl_gradient_unittests.cc.

360 {
361 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
362 }

## ◆ TEST_P() [72/525]

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

Definition at line 369 of file aiks_dl_gradient_unittests.cc.

369 {
370 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
371 }

## ◆ TEST_P() [73/525]

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

Definition at line 366 of file aiks_dl_gradient_unittests.cc.

366 {
367 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
368 }

## ◆ TEST_P() [74/525]

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

Definition at line 363 of file aiks_dl_gradient_unittests.cc.

363 {
364 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
365 }

## ◆ TEST_P() [75/525]

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

Definition at line 404 of file aiks_dl_gradient_unittests.cc.

404 {
405 auto callback = [&]() -> sk_sp<DisplayList> {
406 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
407 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
408 DlTileMode::kMirror, DlTileMode::kDecal};
409
410 static int selected_tile_mode = 0;
411 static Matrix matrix;
412 if (AiksTest::ImGuiBegin("Controls", nullptr,
413 ImGuiWindowFlags_AlwaysAutoResize)) {
414 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
415 sizeof(tile_mode_names) / sizeof(char*));
416 std::string label = "##1";
417 for (int i = 0; i < 4; i++) {
418 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
419 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
420 label[2]++;
421 }
422 ImGui::End();
423 }
424
425 DisplayListBuilder builder;
426 DlPaint paint;
427 builder.Translate(100.0, 100.0);
428 auto tile_mode = tile_modes[selected_tile_mode];
429
430 std::vector<DlColor> colors = {
431 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
432 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
433 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
434 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
435 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
436 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
437 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
438 std::vector<Scalar> stops = {
439 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
440 };
441
442 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
443 stops.size(), colors.data(),
444 stops.data(), tile_mode));
445
446 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
447 return builder.Build();
448 };
449 ASSERT_TRUE(OpenPlaygroundHere(callback));
450 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [76/525]

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

Definition at line 452 of file aiks_dl_gradient_unittests.cc.

452 {
453 DisplayListBuilder builder;
454
455 std::vector<DlColor> colors = {
456 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
457 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
458 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed()};
459 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
460 0.6, 0.7, 0.8, 0.9, 1.0};
461
462 DlPaint paint;
463 paint.setColor(DlColor::kWhite());
464 paint.setColorSource(DlColorSource::MakeLinear(
465 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
466 DlTileMode::kClamp));
467 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
468
469 builder.DrawCircle(DlPoint(300, 300), 200, paint);
470 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
471
472 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
473 }

## ◆ TEST_P() [77/525]

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

Definition at line 60 of file aiks_dl_gradient_unittests.cc.

60 {
61 CanRenderLinearGradient(this, DlTileMode::kMirror);
62 }

## ◆ TEST_P() [78/525]

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

Definition at line 57 of file aiks_dl_gradient_unittests.cc.

57 {
58 CanRenderLinearGradient(this, DlTileMode::kRepeat);
59 }

## ◆ TEST_P() [79/525]

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

Definition at line 400 of file aiks_dl_gradient_unittests.cc.

400 {
401 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
402 }

## ◆ TEST_P() [80/525]

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

Definition at line 107 of file aiks_dl_gradient_unittests.cc.

107 {
108 CanRenderLinearGradientWithDithering(this);
109 }
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:91

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [81/525]

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

Definition at line 307 of file aiks_dl_gradient_unittests.cc.

307 {
308 CanRenderGradientWithIncompleteStops(this,
309 DlColorSourceType::kLinearGradient);
310 }

## ◆ TEST_P() [82/525]

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

Definition at line 202 of file aiks_dl_gradient_unittests.cc.

202 {
203 CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp);
204 }

## ◆ TEST_P() [83/525]

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

Definition at line 151 of file aiks_dl_blur_unittests.cc.

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

## ◆ TEST_P() [84/525]

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

Definition at line 294 of file aiks_dl_blur_unittests.cc.

294 {
295 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
296
297 DisplayListBuilder builder;
298
299 DlPaint paint;
300 builder.DrawImage(image, DlPoint(50.0, 50.0),
301 DlImageSampling::kNearestNeighbor, &paint);
302
303 for (int i = 0; i < 6; i++) {
304 DlRoundRect rrect = DlRoundRect::MakeRectXY(
305 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
306 builder.Save();
307 builder.ClipRoundRect(rrect);
308
309 DlPaint save_paint;
310 save_paint.setBlendMode(DlBlendMode::kSrc);
311 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
312 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
313 /*backdrop_id=*/1);
314 builder.Restore();
315 builder.Restore();
316 }
317
318 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
319 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [85/525]

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

Definition at line 321 of file aiks_dl_blur_unittests.cc.

322 {
323 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
324
325 DisplayListBuilder builder;
326
327 DlPaint paint;
328 builder.DrawImage(image, DlPoint(50.0, 50.0),
329 DlImageSampling::kNearestNeighbor, &paint);
330
331 for (int i = 0; i < 6; i++) {
332 DlRoundRect rrect = DlRoundRect::MakeRectXY(
333 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
334 builder.Save();
335 builder.ClipRoundRect(rrect);
336
337 DlPaint save_paint;
338 save_paint.setBlendMode(DlBlendMode::kSrc);
339 auto backdrop_filter =
340 DlImageFilter::MakeBlur(30 + i, 30, DlTileMode::kClamp);
341 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
342 /*backdrop_id=*/1);
343 builder.Restore();
344 builder.Restore();
345 }
346
347 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
348 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [86/525]

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

Definition at line 1307 of file aiks_dl_blur_unittests.cc.

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

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [87/525]

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

Definition at line 19 of file aiks_dl_clip_unittests.cc.

19 {
20 DisplayListBuilder builder;
21 DlPaint paint;
22 paint.setColor(DlColor::kFuchsia());
23
24 builder.Save();
25 builder.ClipPath(DlPath::MakeCircle(DlPoint(200, 400), 300));
26 builder.Restore();
27 builder.ClipPath(DlPath::MakeCircle(DlPoint(600, 400), 300));
28 builder.ClipPath(DlPath::MakeCircle(DlPoint(400, 600), 300));
29 builder.DrawRect(DlRect::MakeXYWH(200, 200, 400, 400), paint);
30
31 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
32 }

## ◆ TEST_P() [88/525]

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

Definition at line 910 of file aiks_dl_path_unittests.cc.

910 {
911 DisplayListBuilder builder;
912
913 DlPaint paint;
914 paint.setColor(DlColor::kRed());
915
916 RoundingRadii radii = {
917 .top_left = DlSize(50, 50),
918 .top_right = DlSize(50, 50),
919 .bottom_left = DlSize(50, 50),
920 .bottom_right = DlSize(50, 50),
921 };
922
923 const Scalar kTriangleHeight = 100;
924 DlRoundRect rrect = DlRoundRect::MakeRectRadii(
925 DlRect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
926 kTriangleHeight, kTriangleHeight),
927 radii //
928 );
929 // We use the factory method to convert the rrect to a path so that it
930 // uses the legacy conics for legacy golden output.
931 DlPath rrect_path = DlPath::MakeRoundRect(rrect);
932
933 builder.Translate(200, 200);
934 // Form a path similar to the Material drop slider value indicator. Both
935 // shapes should render identically side-by-side.
936 {
937 DlPathBuilder path_builder;
938 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
939 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
940 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
941 path_builder.Close();
942 path_builder.AddPath(rrect_path.GetPath());
943
944 builder.DrawPath(DlPath(path_builder), paint);
945 }
946 builder.Translate(100, 0);
947
948 {
949 DlPathBuilder path_builder;
950 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
951 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
952 path_builder.LineTo(DlPoint(0, -10));
953 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
954 path_builder.Close();
955 path_builder.AddPath(rrect_path.GetPath());
956
957 builder.DrawPath(DlPath(path_builder), paint);
958 }
959
960 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
961 }

References impeller::RoundingRadii::top_left.

## ◆ TEST_P() [89/525]

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

Definition at line 136 of file aiks_dl_path_unittests.cc.

136 {
137 DisplayListBuilder builder;
138
139 DlPaint paint;
140 paint.setColor(DlColor::kRed());
141 paint.setStrokeWidth(50);
142 paint.setDrawStyle(DlDrawStyle::kStroke);
143 paint.setStrokeCap(DlStrokeCap::kRound);
144
145 // Should draw a diagonal pill shape. If flat on either end, the stroke is
146 // rendering wrong.
147 DlPathBuilder path_builder;
148 path_builder.MoveTo(DlPoint(250, 250));
149 path_builder.QuadraticCurveTo(DlPoint(100, 100), DlPoint(250, 250));
150
151 builder.DrawPath(DlPath(path_builder), paint);
152
153 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
154 }

## ◆ TEST_P() [90/525]

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

Definition at line 475 of file aiks_dl_gradient_unittests.cc.

475 {
476 auto callback = [&]() -> sk_sp<DisplayList> {
477 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
478 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
479 DlTileMode::kMirror, DlTileMode::kDecal};
480
481 static int selected_tile_mode = 0;
482 static Matrix matrix;
483 if (AiksTest::ImGuiBegin("Controls", nullptr,
484 ImGuiWindowFlags_AlwaysAutoResize)) {
485 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
486 sizeof(tile_mode_names) / sizeof(char*));
487 std::string label = "##1";
488 for (int i = 0; i < 4; i++) {
489 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
490 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
491 label[2]++;
492 }
493 ImGui::End();
494 }
495
496 DisplayListBuilder builder;
497 DlPaint paint;
498 builder.Translate(100.0, 100.0);
499 auto tile_mode = tile_modes[selected_tile_mode];
500
501 std::vector<DlColor> colors = {
502 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
503 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
504 std::vector<Scalar> stops = {0.0, 1.0};
505
506 paint.setColorSource(DlColorSource::MakeRadial(
507 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
508
509 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
510 return builder.Build();
511 };
512 ASSERT_TRUE(OpenPlaygroundHere(callback));
513 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [91/525]

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

Definition at line 515 of file aiks_dl_gradient_unittests.cc.

515 {
516 auto callback = [&]() -> sk_sp<DisplayList> {
517 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
518 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
519 DlTileMode::kMirror, DlTileMode::kDecal};
520
521 static int selected_tile_mode = 0;
522 static Matrix matrix = {
523 1, 0, 0, 0, //
524 0, 1, 0, 0, //
525 0, 0, 1, 0, //
526 0, 0, 0, 1 //
527 };
528 if (AiksTest::ImGuiBegin("Controls", nullptr,
529 ImGuiWindowFlags_AlwaysAutoResize)) {
530 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
531 sizeof(tile_mode_names) / sizeof(char*));
532 std::string label = "##1";
533 for (int i = 0; i < 4; i++) {
534 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
535 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
536 label[2]++;
537 }
538 ImGui::End();
539 }
540
541 DisplayListBuilder builder;
542 DlPaint paint;
543 builder.Translate(100.0, 100.0);
544 auto tile_mode = tile_modes[selected_tile_mode];
545
546 std::vector<DlColor> colors = {
547 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
548 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
549 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
550 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
551 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
552 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
553 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
554 std::vector<Scalar> stops = {
555 0.0,
556 (1.0 / 6.0) * 1,
557 (1.0 / 6.0) * 2,
558 (1.0 / 6.0) * 3,
559 (1.0 / 6.0) * 4,
560 (1.0 / 6.0) * 5,
561 1.0,
562 };
563
564 paint.setColorSource(DlColorSource::MakeRadial(
565 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
566
567 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
568 return builder.Build();
569 };
570 ASSERT_TRUE(OpenPlaygroundHere(callback));
571 }

References impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [92/525]

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

Definition at line 127 of file aiks_dl_gradient_unittests.cc.

127 {
128 CanRenderRadialGradientWithDithering(this);
129 }
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:111

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [93/525]

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

Definition at line 311 of file aiks_dl_gradient_unittests.cc.

311 {
312 CanRenderGradientWithIncompleteStops(this,
313 DlColorSourceType::kRadialGradient);
314 }

## ◆ TEST_P() [94/525]

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

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

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

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

Definition at line 206 of file aiks_dl_path_unittests.cc.

206 {
207 DisplayListBuilder builder;
208 builder.Scale(GetContentScale().x, GetContentScale().y);
209
210 DlPaint paint;
211 paint.setColor(DlColor::kRed());
212 paint.setStrokeWidth(10);
213 paint.setDrawStyle(DlDrawStyle::kStroke);
214 paint.setStrokeCap(DlStrokeCap::kRound);
215 paint.setStrokeJoin(DlStrokeJoin::kRound);
216
217 DlPaint reference_paint;
218 reference_paint.setColor(DlColor::kGreen());
219 reference_paint.setStrokeWidth(10);
220 reference_paint.setDrawStyle(DlDrawStyle::kStroke);
221 reference_paint.setStrokeCap(DlStrokeCap::kRound);
222 reference_paint.setStrokeJoin(DlStrokeJoin::kRound);
223
224 DlPathBuilder path_builder;
225 DlPathBuilder reference_builder;
226
227 // weight of 1.0 is just a quadratic bezier
228 path_builder.MoveTo(DlPoint(100, 100));
229 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
230 reference_builder.MoveTo(DlPoint(300, 100));
231 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
232
233 // weight of sqrt(2)/2 is a circular section
234 path_builder.MoveTo(DlPoint(100, 200));
235 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
236 reference_builder.MoveTo(DlPoint(300, 200));
237 auto magic = DlPathBuilder::kArcApproximationMagic;
238 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
239 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
240 DlPoint(400, 200));
241
242 // weight of .0 is a straight line
243 path_builder.MoveTo(DlPoint(100, 300));
244 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.0f);
245 reference_builder.MoveTo(DlPoint(300, 300));
246 reference_builder.LineTo(DlPoint(400, 300));
247
248 // weight of 100.0 is nearly a triangle
249 path_builder.MoveTo(DlPoint(100, 400));
250 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
251 reference_builder.MoveTo(DlPoint(300, 400));
252 reference_builder.LineTo(DlPoint(350, 450));
253 reference_builder.LineTo(DlPoint(400, 400));
254
255 builder.DrawPath(DlPath(path_builder), paint);
256 builder.DrawPath(DlPath(reference_builder), reference_paint);
257
258 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
259 }

References impeller::kSqrt2Over2, and x.

## ◆ TEST_P() [98/525]

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

Definition at line 125 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [99/525]

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

Definition at line 104 of file aiks_dl_path_unittests.cc.

104 {
105 DisplayListBuilder builder;
106 DlPaint paint;
107 paint.setColor(DlColor::kRed());
108 paint.setStrokeWidth(200);
109 paint.setDrawStyle(DlDrawStyle::kStroke);
110
111 DlPath path = DlPath::MakeArc(DlRect::MakeXYWH(100, 100, 200, 200), //
112 DlDegrees(0), DlDegrees(90), false);
113
114 builder.DrawPath(path, paint);
115
116 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
117 }

## ◆ TEST_P() [100/525]

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

Definition at line 119 of file aiks_dl_path_unittests.cc.

119 {
120 DisplayListBuilder builder;
121
122 DlPaint paint;
123 paint.setColor(DlColor::kRed());
124 paint.setStrokeWidth(20);
125 paint.setDrawStyle(DlDrawStyle::kStroke);
126
127 DlPathBuilder path_builder;
128 path_builder.MoveTo(DlPoint(0, 200));
129 path_builder.CubicCurveTo(DlPoint(50, 400), DlPoint(350, 0),
130 DlPoint(400, 200));
131
132 builder.DrawPath(DlPath(path_builder), paint);
133 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
134 }

## ◆ TEST_P() [101/525]

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

Definition at line 55 of file aiks_dl_path_unittests.cc.

55 {
56 DisplayListBuilder builder;
57 DlPaint paint;
58 paint.setColor(DlColor::kRed());
59 paint.setStrokeWidth(20);
60 paint.setDrawStyle(DlDrawStyle::kStroke);
61
62 builder.DrawPath(DlPath::MakeLine(DlPoint(200, 100), DlPoint(800, 100)),
63 paint);
64
65 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
66 }

## ◆ TEST_P() [102/525]

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

Definition at line 594 of file aiks_dl_gradient_unittests.cc.

594 {
595 CanRenderSweepGradient(this, DlTileMode::kClamp);
596 }

## ◆ TEST_P() [103/525]

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

Definition at line 603 of file aiks_dl_gradient_unittests.cc.

603 {
604 CanRenderSweepGradient(this, DlTileMode::kDecal);
605 }

## ◆ TEST_P() [104/525]

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

Definition at line 641 of file aiks_dl_gradient_unittests.cc.

641 {
642 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
643 }

## ◆ TEST_P() [105/525]

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

Definition at line 650 of file aiks_dl_gradient_unittests.cc.

650 {
651 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
652 }

## ◆ TEST_P() [106/525]

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

Definition at line 647 of file aiks_dl_gradient_unittests.cc.

647 {
648 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
649 }

## ◆ TEST_P() [107/525]

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

Definition at line 644 of file aiks_dl_gradient_unittests.cc.

644 {
645 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
646 }

## ◆ TEST_P() [108/525]

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

Definition at line 600 of file aiks_dl_gradient_unittests.cc.

600 {
601 CanRenderSweepGradient(this, DlTileMode::kMirror);
602 }

## ◆ TEST_P() [109/525]

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

Definition at line 597 of file aiks_dl_gradient_unittests.cc.

597 {
598 CanRenderSweepGradient(this, DlTileMode::kRepeat);
599 }

## ◆ TEST_P() [110/525]

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

Definition at line 150 of file aiks_dl_gradient_unittests.cc.

150 {
151 CanRenderSweepGradientWithDithering(this);
152 }
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:131

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [111/525]

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

Definition at line 319 of file aiks_dl_gradient_unittests.cc.

319 {
320 CanRenderGradientWithIncompleteStops(this, DlColorSourceType::kSweepGradient);
321 }

## ◆ TEST_P() [112/525]

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

Definition at line 96 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [113/525]

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

Definition at line 250 of file aiks_dl_text_unittests.cc.

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

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

## ◆ TEST_P() [114/525]

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

Definition at line 157 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [115/525]

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

Definition at line 109 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [116/525]

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

Definition at line 221 of file aiks_dl_text_unittests.cc.

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

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

## ◆ TEST_P() [117/525]

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

Definition at line 422 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [118/525]

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

Definition at line 448 of file aiks_dl_text_unittests.cc.

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

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [119/525]

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

Definition at line 141 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [120/525]

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

Definition at line 545 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [121/525]

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

Definition at line 564 of file aiks_dl_text_unittests.cc.

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

References RenderTextInCanvasSkia().

## ◆ TEST_P() [122/525]

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

Definition at line 80 of file aiks_dl_path_unittests.cc.

80 {
81 DisplayListBuilder builder;
82 DlPaint paint;
83 paint.setColor(DlColor::kRed());
84 paint.setStrokeWidth(100);
85 paint.setDrawStyle(DlDrawStyle::kStroke);
86
87 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
88
89 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
90 }

## ◆ TEST_P() [123/525]

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

Definition at line 92 of file aiks_dl_path_unittests.cc.

92 {
93 DisplayListBuilder builder;
94 DlPaint paint;
95 paint.setColor(DlColor::kRed());
96 paint.setStrokeWidth(0.01);
97 paint.setDrawStyle(DlDrawStyle::kStroke);
98
99 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
100
101 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
102 }

## ◆ TEST_P() [124/525]

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

Definition at line 343 of file aiks_dl_path_unittests.cc.

343 {
344 DisplayListBuilder builder;
345 builder.Scale(GetContentScale().x, GetContentScale().y);
346
347 DlPaint paint;
348 paint.setColor(DlColor::kRed());
349 paint.setDrawStyle(DlDrawStyle::kFill);
350
351 DlPaint reference_paint;
352 reference_paint.setColor(DlColor::kGreen());
353 reference_paint.setDrawStyle(DlDrawStyle::kFill);
354
355 DlPathBuilder path_builder;
356
357 path_builder.MoveTo(DlPoint(100, 100));
358 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 100), 5.0f);
359
360 DlPathBuilder reference_builder;
361 ConicPathComponent component(DlPoint(300, 100), //
362 DlPoint(350, 450), //
363 DlPoint(400, 100), //
364 5.0f);
365 reference_builder.MoveTo(component.p1);
366 constexpr int N = 100;
367 for (int i = 1; i < N; i++) {
368 reference_builder.LineTo(component.Solve(static_cast<Scalar>(i) / N));
369 }
370 reference_builder.LineTo(component.p2);
371
372 DlPaint line_paint;
373 line_paint.setColor(DlColor::kYellow());
374 line_paint.setDrawStyle(DlDrawStyle::kStroke);
375 line_paint.setStrokeWidth(1.0f);
376
377 // Draw some lines to provide a spacial reference for the curvature of
378 // the tips of the direct rendering and the manually tessellated versions.
379 builder.DrawLine(DlPoint(145, 100), DlPoint(145, 450), line_paint);
380 builder.DrawLine(DlPoint(155, 100), DlPoint(155, 450), line_paint);
381 builder.DrawLine(DlPoint(345, 100), DlPoint(345, 450), line_paint);
382 builder.DrawLine(DlPoint(355, 100), DlPoint(355, 450), line_paint);
383 builder.DrawLine(DlPoint(100, 392.5f), DlPoint(400, 392.5f), line_paint);
384
385 // Draw the two paths (direct and manually tessellated) on top of the lines.
386 builder.DrawPath(DlPath(path_builder), paint);
387 builder.DrawPath(DlPath(reference_builder), reference_paint);
388
389 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
390 }

References impeller::ConicPathComponent::p1, impeller::ConicPathComponent::p2, impeller::ConicPathComponent::Solve(), and x.

## ◆ TEST_P() [125/525]

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

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

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

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

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

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

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

Definition at line 73 of file aiks_dl_clip_unittests.cc.

73 {
74 DisplayListBuilder builder;
75
76 // Cover the whole canvas with red.
77 DlPaint paint;
78 paint.setColor(DlColor::kRed());
79 builder.DrawPaint(paint);
80
81 builder.Save();
82
83 // Append two clips, the second resulting in empty coverage.
84 builder.ClipRect(DlRect::MakeXYWH(100, 100, 100, 100));
85 builder.ClipRect(DlRect::MakeXYWH(300, 300, 100, 100));
86
87 // Restore to no clips.
88 builder.Restore();
89
90 // Replace the whole canvas with green.
91 paint.setColor(DlColor::kGreen());
92 builder.DrawPaint(paint);
93
94 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
95 }

## ◆ TEST_P() [132/525]

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

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

Definition at line 110 of file canvas_unittests.cc.

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

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

## ◆ TEST_P() [134/525]

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

Definition at line 128 of file canvas_unittests.cc.

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

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

## ◆ TEST_P() [135/525]

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

Definition at line 484 of file aiks_dl_blend_unittests.cc.

484 {
485 DisplayListBuilder builder;
486
487 DlPaint blue;
488 blue.setColor(DlColor::kBlue());
489 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), blue);
490
491 DlPaint clear;
492 clear.setBlendMode(DlBlendMode::kClear);
493
494 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
495
496 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
497 }

## ◆ TEST_P() [136/525]

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

Definition at line 422 of file aiks_dl_blur_unittests.cc.

422 {
423 DisplayListBuilder builder;
424 DlPaint paint;
425 paint.setColor(DlColor::kBlue());
426 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
427
428 DlPaint clear;
429 clear.setBlendMode(DlBlendMode::kClear);
430 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
431
432 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
433
434 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
435 }

## ◆ TEST_P() [137/525]

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

Definition at line 1047 of file aiks_dl_basic_unittests.cc.

1047 {
1048 SetWindowSize({400, 400});
1049 DisplayListBuilder builder;
1050
1051 builder.Scale(GetContentScale().x, GetContentScale().y);
1052
1053 DlPaint paint;
1054 paint.setColor(DlColor::kRed());
1055 builder.DrawRect(DlRect::MakeLTRB(200, 200, 300, 300), paint);
1056
1057 paint.setImageFilter(DlImageFilter::MakeMatrix(DlMatrix::MakeScale({2, 2, 1}),
1058 DlImageSampling::kLinear));
1059 builder.SaveLayer(std::nullopt, &paint);
1060 // Draw a rectangle that would fully cover the parent pass size, but not
1061 // the subpass that it is rendered in.
1062 paint.setColor(DlColor::kGreen());
1063 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
1064 // Draw a bigger rectangle to force the subpass to be bigger.
1065
1066 paint.setColor(DlColor::kRed());
1067 builder.DrawRect(DlRect::MakeLTRB(0, 0, 800, 800), paint);
1068 builder.Restore();
1069
1070 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1071 }

References x.

## ◆ TEST_P() [138/525]

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

Definition at line 405 of file aiks_dl_blur_unittests.cc.

405 {
406 DisplayListBuilder builder;
407 builder.Translate(0, -400);
408 DlPaint paint;
409
410 Sigma sigma = Radius{120 * 3};
411 paint.setMaskFilter(
412 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
413 paint.setColor(DlColor::kRed());
414
415 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
416 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
417 builder.DrawPath(path, paint);
418
419 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
420 }

References impeller::Sigma::sigma.

## ◆ TEST_P() [139/525]

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

Definition at line 381 of file aiks_dl_blur_unittests.cc.

381 {
382 auto callback = [&]() -> sk_sp<DisplayList> {
383 static PlaygroundPoint playground_point(Point(400, 400), 20,
384 Color::Green());
385 auto point = DrawPlaygroundPoint(playground_point);
386
387 DisplayListBuilder builder;
388 auto location = point - Point(400, 400);
389 builder.Translate(location.x, location.y);
390
391 DlPaint paint;
392 Sigma sigma = Radius{120 * 3};
393 paint.setMaskFilter(
394 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
395 paint.setColor(DlColor::kRed());
396
397 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
398 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
399 builder.DrawPath(path, paint);
400 return builder.Build();
401 };
402 ASSERT_TRUE(OpenPlaygroundHere(callback));
403 }
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:9

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

## ◆ TEST_P() [140/525]

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

Definition at line 97 of file aiks_dl_clip_unittests.cc.

97 {
98 std::array<DlColor, 5> colors = {DlColor::kWhite(), DlColor::kBlack(),
99 DlColor::kSkyBlue(), DlColor::kRed(),
100 DlColor::kYellow()};
101 DisplayListBuilder builder;
102 DlPaint paint;
103
104 builder.Translate(300, 300);
105 for (int i = 0; i < 15; i++) {
106 builder.Scale(0.8, 0.8);
107
108 paint.setColor(colors[i % colors.size()]);
109 builder.ClipPath(DlPath::MakeCircle(DlPoint(0, 0), 300));
110 builder.DrawRect(DlRect::MakeXYWH(-300, -300, 600, 600), paint);
111 }
112 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
113 }

## ◆ TEST_P() [141/525]

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

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

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

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 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
342
343 bool has_color_filter = true;
344 auto callback = [&]() -> sk_sp<DisplayList> {
345 if (AiksTest::ImGuiBegin("Controls", nullptr,
346 ImGuiWindowFlags_AlwaysAutoResize)) {
347 ImGui::Checkbox("has color filter", &has_color_filter);
348 ImGui::End();
349 }
350
351 DisplayListBuilder builder;
352 builder.Scale(GetContentScale().x, GetContentScale().y);
353
354 auto src_image =
355 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png"));
356 auto dst_image =
357 DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png"));
358
359 std::vector<DlBlendMode> blend_modes = {
360 DlBlendMode::kScreen, DlBlendMode::kOverlay,
361 DlBlendMode::kDarken, DlBlendMode::kLighten,
362 DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
363 DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
364 DlBlendMode::kDifference, DlBlendMode::kExclusion,
365 DlBlendMode::kMultiply, DlBlendMode::kHue,
366 DlBlendMode::kSaturation, DlBlendMode::kColor,
367 DlBlendMode::kLuminosity,
368 };
369
370 for (uint32_t i = 0; i < blend_modes.size(); ++i) {
371 builder.Save();
372 builder.Translate((i % 5) * 200, (i / 5) * 200);
373 builder.Scale(0.4, 0.4);
374 {
375 DlPaint dstPaint;
376 builder.DrawImage(dst_image, DlPoint(0, 0),
377 DlImageSampling::kMipmapLinear, &dstPaint);
378 }
379 {
380 DlPaint srcPaint;
381 srcPaint.setBlendMode(blend_modes[i]);
382 if (has_color_filter) {
383 std::shared_ptr<const DlColorFilter> color_filter =
384 DlColorFilter::MakeBlend(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
385 DlBlendMode::kMultiply);
386 srcPaint.setColorFilter(color_filter);
387 }
388 builder.DrawImage(src_image, DlPoint(0, 0),
389 DlImageSampling::kMipmapLinear, &srcPaint);
390 }
391 builder.Restore();
392 }
393 return builder.Build();
394 };
395 ASSERT_TRUE(OpenPlaygroundHere(callback));
396 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::kMetal, impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [145/525]

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

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

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 772 of file aiks_dl_blend_unittests.cc.

772 {
773 // Compare with https://fiddle.skia.org/c/@BlendModes
774
775 BlendModeSelection blend_modes = GetBlendModeSelection();
776
777 auto draw_color_wheel = [](DisplayListBuilder& builder) -> void {
778 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
779 /// cyan domain: r >= 0 (because modulo used is non euclidean)
780 auto color_wheel_sampler = [](Radians r) {
781 Scalar x = r.radians / k2Pi + 1;
782
783 // https://www.desmos.com/calculator/6nhjelyoaj
784 auto color_cycle = [](Scalar x) {
785 Scalar cycle = std::fmod(x, 6.0f);
786 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
787 };
788 return Color(color_cycle(6 * x + 1), //
789 color_cycle(6 * x - 1), //
790 color_cycle(6 * x - 3), //
791 1);
792 };
793
794 DlPaint paint;
795 paint.setBlendMode(DlBlendMode::kSrcOver);
796
797 // Draw a fancy color wheel for the backdrop.
798 // https://www.desmos.com/calculator/xw7kafthwd
799 const int max_dist = 900;
800 for (int i = 0; i <= 900; i++) {
801 Radians r(kPhi / k2Pi * i);
802 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
803 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
804
805 auto color = color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
806 paint.setColor(
807 DlColor::RGBA(color.red, color.green, color.blue, color.alpha));
808 DlPoint position = DlPoint(distance * std::sin(r.radians),
809 -distance * std::cos(r.radians));
810
811 builder.DrawCircle(position, 9 + normalized_distance * 3, paint);
812 }
813 };
814
815 auto callback = [&]() -> sk_sp<DisplayList> {
816 // UI state.
817 static bool cache_the_wheel = true;
818 static int current_blend_index = 3;
819 static float dst_alpha = 1;
820 static float src_alpha = 1;
821 static DlColor color0 = DlColor::kRed();
822 static DlColor color1 = DlColor::kGreen();
823 static DlColor color2 = DlColor::kBlue();
824
825 if (AiksTest::ImGuiBegin("Controls", nullptr,
826 ImGuiWindowFlags_AlwaysAutoResize)) {
827 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
828 ImGui::ListBox("Blending mode", &current_blend_index,
829 blend_modes.blend_mode_names.data(),
830 blend_modes.blend_mode_names.size());
831 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
832 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
833 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
834 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
835 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
836 ImGui::End();
837 }
838
839 DisplayListBuilder builder;
840
841 DlPaint paint;
842 paint.setColor(DlColor::kWhite().withAlpha(dst_alpha * 255));
843 paint.setBlendMode(DlBlendMode::kSrc);
844 builder.SaveLayer(std::nullopt, &paint);
845 {
846 DlPaint paint;
847 paint.setColor(DlColor::kWhite());
848 builder.DrawPaint(paint);
849
850 builder.SaveLayer(std::nullopt, nullptr);
851 builder.Scale(GetContentScale().x, GetContentScale().y);
852 builder.Translate(500, 400);
853 builder.Scale(3, 3);
854 draw_color_wheel(builder);
855 builder.Restore();
856 }
857 builder.Restore();
858
859 builder.Scale(GetContentScale().x, GetContentScale().y);
860 builder.Translate(500, 400);
861 builder.Scale(3, 3);
862
863 // Draw 3 circles to a subpass and blend it in.
864 DlPaint save_paint;
865 save_paint.setColor(DlColor::kWhite().withAlpha(src_alpha * 255));
866 save_paint.setBlendMode(static_cast<DlBlendMode>(
867 blend_modes.blend_mode_values[current_blend_index]));
868 builder.SaveLayer(std::nullopt, &save_paint);
869 {
870 DlPaint paint;
871 paint.setBlendMode(DlBlendMode::kPlus);
872 const Scalar x = std::sin(k2Pi / 3);
873 const Scalar y = -std::cos(k2Pi / 3);
874 paint.setColor(color0);
875 builder.DrawCircle(DlPoint(-x * 45, y * 45), 65, paint);
876 paint.setColor(color1);
877 builder.DrawCircle(DlPoint(0, -45), 65, paint);
878 paint.setColor(color2);
879 builder.DrawCircle(DlPoint(x * 45, y * 45), 65, paint);
880 }
881 builder.Restore();
882
883 return builder.Build();
884 };
885
886 ASSERT_TRUE(OpenPlaygroundHere(callback));
887 }
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() [148/525]

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

Definition at line 1145 of file aiks_dl_basic_unittests.cc.

1145 {
1146 DisplayListBuilder builder;
1147
1148 // Render a texture directly.
1149 {
1150 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1151
1152 builder.Save();
1153 builder.Translate(100, 200);
1154 builder.Scale(0.5, 0.5);
1155 builder.DrawImage(image, DlPoint(100.0, 100.0),
1156 DlImageSampling::kNearestNeighbor);
1157 builder.Restore();
1158 }
1159
1160 // Render an offscreen rendered texture.
1161 {
1162 DlPaint alpha;
1163 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1164
1165 builder.SaveLayer(std::nullopt, &alpha);
1166
1167 DlPaint paint;
1168 paint.setColor(DlColor::kRed());
1169 builder.DrawRect(DlRect::MakeXYWH(000, 000, 100, 100), paint);
1170 paint.setColor(DlColor::kGreen());
1171 builder.DrawRect(DlRect::MakeXYWH(020, 020, 100, 100), paint);
1172 paint.setColor(DlColor::kBlue());
1173 builder.DrawRect(DlRect::MakeXYWH(040, 040, 100, 100), paint);
1174
1175 builder.Restore();
1176 }
1177
1178 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1179 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [149/525]

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

Definition at line 1326 of file aiks_dl_basic_unittests.cc.

1326 {
1327 auto callback = [&]() -> sk_sp<DisplayList> {
1328 DisplayListBuilder builder;
1329 builder.Scale(GetContentScale().x, GetContentScale().y);
1330
1331 DlPaint alpha;
1332 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
1333
1334 auto current = Point{25, 25};
1335 const auto offset = Point{25, 25};
1336 const auto size = Size(100, 100);
1337
1338 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1339 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1340 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1341 DlRect bounds = DlRect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1342
1343 DlPaint stroke_paint;
1344 stroke_paint.setColor(DlColor::kYellow());
1345 stroke_paint.setStrokeWidth(5);
1346 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
1347 builder.DrawRect(bounds, stroke_paint);
1348
1349 builder.SaveLayer(bounds, &alpha);
1350
1351 DlPaint paint;
1352 paint.setColor(DlColor::kRed());
1353 builder.DrawRect(
1354 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1355
1356 paint.setColor(DlColor::kGreen());
1357 current += offset;
1358 builder.DrawRect(
1359 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1360
1361 paint.setColor(DlColor::kBlue());
1362 current += offset;
1363 builder.DrawRect(
1364 DlRect::MakeXYWH(current.x, current.y, size.width, size.height), paint);
1365
1366 builder.Restore();
1367
1368 return builder.Build();
1369 };
1370
1371 ASSERT_TRUE(OpenPlaygroundHere(callback));
1372 }

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

## ◆ TEST_P() [150/525]

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 }

## ◆ TEST_P() [151/525]

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 }

## ◆ TEST_P() [152/525]

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

Definition at line 889 of file aiks_dl_blend_unittests.cc.

889 {
890 DisplayListBuilder builder;
891
892 DlPaint paint;
893 paint.setColor(DlColor::kBlue());
894 builder.DrawPaint(paint);
895
896 DlPaint save_paint;
897 save_paint.setColorFilter(
898 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kSrc));
899 builder.SaveLayer(std::nullopt, &save_paint);
900 builder.Restore();
901
902 // Should be solid red as the destructive color filter floods the clip.
903 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
904 }

## ◆ TEST_P() [153/525]

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

Definition at line 630 of file aiks_dl_text_unittests.cc.

630 {
631 DisplayListBuilder builder;
632
633 DlPaint paint;
634 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
635 paint.setColor(clear_color);
636 builder.DrawPaint(paint);
637
638 DlMatrix identity = {
639 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
640 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
641 };
642 builder.Save();
643 builder.Transform(identity);
644
645 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
646 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
647 paint.setColor(white);
648 builder.DrawRect(frame, paint);
649
650 builder.Save();
651 builder.ClipRect(frame, DlClipOp::kIntersect);
652
653 DlMatrix rect_xform = {
654 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
655 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
656 };
657 builder.Save();
658 builder.Transform(rect_xform);
659
660 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
661 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
662 paint.setColor(bluish);
663 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
664 builder.DrawRoundRect(rrect, paint);
665
666 builder.Save();
667 builder.ClipRect(rect, DlClipOp::kIntersect);
668 builder.Restore();
669
670 builder.Restore();
671
672 DlMatrix path_xform = {
673 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
674 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
675 };
676 builder.Save();
677 builder.Transform(path_xform);
678
679 DlPathBuilder path_builder;
680 path_builder.MoveTo(DlPoint(87.5, 349.5));
681 path_builder.LineTo(DlPoint(25.0, 29.5));
682 path_builder.LineTo(DlPoint(150.0, 118.0));
683 path_builder.LineTo(DlPoint(25.0, 118.0));
684 path_builder.LineTo(DlPoint(150.0, 29.5));
685 path_builder.Close();
686 DlPath path(path_builder);
687
688 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
689 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
690 paint.setColor(fill_color);
691 paint.setDrawStyle(DlDrawStyle::kFill);
692 builder.DrawPath(path, paint);
693
694 paint.setColor(stroke_color);
695 paint.setStrokeWidth(2.0);
696 paint.setDrawStyle(DlDrawStyle::kStroke);
697 builder.DrawPath(path, paint);
698
699 builder.Restore();
700 builder.Restore();
701 builder.Restore();
702
703 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
704 }

## ◆ TEST_P() [154/525]

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

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

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

Definition at line 1125 of file aiks_dl_unittests.cc.

1125 {
1126 if (GetBackend() != PlaygroundBackend::kOpenGLES) {
1127 GTEST_SKIP() << "Only relevant for GLES";
1128 }
1129 DisplayListBuilder builder;
1130
1131 std::shared_ptr<DlImageFilter> filter =
1132 DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
1133 builder.SaveLayer(std::nullopt, nullptr, filter.get());
1134 builder.Restore();
1135
1136 AiksContext aiks_context(GetContext(), nullptr);
1137 // Use intentionally invalid dimensions that would trigger an allocation
1138 // failure.
1139 auto texture =
1140 DisplayListToTexture(builder.Build(), ISize{10, 10}, aiks_context,
1141 /*reset_host_buffer=*/true, /*generate_mips=*/true);
1142
1143 EXPECT_FALSE(texture->NeedsMipmapGeneration());
1144 }

References impeller::DisplayListToTexture(), and impeller::kOpenGLES.

## ◆ TEST_P() [157/525]

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

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

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

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

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

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

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

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

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

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

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

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

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

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->dimensions().fWidth * 0.25f, image->dimensions().fHeight * 0.4f,
236 image->dimensions().fWidth, image->dimensions().fHeight);
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() [171/525]

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

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

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

Definition at line 549 of file aiks_dl_path_unittests.cc.

549 {
550 DisplayListBuilder builder;
551 builder.Scale(GetContentScale().x, GetContentScale().y);
552
553 DlPaint paint;
554 paint.setColor(DlColor::kBlue());
555 paint.setStrokeWidth(10);
556
557 auto draw = [&builder](DlPaint& paint) {
558 for (auto cap :
559 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
560 paint.setStrokeCap(cap);
561 DlPoint origin = {100, 100};
562 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
563 for (int d = 15; d < 90; d += 15) {
564 Matrix m = Matrix::MakeRotationZ(Degrees(d));
565 Point origin = {100, 100};
566 Point p0 = {50, 0};
567 Point p1 = {150, 0};
568 auto a = origin + m * p0;
569 auto b = origin + m * p1;
570
571 builder.DrawLine(a, b, paint);
572 }
573 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
574 builder.DrawCircle(origin, 35, paint);
575
576 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
577
578 builder.Translate(250, 0);
579 }
580 builder.Translate(-750, 250);
581 };
582
583 std::vector<DlColor> colors = {
584 DlColor::ARGB(1, 0x1f / 255.0, 0.0, 0x5c / 255.0),
585 DlColor::ARGB(1, 0x5b / 255.0, 0.0, 0x60 / 255.0),
586 DlColor::ARGB(1, 0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0),
587 DlColor::ARGB(1, 0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0),
588 DlColor::ARGB(1, 0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0),
589 DlColor::ARGB(1, 0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0),
590 DlColor::ARGB(1, 0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0)};
591 std::vector<Scalar> stops = {
592 0.0,
593 (1.0 / 6.0) * 1,
594 (1.0 / 6.0) * 2,
595 (1.0 / 6.0) * 3,
596 (1.0 / 6.0) * 4,
597 (1.0 / 6.0) * 5,
598 1.0,
599 };
600
601 auto texture = DlImageImpeller::Make(
602 CreateTextureForFixture("airplane.jpg",
603 /*enable_mipmapping=*/true));
604
605 draw(paint);
606
607 paint.setColorSource(DlColorSource::MakeRadial({100, 100}, 200, stops.size(),
608 colors.data(), stops.data(),
609 DlTileMode::kMirror));
610 draw(paint);
611
612 DlMatrix matrix = DlMatrix::MakeTranslation({-150, 75});
613 paint.setColorSource(DlColorSource::MakeImage(
614 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
615 DlImageSampling::kMipmapLinear, &matrix));
616 draw(paint);
617
618 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
619 }

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

## ◆ TEST_P() [174/525]

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

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

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

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

Definition at line 780 of file aiks_dl_path_unittests.cc.

780 {
781 DisplayListBuilder builder;
782 DlPaint paint;
783 paint.setColor(DlColor::kRed());
784 paint.setDrawStyle(DlDrawStyle::kStroke);
785 paint.setStrokeWidth(10);
786
787 builder.Translate(100, 100);
788 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
789
790 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
791 }

## ◆ TEST_P() [178/525]

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

Definition at line 793 of file aiks_dl_path_unittests.cc.

793 {
794 DisplayListBuilder builder;
795 DlPaint paint;
796 paint.setColor(DlColor::kRed());
797 paint.setDrawStyle(DlDrawStyle::kStroke);
798 paint.setStrokeWidth(10);
799 paint.setStrokeJoin(DlStrokeJoin::kBevel);
800
801 builder.Translate(100, 100);
802 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
803
804 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
805 }

## ◆ TEST_P() [179/525]

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

Definition at line 506 of file aiks_dl_text_unittests.cc.

506 {
507 DisplayListBuilder builder;
508
509 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
510 0.0, 1.0, 0.0, 0.0, //
511 0.0, 0.0, 1.0, 0.01, //
512 0.0, 0.0, 0.0, 1.0) * //
513 Matrix::MakeRotationY({Degrees{10}});
514
515 builder.Transform(matrix);
516
517 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
518 "Roboto-Regular.ttf"));
519 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
520 }

References RenderTextInCanvasSkia(), and impeller::Matrix::Transform().

## ◆ TEST_P() [180/525]

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

Definition at line 522 of file aiks_dl_text_unittests.cc.

522 {
523 DisplayListBuilder builder;
524
525 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
526 0.0, 1.0, 0.0, 0.0, //
527 0.0, 0.0, 1.0, 0.01, //
528 0.0, 0.0, 0.0, 1.0) * //
529 Matrix::MakeRotationY({Degrees{10}});
530
531 DlPaint save_paint;
532 DlRect window_bounds =
533 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
534 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
535 builder.SaveLayer(window_bounds, &save_paint);
536 builder.Transform(matrix);
537
538 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
539 "Roboto-Regular.ttf"));
540
541 builder.Restore();
542 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
543 }

References RenderTextInCanvasSkia().

## ◆ TEST_P() [181/525]

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

Definition at line 270 of file aiks_dl_vertices_unittests.cc.

270 {
271 auto texture = CreateTextureForFixture("embarcadero.jpg");
272 auto dl_image = DlImageImpeller::Make(texture);
273 std::vector<DlPoint> positions = {
274 DlPoint(100, 300),
275 DlPoint(200, 100),
276 DlPoint(300, 300),
277 };
278 std::vector<DlPoint> texture_coordinates = {
279 DlPoint(0, 0),
280 DlPoint(100, 200),
281 DlPoint(200, 100),
282 };
283
284 auto vertices = flutter::DlVertices::Make(
285 flutter::DlVertexMode::kTriangles, 3, positions.data(),
286 texture_coordinates.data(), /*colors=*/nullptr);
287
288 flutter::DisplayListBuilder builder;
289 flutter::DlPaint paint;
290
291 auto image_source = flutter::DlColorSource::MakeImage(
292 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
293
294 paint.setColorSource(image_source);
295 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
296
297 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
298 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [182/525]

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

Definition at line 300 of file aiks_dl_vertices_unittests.cc.

301 {
302 auto texture = CreateTextureForFixture("embarcadero.jpg");
303 auto dl_image = DlImageImpeller::Make(texture);
304 std::vector<DlPoint> positions = {
305 DlPoint(100, 300),
306 DlPoint(200, 100),
307 DlPoint(300, 300),
308 };
309 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
310 flutter::DlColor::kGreen(),
311 flutter::DlColor::kWhite()};
312 std::vector<DlPoint> texture_coordinates = {
313 DlPoint(0, 0),
314 DlPoint(100, 200),
315 DlPoint(200, 100),
316 };
317
318 auto vertices = flutter::DlVertices::Make(
319 flutter::DlVertexMode::kTriangles, 3, positions.data(),
320 texture_coordinates.data(), colors.data());
321
322 flutter::DisplayListBuilder builder;
323 flutter::DlPaint paint;
324
325 auto image_source = flutter::DlColorSource::MakeImage(
326 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
327
328 paint.setColorSource(image_source);
329 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
330
331 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
332 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [183/525]

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

Definition at line 283 of file canvas_unittests.cc.

283 {
284 RenderCallback callback = [&](RenderTarget& render_target) {
285 ContentContext context(GetContext(), nullptr);
286 Canvas canvas(context, render_target, true, false);
287
288 std::vector<flutter::DlPoint> vertex_coordinates = {
289 flutter::DlPoint(0, 0),
290 flutter::DlPoint(600, 0),
291 flutter::DlPoint(0, 600),
292 };
293 std::vector<flutter::DlPoint> texture_coordinates = {
294 flutter::DlPoint(0, 0),
295 flutter::DlPoint(500, 0),
296 flutter::DlPoint(0, 500),
297 };
298 std::vector<uint16_t> indices = {0, 1, 2};
299 flutter::DlVertices::Builder vertices_builder(
300 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
301 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
302 vertices_builder.store_vertices(vertex_coordinates.data());
303 vertices_builder.store_indices(indices.data());
304 vertices_builder.store_texture_coordinates(texture_coordinates.data());
305 auto vertices = vertices_builder.build();
306
307 // The start and end points of the gradient form an empty rectangle.
308 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
309 flutter::DlColor::kRed()};
310 std::vector<Scalar> stops = {0.0, 1.0};
311 auto gradient = flutter::DlColorSource::MakeLinear(
312 {0, 0}, {0, 600}, 2, colors.data(), stops.data(),
313 flutter::DlTileMode::kClamp);
314
315 Paint paint;
316 paint.color_source = gradient.get();
317 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
318 BlendMode::kSrcOver, paint);
319
320 canvas.EndReplay();
321 return true;
322 };
323
324 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
325 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, and impeller::Playground::OpenPlaygroundHere().

## ◆ TEST_P() [184/525]

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

Definition at line 209 of file aiks_dl_vertices_unittests.cc.

209 {
210 std::vector<DlPoint> positions = {
211 DlPoint(100, 300),
212 DlPoint(200, 100),
213 DlPoint(300, 300),
214 };
215
216 auto vertices = flutter::DlVertices::Make(
217 flutter::DlVertexMode::kTriangles, 3, positions.data(),
218 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
219
220 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
221 flutter::DlColor::kRed()};
222 const float stops[2] = {0.0, 1.0};
223
224 auto linear = flutter::DlColorSource::MakeLinear(
225 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
226 flutter::DlTileMode::kRepeat);
227
228 flutter::DisplayListBuilder builder;
229 flutter::DlPaint paint;
230
231 paint.setColorSource(linear);
232 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
233
234 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
235 }

## ◆ TEST_P() [185/525]

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

Definition at line 237 of file aiks_dl_vertices_unittests.cc.

237 {
238 std::vector<DlPoint> positions = {
239 DlPoint(100, 300),
240 DlPoint(200, 100),
241 DlPoint(300, 300),
242 };
243 std::vector<DlPoint> texture_coordinates = {
244 DlPoint(300, 100),
245 DlPoint(100, 200),
246 DlPoint(300, 300),
247 };
248
249 auto vertices = flutter::DlVertices::Make(
250 flutter::DlVertexMode::kTriangles, 3, positions.data(),
251 texture_coordinates.data(), /*colors=*/nullptr);
252
253 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
254 flutter::DlColor::kRed()};
255 const float stops[2] = {0.0, 1.0};
256
257 auto linear = flutter::DlColorSource::MakeLinear(
258 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
259 flutter::DlTileMode::kRepeat);
260
261 flutter::DisplayListBuilder builder;
262 flutter::DlPaint paint;
263
264 paint.setColorSource(linear);
265 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
266
267 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
268 }

## ◆ TEST_P() [186/525]

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

Definition at line 357 of file aiks_dl_vertices_unittests.cc.

357 {
358 std::vector<DlPoint> positions = {
359 DlPoint(100, 300),
360 DlPoint(200, 100),
361 DlPoint(300, 300),
362 DlPoint(200, 500),
363 };
364 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
365 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
366 std::vector<flutter::DlColor> colors = {color, color, color, color};
367
368 auto vertices = flutter::DlVertices::Make(
369 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
370 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
371 indices.data());
372
373 flutter::DisplayListBuilder builder;
374 flutter::DlPaint paint;
375 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
376 paint.setColor(flutter::DlColor::kRed());
377
378 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
379 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
380
381 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
382 }

## ◆ TEST_P() [187/525]

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

Definition at line 334 of file aiks_dl_vertices_unittests.cc.

334 {
335 std::vector<DlPoint> positions = {
336 DlPoint(100, 300),
337 DlPoint(200, 100),
338 DlPoint(300, 300),
339 DlPoint(200, 500),
340 };
341 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
342
343 auto vertices = flutter::DlVertices::Make(
344 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
345 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
346 indices.data());
347
348 flutter::DisplayListBuilder builder;
349 flutter::DlPaint paint;
350
351 paint.setColor(flutter::DlColor::kRed());
352 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
353
354 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
355 }

## ◆ TEST_P() [188/525]

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

Definition at line 183 of file aiks_dl_vertices_unittests.cc.

183 {
184 // Use negative coordinates and then scale the transform by -1, -1 to make
185 // sure coverage is taking the transform into account.
186 std::vector<DlPoint> positions = {
187 DlPoint(-100, -300),
188 DlPoint(-200, -100),
189 DlPoint(-300, -300),
190 };
191 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
192 flutter::DlColor::kGreen(),
193 flutter::DlColor::kWhite()};
194
195 auto vertices = flutter::DlVertices::Make(
196 flutter::DlVertexMode::kTriangles, 3, positions.data(),
197 /*texture_coordinates=*/nullptr, colors.data());
198
199 flutter::DisplayListBuilder builder;
200 flutter::DlPaint paint;
201
202 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
203 builder.Scale(-1, -1);
204 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
205
206 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
207 }

## ◆ TEST_P() [189/525]

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

Definition at line 416 of file aiks_dl_vertices_unittests.cc.

416 {
417 std::vector<DlPoint> positions_lt = {
418 DlPoint(0, 0), //
419 DlPoint(50, 0), //
420 DlPoint(0, 50), //
421 DlPoint(50, 50), //
422 };
423
424 auto vertices_lt = flutter::DlVertices::Make(
425 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
426 positions_lt.data(),
427 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
428 /*index_count=*/0,
429 /*indices=*/nullptr);
430
431 std::vector<DlPoint> positions_rt = {
432 DlPoint(50, 0), //
433 DlPoint(100, 0), //
434 DlPoint(50, 50), //
435 DlPoint(100, 50), //
436 };
437
438 auto vertices_rt = flutter::DlVertices::Make(
439 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
440 positions_rt.data(),
441 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
442 /*index_count=*/0,
443 /*indices=*/nullptr);
444
445 std::vector<DlPoint> positions_lb = {
446 DlPoint(0, 50), //
447 DlPoint(50, 50), //
448 DlPoint(0, 100), //
449 DlPoint(50, 100), //
450 };
451
452 auto vertices_lb = flutter::DlVertices::Make(
453 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
454 positions_lb.data(),
455 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
456 /*index_count=*/0,
457 /*indices=*/nullptr);
458
459 std::vector<DlPoint> positions_rb = {
460 DlPoint(50, 50), //
461 DlPoint(100, 50), //
462 DlPoint(50, 100), //
463 DlPoint(100, 100), //
464 };
465
466 auto vertices_rb = flutter::DlVertices::Make(
467 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
468 positions_rb.data(),
469 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
470 /*index_count=*/0,
471 /*indices=*/nullptr);
472
473 flutter::DisplayListBuilder builder;
474 flutter::DlPaint paint;
475 flutter::DlPaint rect_paint;
476 rect_paint.setColor(DlColor::kBlue());
477
478 auto runtime_stages =
479 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
480
481 auto runtime_stage =
482 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
483 ASSERT_TRUE(runtime_stage);
484
485 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
486 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
487 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
488 runtime_effect, {}, uniform_data);
489
490 paint.setColorSource(color_source);
491
492 builder.Scale(GetContentScale().x, GetContentScale().y);
493 builder.Save();
494 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), rect_paint);
495 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
496 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
497 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
498 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
499 builder.Restore();
500
501 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
502 }

References impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [190/525]

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

Definition at line 506 of file aiks_dl_vertices_unittests.cc.

507 {
508 std::vector<DlPoint> positions_lt = {
509 DlPoint(200, 200), //
510 DlPoint(250, 200), //
511 DlPoint(200, 250), //
512 DlPoint(250, 250), //
513 };
514
515 auto vertices = flutter::DlVertices::Make(
516 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
517 positions_lt.data(),
518 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
519 /*index_count=*/0,
520 /*indices=*/nullptr);
521
522 flutter::DisplayListBuilder builder;
523 flutter::DlPaint paint;
524 flutter::DlPaint rect_paint;
525 rect_paint.setColor(DlColor::kBlue());
526
527 auto runtime_stages =
528 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
529
530 auto runtime_stage =
531 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
532 ASSERT_TRUE(runtime_stage);
533
534 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
535 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
536
537 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
538 uniform_data->resize(rect_data.size() * sizeof(Rect));
539 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
540
541 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
542 runtime_effect, {}, uniform_data);
543
544 paint.setColorSource(color_source);
545
546 builder.Scale(GetContentScale().x, GetContentScale().y);
547 builder.DrawRect(DlRect::MakeLTRB(200, 200, 250, 250), rect_paint);
548 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
549
550 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
551 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::PlaygroundBackendToRuntimeStageBackend(), and x.

## ◆ TEST_P() [191/525]

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

Definition at line 327 of file canvas_unittests.cc.

327 {
328 auto runtime_stages =
329 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
330
331 auto runtime_stage =
332 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
333 ASSERT_TRUE(runtime_stage);
334
335 auto runtime_effect = flutter::DlRuntimeEffect::MakeImpeller(runtime_stage);
336 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
337 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
338 runtime_effect, {}, uniform_data);
339
340 RenderCallback callback = [&](RenderTarget& render_target) {
341 ContentContext context(GetContext(), nullptr);
342 Canvas canvas(context, render_target, true, false);
343
344 std::vector<flutter::DlPoint> vertex_coordinates = {
345 flutter::DlPoint(100, 100),
346 flutter::DlPoint(300, 100),
347 flutter::DlPoint(100, 300),
348 };
349 // The bounding box of the texture coordinates is empty.
350 std::vector<flutter::DlPoint> texture_coordinates = {
351 flutter::DlPoint(0, 0),
352 flutter::DlPoint(0, 100),
353 flutter::DlPoint(0, 0),
354 };
355 std::vector<uint16_t> indices = {0, 1, 2};
356 flutter::DlVertices::Builder vertices_builder(
357 flutter::DlVertexMode::kTriangleStrip, vertex_coordinates.size(),
358 flutter::DlVertices::Builder::kHasTextureCoordinates, indices.size());
359 vertices_builder.store_vertices(vertex_coordinates.data());
360 vertices_builder.store_indices(indices.data());
361 vertices_builder.store_texture_coordinates(texture_coordinates.data());
362 auto vertices = vertices_builder.build();
363
364 Paint paint;
365 paint.color_source = color_source.get();
366 canvas.DrawVertices(std::make_shared<DlVerticesGeometry>(vertices, context),
367 BlendMode::kSrcOver, paint);
368
369 canvas.EndReplay();
370 return true;
371 };
372
373 ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
374 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), impeller::Canvas::EndReplay(), impeller::kSrcOver, impeller::Playground::OpenPlaygroundHere(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [192/525]

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

Definition at line 384 of file aiks_dl_vertices_unittests.cc.

384 {
385 std::vector<DlPoint> positions = {
386 DlPoint(100, 300),
387 DlPoint(200, 100),
388 DlPoint(300, 300),
389 DlPoint(200, 500),
390 };
391 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3, 99, 100, 101};
392
393 auto vertices = flutter::DlVertices::Make(
394 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
395 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
396 indices.data());
397
398 EXPECT_EQ(vertices->GetBounds(), DlRect::MakeLTRB(100, 100, 300, 500));
399
400 flutter::DisplayListBuilder builder;
401 flutter::DlPaint paint;
402 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
403 paint.setColor(flutter::DlColor::kRed());
404
405 builder.DrawRect(DlRect::MakeLTRB(0, 0, 400, 400), paint);
406 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrc, paint);
407
408 AiksContext renderer(GetContext(), nullptr);
409 std::shared_ptr<Texture> image =
410 DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
411 EXPECT_TRUE(image);
412 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [193/525]

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

Definition at line 1073 of file aiks_dl_basic_unittests.cc.

1073 {
1074 DisplayListBuilder builder;
1075 builder.Scale(GetContentScale().x, GetContentScale().y);
1076
1077 DlPaint paint;
1078 paint.setColor(DlColor::kRed());
1079 builder.DrawPaint(paint);
1080 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1081 paint.setColor(DlColor::kBlue());
1082 builder.SaveLayer(std::nullopt, &paint);
1083 builder.Restore();
1084
1085 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1086 }

References x.

## ◆ TEST_P() [194/525]

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

Definition at line 1088 of file aiks_dl_basic_unittests.cc.

1088 {
1089 DisplayListBuilder builder;
1090 builder.Scale(GetContentScale().x, GetContentScale().y);
1091 auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
1092 builder.DrawImage(image, DlPoint(10, 10), {});
1093 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1094
1095 DlPaint paint;
1096 paint.setBlendMode(DlBlendMode::kClear);
1097 builder.SaveLayer(std::nullopt, &paint);
1098 builder.Restore();
1099
1100 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1101 }

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

## ◆ TEST_P() [195/525]

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

Definition at line 1490 of file aiks_dl_basic_unittests.cc.

1490 {
1491 DisplayListBuilder builder;
1492
1493 builder.Scale(GetContentScale().x, GetContentScale().y);
1494 DlPaint paint;
1495 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1496
1497 DlPaint save_paint;
1498 save_paint.setColor(DlColor::kWhite());
1499 builder.DrawPaint(save_paint);
1500
1501 paint.setColor(DlColor::kBlue());
1502 for (int i = 0; i < 5; i++) {
1503 Scalar y = i * 125;
1504 Scalar y_radius = i * 15;
1505 for (int j = 0; j < 5; j++) {
1506 Scalar x = j * 125;
1507 Scalar x_radius = j * 15;
1508 builder.DrawRoundRect(
1509 DlRoundRect::MakeRectXY(
1510 DlRect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f), //
1511 x_radius, y_radius),
1512 paint);
1513 }
1514 }
1515
1516 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1517 }

References x.

## ◆ TEST_P() [196/525]

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

Definition at line 824 of file aiks_dl_gradient_unittests.cc.

824 {
825 DisplayListBuilder builder;
826 DlPaint paint;
827 builder.Translate(100.0f, 0);
828
829 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
830 DlColor::kGreen()};
831 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
832
833 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
834 colors.data(), stops.data(),
835 DlTileMode::kClamp));
836
837 paint.setColor(DlColor::kWhite());
838 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
839 builder.Translate(400, 0);
840 builder.DrawRoundRect(
841 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
842
843 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
844 }

## ◆ TEST_P() [197/525]

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

Definition at line 870 of file aiks_dl_gradient_unittests.cc.

870 {
871 DisplayListBuilder builder;
872 DlPaint paint;
873 builder.Translate(100.0f, 0);
874
875 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
876 DlColor::kGreen()};
877 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
878
879 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
880 colors.data(), stops.data(),
881 DlTileMode::kClamp));
882
883 paint.setColor(DlColor::kWhite());
884 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
885 builder.Translate(400, 0);
886 builder.DrawRoundRect(
887 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
888
889 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
890 }

## ◆ TEST_P() [198/525]

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

Definition at line 847 of file aiks_dl_gradient_unittests.cc.

847 {
848 DisplayListBuilder builder;
849 DlPaint paint;
850 builder.Translate(100.0f, 0);
851
852 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
853 DlColor::kGreen()};
854 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
855
856 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
857 colors.data(), stops.data(),
858 DlTileMode::kClamp));
859
860 paint.setColor(DlColor::kWhite());
861 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
862 builder.Translate(400, 0);
863 builder.DrawRoundRect(
864 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
865
866 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
867 }

## ◆ TEST_P() [199/525]

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

Definition at line 893 of file aiks_dl_gradient_unittests.cc.

893 {
894 DisplayListBuilder builder;
895 DlPaint paint;
896 builder.Translate(100.0f, 0);
897
898 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
899 DlColor::kGreen()};
900 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
901
902 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
903 colors.data(), stops.data(),
904 DlTileMode::kClamp));
905
906 paint.setColor(DlColor::kWhite());
907 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
908 builder.Translate(400, 0);
909 builder.DrawRoundRect(
910 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
911
912 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
913 }

## ◆ TEST_P() [200/525]

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

Definition at line 871 of file aiks_dl_path_unittests.cc.

871 {
872 DlScalar stroke_width = 300;
873 DlScalar aspect = 1.0;
874 DlScalar start_angle = 0;
875 DlScalar end_angle = 90;
876 auto callback = [&]() -> sk_sp<DisplayList> {
877 if (AiksTest::ImGuiBegin("Controls", nullptr,
878 ImGuiWindowFlags_AlwaysAutoResize)) {
879 ImGui::SliderFloat("Stroke Width", &stroke_width, 1, 300);
880 ImGui::SliderFloat("Aspect", &aspect, 0.5, 2.0);
881 ImGui::SliderFloat("Start Angle", &start_angle, 0, 360);
882 ImGui::SliderFloat("End Angle", &end_angle, 0, 360);
883 ImGui::End();
884 }
885
886 DisplayListBuilder builder;
887 DlPaint grey_paint;
888 grey_paint.setColor(DlColor(0xff111111));
889 builder.DrawPaint(grey_paint);
890
891 DlPaint white_paint;
892 white_paint.setColor(DlColor::kWhite());
893 white_paint.setStrokeWidth(stroke_width);
894 white_paint.setDrawStyle(DlDrawStyle::kStroke);
895 DlPaint red_paint;
896 red_paint.setColor(DlColor::kRed());
897
898 Rect rect = Rect::MakeXYWH(100, 100, 100, aspect * 100);
899 builder.DrawRect(rect, red_paint);
900 builder.DrawArc(rect, start_angle, end_angle,
901 /*useCenter=*/false, white_paint);
902 DlScalar frontier = rect.GetRight() + stroke_width / 2.0;
903 builder.DrawLine(Point(frontier, 0), Point(frontier, 150), red_paint);
904
905 return builder.Build();
906 };
907 ASSERT_TRUE(OpenPlaygroundHere(callback));
908 }
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:315

References impeller::TRect< T >::GetRight(), impeller::AiksPlayground::ImGuiBegin(), impeller::TRect< Scalar >::MakeXYWH(), and stroke_width.

## ◆ TEST_P() [201/525]

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

Definition at line 427 of file aiks_dl_basic_unittests.cc.

427 {
428 DisplayListBuilder builder;
429 builder.Scale(GetContentScale().x, GetContentScale().y);
430 DlPaint paint;
431 const int color_count = 3;
432 DlColor colors[color_count] = {
433 DlColor::kBlue(),
434 DlColor::kGreen(),
435 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
436 };
437
438 paint.setColor(DlColor::kWhite());
439 builder.DrawPaint(paint);
440
441 int c_index = 0;
442 int radius = 600;
443 while (radius > 0) {
444 paint.setColor(colors[(c_index++) % color_count]);
445 builder.DrawCircle(DlPoint(10, 10), radius, paint);
446 if (radius > 30) {
447 radius -= 10;
448 } else {
449 radius -= 2;
450 }
451 }
452
453 DlColor gradient_colors[7] = {
454 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
455 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
456 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
457 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
458 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
459 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
460 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
461 };
462 DlScalar stops[7] = {
463 0.0,
464 (1.0 / 6.0) * 1,
465 (1.0 / 6.0) * 2,
466 (1.0 / 6.0) * 3,
467 (1.0 / 6.0) * 4,
468 (1.0 / 6.0) * 5,
469 1.0,
470 };
471 auto texture = CreateTextureForFixture("airplane.jpg",
472 /*enable_mipmapping=*/true);
473 auto image = DlImageImpeller::Make(texture);
474
475 paint.setColorSource(DlColorSource::MakeRadial(
476 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
477 builder.DrawCircle(DlPoint(500, 600), 100, paint);
478
479 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
480 paint.setColorSource(DlColorSource::MakeImage(
481 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
482 DlImageSampling::kNearestNeighbor, &local_matrix));
483 builder.DrawCircle(DlPoint(800, 300), 100, paint);
484
485 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
486 }

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

## ◆ TEST_P() [202/525]

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

Definition at line 554 of file aiks_dl_basic_unittests.cc.

554 {
555 DisplayListBuilder builder;
556 builder.Scale(GetContentScale().x, GetContentScale().y);
557 DlPaint paint;
558 const int color_count = 3;
559 DlColor colors[color_count] = {
560 DlColor::kBlue(),
561 DlColor::kGreen(),
562 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
563 };
564
565 paint.setColor(DlColor::kWhite());
566 builder.DrawPaint(paint);
567
568 int c_index = 0;
569 int long_radius = 600;
570 int short_radius = 600;
571 while (long_radius > 0 && short_radius > 0) {
572 paint.setColor(colors[(c_index++) % color_count]);
573 builder.DrawOval(DlRect::MakeXYWH(10 - long_radius, 10 - short_radius,
574 long_radius * 2, short_radius * 2),
575 paint);
576 builder.DrawOval(DlRect::MakeXYWH(1000 - short_radius, 750 - long_radius,
577 short_radius * 2, long_radius * 2),
578 paint);
579 if (short_radius > 30) {
580 short_radius -= 10;
581 long_radius -= 5;
582 } else {
583 short_radius -= 2;
584 long_radius -= 1;
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.setColor(DlColor::kWhite().modulateOpacity(0.5));
611
612 paint.setColorSource(DlColorSource::MakeRadial(
613 DlPoint(300, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
614 builder.DrawOval(DlRect::MakeXYWH(200, 625, 200, 50), paint);
615 builder.DrawOval(DlRect::MakeXYWH(275, 550, 50, 200), paint);
616
617 DlMatrix local_matrix = DlMatrix::MakeTranslation({610, 15});
618 paint.setColorSource(DlColorSource::MakeImage(
619 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
620 DlImageSampling::kNearestNeighbor, &local_matrix));
621 builder.DrawOval(DlRect::MakeXYWH(610, 90, 200, 50), paint);
622 builder.DrawOval(DlRect::MakeXYWH(685, 15, 50, 200), paint);
623
624 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
625 }

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

## ◆ TEST_P() [203/525]

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

Definition at line 1224 of file aiks_dl_basic_unittests.cc.

1224 {
1225 DisplayListBuilder builder;
1226 builder.Scale(GetContentScale().x, GetContentScale().y);
1227
1228 DlPaint paint;
1229 const int color_count = 3;
1230 DlColor colors[color_count] = {
1231 DlColor::kBlue(),
1232 DlColor::kGreen(),
1233 DlColor::ARGB(1.0, 220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f),
1234 };
1235
1236 paint.setColor(DlColor::kWhite());
1237 builder.DrawPaint(paint);
1238
1239 auto draw_rrect_as_path = [&builder](const DlRect& rect, Scalar x, Scalar y,
1240 const DlPaint& paint) {
1241 builder.DrawPath(DlPath::MakeRoundRectXY(rect, x, y), paint);
1242 };
1243
1244 int c_index = 0;
1245 for (int i = 0; i < 4; i++) {
1246 for (int j = 0; j < 4; j++) {
1247 paint.setColor(colors[(c_index++) % color_count]);
1248 draw_rrect_as_path(DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1249 i * 5 + 10, j * 5 + 10, paint);
1250 }
1251 }
1252 paint.setColor(colors[(c_index++) % color_count]);
1253 draw_rrect_as_path(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40, paint);
1254 paint.setColor(colors[(c_index++) % color_count]);
1255 draw_rrect_as_path(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40, paint);
1256
1257 std::vector<DlColor> gradient_colors = {
1258 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
1259 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
1260 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
1261 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
1262 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
1263 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
1264 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0)};
1265 std::vector<Scalar> stops = {
1266 0.0,
1267 (1.0 / 6.0) * 1,
1268 (1.0 / 6.0) * 2,
1269 (1.0 / 6.0) * 3,
1270 (1.0 / 6.0) * 4,
1271 (1.0 / 6.0) * 5,
1272 1.0,
1273 };
1274 auto texture = DlImageImpeller::Make(
1275 CreateTextureForFixture("airplane.jpg",
1276 /*enable_mipmapping=*/true));
1277
1278 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1279 paint.setColorSource(DlColorSource::MakeRadial(
1280 /*center=*/DlPoint(550, 550),
1281 /*radius=*/75,
1282 /*stop_count=*/gradient_colors.size(),
1283 /*colors=*/gradient_colors.data(),
1284 /*stops=*/stops.data(),
1285 /*tile_mode=*/DlTileMode::kMirror));
1286 for (int i = 1; i <= 10; i++) {
1287 int j = 11 - i;
1288 draw_rrect_as_path(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1289 550 + i * 20, 550 + j * 20),
1290 i * 10, j * 10, paint);
1291 }
1292 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1293 paint.setColorSource(DlColorSource::MakeRadial(
1294 /*center=*/DlPoint(200, 650),
1295 /*radius=*/75,
1296 /*stop_count=*/gradient_colors.size(),
1297 /*colors=*/gradient_colors.data(),
1298 /*stops=*/stops.data(),
1299 /*tile_mode=*/DlTileMode::kMirror));
1300 draw_rrect_as_path(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40, paint);
1301 draw_rrect_as_path(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40, paint);
1302
1303 auto matrix = DlMatrix::MakeTranslation({520, 20});
1304 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
1305 paint.setColorSource(DlColorSource::MakeImage(
1306 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1307 DlImageSampling::kMipmapLinear, &matrix));
1308 for (int i = 1; i <= 10; i++) {
1309 int j = 11 - i;
1310 draw_rrect_as_path(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1311 720 + i * 20, 220 + j * 20),
1312 i * 10, j * 10, paint);
1313 }
1314 matrix = DlMatrix::MakeTranslation({800, 300});
1315 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
1316 paint.setColorSource(DlColorSource::MakeImage(
1317 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
1318 DlImageSampling::kMipmapLinear, &matrix));
1319
1320 draw_rrect_as_path(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40, paint);
1321 draw_rrect_as_path(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40, paint);
1322
1323 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1324 }

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

## ◆ TEST_P() [204/525]

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

Definition at line 627 of file aiks_dl_basic_unittests.cc.

627 {
628 DisplayListBuilder builder;
629 builder.Scale(GetContentScale().x, GetContentScale().y);
630 DlPaint paint;
631 const int color_count = 3;
632 DlColor colors[color_count] = {
633 DlColor::kBlue(),
634 DlColor::kGreen(),
635 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
636 };
637
638 paint.setColor(DlColor::kWhite());
639 builder.DrawPaint(paint);
640
641 int c_index = 0;
642 for (int i = 0; i < 4; i++) {
643 for (int j = 0; j < 4; j++) {
644 paint.setColor(colors[(c_index++) % color_count]);
645 builder.DrawRoundRect(
646 DlRoundRect::MakeRectXY(
647 DlRect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80), //
648 i * 5 + 10, j * 5 + 10),
649 paint);
650 }
651 }
652 paint.setColor(colors[(c_index++) % color_count]);
653 builder.DrawRoundRect(
654 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 420, 380, 80), 40, 40),
655 paint);
656 paint.setColor(colors[(c_index++) % color_count]);
657 builder.DrawRoundRect(
658 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(410, 20, 80, 380), 40, 40),
659 paint);
660
661 DlColor gradient_colors[7] = {
662 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
663 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
664 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
665 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
666 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
667 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
668 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
669 };
670 DlScalar stops[7] = {
671 0.0,
672 (1.0 / 6.0) * 1,
673 (1.0 / 6.0) * 2,
674 (1.0 / 6.0) * 3,
675 (1.0 / 6.0) * 4,
676 (1.0 / 6.0) * 5,
677 1.0,
678 };
679 auto texture = CreateTextureForFixture("airplane.jpg",
680 /*enable_mipmapping=*/true);
681 auto image = DlImageImpeller::Make(texture);
682
683 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
684 paint.setColorSource(DlColorSource::MakeRadial(
685 DlPoint(550, 550), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
686 for (int i = 1; i <= 10; i++) {
687 int j = 11 - i;
688 builder.DrawRoundRect(
689 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(550 - i * 20, 550 - j * 20, //
690 550 + i * 20, 550 + j * 20),
691 i * 10, j * 10),
692 paint);
693 }
694
695 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
696 paint.setColorSource(DlColorSource::MakeRadial(
697 DlPoint(200, 650), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
698 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
699 builder.DrawRoundRect(
700 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(100, 610, 300, 690), 40, 40),
701 paint);
702 builder.DrawRoundRect(
703 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(160, 550, 240, 750), 40, 40),
704 paint);
705
706 paint.setColor(DlColor::kWhite().modulateOpacity(0.1));
707 DlMatrix local_matrix = DlMatrix::MakeTranslation({520, 20});
708 paint.setColorSource(DlColorSource::MakeImage(
709 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
710 DlImageSampling::kNearestNeighbor, &local_matrix));
711 for (int i = 1; i <= 10; i++) {
712 int j = 11 - i;
713 builder.DrawRoundRect(
714 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(720 - i * 20, 220 - j * 20, //
715 720 + i * 20, 220 + j * 20),
716 i * 10, j * 10),
717 paint);
718 }
719
720 paint.setColor(DlColor::kWhite().modulateOpacity(0.5));
721 local_matrix = DlMatrix::MakeTranslation({800, 300});
722 paint.setColorSource(DlColorSource::MakeImage(
723 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
724 DlImageSampling::kNearestNeighbor, &local_matrix));
725 builder.DrawRoundRect(
726 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(800, 410, 1000, 490), 40, 40),
727 paint);
728 builder.DrawRoundRect(
729 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(860, 350, 940, 550), 40, 40),
730 paint);
731
732 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
733 }

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

## ◆ TEST_P() [205/525]

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

Definition at line 731 of file aiks_dl_blend_unittests.cc.

731 {
732 auto texture = CreateTextureForFixture("airplane.jpg",
733 /*enable_mipmapping=*/true);
734
735 DisplayListBuilder builder;
736 builder.Rotate(30);
737
738 DlPaint image_paint;
739 image_paint.setColorFilter(DlColorFilter::MakeBlend(
740 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
741 DlBlendMode::kColorDodge));
742
743 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
744 DlImageSampling::kMipmapLinear, &image_paint);
745
746 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
747 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [206/525]

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

Definition at line 466 of file aiks_dl_blend_unittests.cc.

466 {
467 DisplayListBuilder builder;
468
469 DlPaint save_paint;
470 save_paint.setColorFilter(
471 DlColorFilter::MakeBlend(DlColor::kRed(), DlBlendMode::kColorDodge));
472 builder.SaveLayer(std::nullopt, &save_paint);
473
474 builder.Translate(500, 300);
475 builder.Rotate(120);
476
477 DlPaint paint;
478 paint.setColor(DlColor::kBlue());
479 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
480
481 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
482 }

## ◆ TEST_P() [207/525]

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

Definition at line 713 of file aiks_dl_blend_unittests.cc.

713 {
714 auto texture = CreateTextureForFixture("airplane.jpg",
715 /*enable_mipmapping=*/true);
716
717 DisplayListBuilder builder;
718 builder.Rotate(30);
719
720 DlPaint image_paint;
721 image_paint.setColorFilter(DlColorFilter::MakeBlend(
722 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f),
723 DlBlendMode::kSrcIn));
724
725 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
726 DlImageSampling::kMipmapLinear, &image_paint);
727
728 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
729 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [208/525]

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

Definition at line 1137 of file aiks_dl_basic_unittests.cc.

1137 {
1138 PixelFormat pixel_format =
1139 GetContext()->GetCapabilities()->GetDefaultColorFormat();
1140 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
1141 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
1142 << "pixel format: " << PixelFormatToString(pixel_format);
1143 }
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() [209/525]

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

Definition at line 1132 of file aiks_dl_basic_unittests.cc.

1132 {
1133 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
1134 PixelFormat::kB10G10R10A10XR);
1135 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [210/525]

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

Definition at line 749 of file aiks_dl_blend_unittests.cc.

749 {
750 auto texture = CreateTextureForFixture("airplane.jpg",
751 /*enable_mipmapping=*/true);
752
753 // Draw with an advanced blend that can use FramebufferBlendContents and
754 // verify that the scale transform is correctly applied to the image.
755 DisplayListBuilder builder;
756
757 DlPaint paint;
758 paint.setColor(
759 DlColor::RGBA(169.0f / 255.0f, 169.0f / 255.0f, 169.0f / 255.0f, 1.0f));
760 builder.DrawPaint(paint);
761 builder.Scale(0.4, 0.4);
762
763 DlPaint image_paint;
764 image_paint.setBlendMode(DlBlendMode::kMultiply);
765
766 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(20, 20),
767 DlImageSampling::kMipmapLinear, &image_paint);
768
769 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
770 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [211/525]

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 117 of file aiks_dl_clip_unittests.cc.

117 {
118 DisplayListBuilder builder;
119
120 // Clear the whole canvas with white.
121 DlPaint paint;
122 paint.setColor(DlColor::kWhite());
123 builder.DrawPaint(paint);
124
125 builder.ClipPath(DlPath::MakeCircle(DlPoint(150, 150), 50),
126 DlClipOp::kIntersect);
127
128 // Draw a red rectangle that should not show through the circle clip.
129 paint.setColor(DlColor::kRed());
130 paint.setBlendMode(DlBlendMode::kMultiply);
131 builder.DrawRect(DlRect::MakeXYWH(100, 100, 100, 100), paint);
132
133 // Draw a green circle that shows through the clip.
134 paint.setColor(DlColor::kGreen());
135 paint.setBlendMode(DlBlendMode::kSrcOver);
136 builder.DrawCircle(DlPoint(150, 150), 50, paint);
137
138 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
139 }

## ◆ TEST_P() [212/525]

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

Definition at line 850 of file aiks_dl_blur_unittests.cc.

850 {
851 // This test is for checking out how stable rendering is when content is
852 // translated underneath a blur. Animating under a blur can cause
853 // *shimmering* to happen as a result of pixel alignment.
854 // See also: https://github.com/flutter/flutter/issues/140193
855 auto boston =
856 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
857 ASSERT_TRUE(boston);
858 int64_t count = 0;
859 Scalar sigma = 20.0;
860 Scalar freq = 0.1;
861 Scalar amp = 50.0;
862 auto callback = [&]() -> sk_sp<DisplayList> {
863 if (AiksTest::ImGuiBegin("Controls", nullptr,
864 ImGuiWindowFlags_AlwaysAutoResize)) {
865 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
866 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
867 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
868 ImGui::End();
869 }
870
871 DisplayListBuilder builder;
872 builder.Scale(GetContentScale().x, GetContentScale().y);
873 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
874 builder.DrawImage(DlImageImpeller::Make(boston),
875 DlPoint(1024 / 2 - boston->GetSize().width / 2,
876 (768 / 2 - boston->GetSize().height / 2) + y),
877 DlImageSampling::kMipmapLinear);
878 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
879 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
880 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
881
882 builder.ClipRect(
883 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
884 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
885
886 DlPaint paint;
887 paint.setBlendMode(DlBlendMode::kSrc);
888
889 auto backdrop_filter =
890 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
891 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
892 count += 1;
893 return builder.Build();
894 };
895 ASSERT_TRUE(OpenPlaygroundHere(callback));
896 }

References impeller::DrawPlaygroundLine(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), and x.

## ◆ TEST_P() [213/525]

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

Definition at line 821 of file aiks_dl_blur_unittests.cc.

821 {
822 DisplayListBuilder builder;
823
824 builder.Scale(GetContentScale().x, GetContentScale().y);
825 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
826 builder.DrawImageRect(
827 DlImageImpeller::Make(boston),
828 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
829 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
830 DlImageSampling::kNearestNeighbor);
831
832 DlPaint paint;
833 paint.setColor(DlColor::kMagenta());
834
835 DlRoundRect rrect = DlRoundRect::MakeRectXY(
836 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
837 builder.DrawRoundRect(rrect, paint);
838 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
839
840 DlPaint save_paint;
841 save_paint.setBlendMode(DlBlendMode::kSrc);
842
843 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
844 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
845
846 builder.Restore();
847 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
848 }

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

## ◆ TEST_P() [214/525]

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

Definition at line 793 of file aiks_dl_blur_unittests.cc.

793 {
794 DisplayListBuilder builder;
795
796 DlPaint paint;
797 builder.Scale(GetContentScale().x, GetContentScale().y);
798
799 paint.setColor(DlColor::kLimeGreen());
800 DlRoundRect rrect = DlRoundRect::MakeRectXY(
801 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
802 builder.DrawRoundRect(rrect, paint);
803
804 paint.setColor(DlColor::kMagenta());
805 rrect = DlRoundRect::MakeRectXY(
806 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
807 builder.DrawRoundRect(rrect, paint);
808 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
809
810 DlPaint save_paint;
811 save_paint.setBlendMode(DlBlendMode::kSrc);
812
813 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
814
815 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
816 builder.Restore();
817
818 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
819 }

References x.

## ◆ TEST_P() [215/525]

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

Definition at line 1284 of file aiks_dl_blur_unittests.cc.

1284 {
1285 AiksContext renderer(GetContext(), nullptr);
1286 for (int32_t i = 1; i < 5; ++i) {
1287 DisplayListBuilder builder;
1288
1289 ISize clip_size = ISize(i, i);
1290 builder.Save();
1291 builder.ClipRect(
1292 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1293
1294 DlPaint paint;
1295 paint.setColor(DlColor::kGreen());
1296 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1297 paint.setImageFilter(blur_filter);
1298
1299 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1300 builder.Restore();
1301
1302 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1303 EXPECT_TRUE(image) << " length " << i;
1304 }
1305 }

References impeller::DisplayListToTexture(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

## ◆ TEST_P() [216/525]

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

Definition at line 1096 of file aiks_dl_blur_unittests.cc.

1096 {
1097 DisplayListBuilder builder;
1098
1099 builder.Scale(GetContentScale().x, GetContentScale().y);
1100 builder.Scale(0.5, 0.5);
1101
1102 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1103 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1104
1105 DlPaint paint;
1106 paint.setBlendMode(DlBlendMode::kSrc);
1107
1108 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1109 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1110 builder.Restore();
1111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1112 }

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

## ◆ TEST_P() [217/525]

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

Definition at line 1118 of file aiks_dl_blur_unittests.cc.

1118 {
1119 DisplayListBuilder builder;
1120
1121 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1122 Rect bounds =
1123 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1124
1125 DlPaint paint;
1126 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1127
1128 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1129 Vector2 clip_size = {150, 75};
1130 Vector2 center = Vector2(1024, 768) / 2;
1131 builder.Scale(GetContentScale().x, GetContentScale().y);
1132
1133 auto clip_bounds =
1134 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1135 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1136 clip_bounds.GetRight(),
1137 clip_bounds.GetBottom()));
1138 builder.Translate(center.x, center.y);
1139 builder.Scale(0.6, 0.6);
1140 builder.Rotate(25);
1141
1142 auto dst_rect = bounds.Shift(-image_center);
1143 builder.DrawImageRect(
1144 DlImageImpeller::Make(boston), /*src=*/
1145 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1146 bounds.GetBottom()),
1147 /*dst=*/
1148 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1149 dst_rect.GetRight(), dst_rect.GetBottom()),
1150 DlImageSampling::kMipmapLinear, &paint);
1151
1152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1153 }
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:226

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [218/525]

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

Definition at line 1041 of file aiks_dl_blur_unittests.cc.

1041 {
1042 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1043
1044 auto callback = [&]() -> sk_sp<DisplayList> {
1045 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1046 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1047 DlTileMode::kMirror, DlTileMode::kDecal};
1048
1049 static float rotation = 0;
1050 static float scale = 0.6;
1051 static int selected_tile_mode = 3;
1052
1053 if (AiksTest::ImGuiBegin("Controls", nullptr,
1054 ImGuiWindowFlags_AlwaysAutoResize)) {
1055 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1056 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1057 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1058 sizeof(tile_mode_names) / sizeof(char*));
1059 ImGui::End();
1060 }
1061
1062 DisplayListBuilder builder;
1063 Rect bounds =
1064 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1065 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1066 DlPaint paint;
1067 paint.setImageFilter(
1068 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1069
1070 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1071 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1072 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1073 Vector2 center = Vector2(1024, 768) / 2;
1074
1075 builder.Scale(GetContentScale().x, GetContentScale().y);
1076 builder.ClipRect(
1077 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1078 builder.Translate(center.x, center.y);
1079 builder.Scale(scale, scale);
1080 builder.Rotate(rotation);
1081
1082 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1083 bounds.GetRight(), bounds.GetBottom());
1084 Rect dest = bounds.Shift(-image_center);
1085 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1086 dest.GetRight(), dest.GetBottom());
1087 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1088 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1089 &paint);
1090 return builder.Build();
1091 };
1092
1093 ASSERT_TRUE(OpenPlaygroundHere(callback));
1094 }
impeller::TRect::Shift
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:606

References impeller::DrawPlaygroundLine(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::TPoint< T >::Rotate(), scale, impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [219/525]

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

Definition at line 1155 of file aiks_dl_blur_unittests.cc.

1155 {
1156 auto callback = [&]() -> sk_sp<DisplayList> {
1157 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1158 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1159 DlTileMode::kMirror, DlTileMode::kDecal};
1160
1161 static float rotation = 45;
1162 static float scale = 0.6;
1163 static int selected_tile_mode = 3;
1164
1165 if (AiksTest::ImGuiBegin("Controls", nullptr,
1166 ImGuiWindowFlags_AlwaysAutoResize)) {
1167 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1168 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1169 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1170 sizeof(tile_mode_names) / sizeof(char*));
1171 ImGui::End();
1172 }
1173
1174 DisplayListBuilder builder;
1175
1176 DlPaint paint;
1177 paint.setColor(DlColor::kGreen());
1178 paint.setImageFilter(
1179 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1180
1181 Vector2 center = Vector2(1024, 768) / 2;
1182 builder.Scale(GetContentScale().x, GetContentScale().y);
1183 builder.Translate(center.x, center.y);
1184 builder.Scale(scale, scale);
1185 builder.Rotate(rotation);
1186
1187 DlRoundRect rrect =
1188 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1189 builder.DrawRoundRect(rrect, paint);
1190 return builder.Build();
1191 };
1192
1193 ASSERT_TRUE(OpenPlaygroundHere(callback));
1194 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::TPoint< T >::Rotate(), scale, x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [220/525]

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

Definition at line 1008 of file aiks_dl_blur_unittests.cc.

1008 {
1009 DisplayListBuilder builder;
1010 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1011 Rect bounds =
1012 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1013 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1014
1015 DlPaint paint;
1016 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1017
1018 Vector2 clip_size = {150, 75};
1019 Vector2 center = Vector2(1024, 768) / 2;
1020 builder.Scale(GetContentScale().x, GetContentScale().y);
1021
1022 auto rect =
1023 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1024 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1025 rect.GetRight(), rect.GetBottom()));
1026 builder.Translate(center.x, center.y);
1027 builder.Scale(0.6, 0.6);
1028
1029 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1030 bounds.GetRight(), bounds.GetBottom());
1031 Rect dest = bounds.Shift(-image_center);
1032 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1033 dest.GetRight(), dest.GetBottom());
1034 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1035 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1036 &paint);
1037
1038 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1039 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetTop(), impeller::DlImageImpeller::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Shift(), x, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [221/525]

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

Definition at line 1259 of file aiks_dl_blur_unittests.cc.

1259 {
1260 AiksContext renderer(GetContext(), nullptr);
1261
1262 for (int32_t i = 1; i < 5; ++i) {
1263 DisplayListBuilder builder;
1264 Scalar fi = i;
1265 DlPathBuilder path_builder;
1266 path_builder.MoveTo(DlPoint(100, 100));
1267 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1268
1269 DlPaint paint;
1270 paint.setColor(DlColor::kChartreuse());
1271 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1272 paint.setImageFilter(blur_filter);
1273
1274 builder.DrawPath(DlPath(path_builder), paint);
1275
1276 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1277 EXPECT_TRUE(image) << " length " << i;
1278 }
1279 }

References impeller::DisplayListToTexture().

## ◆ TEST_P() [222/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInner |
| ) |  |

Definition at line 648 of file aiks_dl_blur_unittests.cc.

648 {
649 DisplayListBuilder builder;
650 builder.Scale(GetContentScale().x, GetContentScale().y);
651
652 DlPaint paint;
653 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
654 builder.DrawPaint(paint);
655
656 paint.setColor(DlColor::kGreen());
657 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
658
659 DlPathBuilder path_builder;
660 path_builder.MoveTo(DlPoint(200, 200));
661 path_builder.LineTo(DlPoint(300, 400));
662 path_builder.LineTo(DlPoint(100, 400));
663 path_builder.Close();
664
665 builder.DrawPath(DlPath(path_builder), paint);
666
667 // Draw another thing to make sure the clip area is reset.
668 DlPaint red;
669 red.setColor(DlColor::kRed());
670 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
671
672 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
673 }

References x.

## ◆ TEST_P() [223/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleInnerGradient |
| ) |  |

Definition at line 898 of file aiks_dl_blur_unittests.cc.

898 {
899 DisplayListBuilder builder;
900
901 builder.Scale(GetContentScale().x, GetContentScale().y);
902
903 DlPaint paint;
904 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
905 builder.DrawPaint(paint);
906
907 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
908 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
909 std::vector<Scalar> stops = {0.0, 1.0};
910
911 paint = DlPaint{};
912 paint.setColorSource(DlColorSource::MakeLinear(
913 /*start_point=*/{0, 0},
914 /*end_point=*/{200, 200},
915 /*stop_count=*/colors.size(),
916 /*colors=*/colors.data(),
917 /*stops=*/stops.data(),
918 /*tile_mode=*/DlTileMode::kMirror));
919 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
920
921 DlPathBuilder path_builder;
922 path_builder.MoveTo(DlPoint(200, 200));
923 path_builder.LineTo(DlPoint(300, 400));
924 path_builder.LineTo(DlPoint(100, 400));
925 path_builder.Close();
926 builder.DrawPath(DlPath(path_builder), paint);
927
928 // Draw another thing to make sure the clip area is reset.
929 DlPaint red;
930 red.setColor(DlColor::kRed());
931 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
932
933 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
934 }

References x.

## ◆ TEST_P() [224/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuter |
| ) |  |

Definition at line 675 of file aiks_dl_blur_unittests.cc.

675 {
676 DisplayListBuilder builder;
677 builder.Scale(GetContentScale().x, GetContentScale().y);
678
679 DlPaint paint;
680 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
681 builder.DrawPaint(paint);
682
683 paint.setColor(DlColor::kGreen());
684 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
685
686 DlPathBuilder path_builder;
687 path_builder.MoveTo(DlPoint(200, 200));
688 path_builder.LineTo(DlPoint(300, 400));
689 path_builder.LineTo(DlPoint(100, 400));
690 path_builder.Close();
691
692 builder.DrawPath(DlPath(path_builder), paint);
693
694 // Draw another thing to make sure the clip area is reset.
695 DlPaint red;
696 red.setColor(DlColor::kRed());
697 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
698
699 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
700 }

References x.

## ◆ TEST_P() [225/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleOuterGradient |
| ) |  |

Definition at line 972 of file aiks_dl_blur_unittests.cc.

972 {
973 DisplayListBuilder builder;
974 builder.Scale(GetContentScale().x, GetContentScale().y);
975
976 DlPaint paint;
977 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
978 builder.DrawPaint(paint);
979
980 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
981 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
982 std::vector<Scalar> stops = {0.0, 1.0};
983
984 paint = DlPaint{};
985 paint.setColorSource(DlColorSource::MakeLinear(
986 /*start_point=*/{0, 0},
987 /*end_point=*/{200, 200},
988 /*stop_count=*/colors.size(),
989 /*colors=*/colors.data(),
990 /*stops=*/stops.data(),
991 /*tile_mode=*/DlTileMode::kMirror));
992 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
993
994 DlPathBuilder path_builder;
995 path_builder.MoveTo(DlPoint(200, 200));
996 path_builder.LineTo(DlPoint(300, 400));
997 path_builder.LineTo(DlPoint(100, 400));
998 path_builder.Close();
999 builder.DrawPath(DlPath(path_builder), paint);
1000
1001 // Draw another thing to make sure the clip area is reset.
1002 DlPaint red;
1003 red.setColor(DlColor::kRed());
1004 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1005 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1006 }

References x.

## ◆ TEST_P() [226/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolid |
| ) |  |

Definition at line 702 of file aiks_dl_blur_unittests.cc.

702 {
703 DisplayListBuilder builder;
704 builder.Scale(GetContentScale().x, GetContentScale().y);
705
706 DlPaint paint;
707 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
708 builder.DrawPaint(paint);
709
710 paint.setColor(DlColor::kGreen());
711 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
712
713 DlPathBuilder path_builder;
714 path_builder.MoveTo(DlPoint(200, 200));
715 path_builder.LineTo(DlPoint(300, 400));
716 path_builder.LineTo(DlPoint(100, 400));
717 path_builder.Close();
718
719 builder.DrawPath(DlPath(path_builder), paint);
720
721 // Draw another thing to make sure the clip area is reset.
722 DlPaint red;
723 red.setColor(DlColor::kRed());
724 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
725
726 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
727 }

References x.

## ◆ TEST_P() [227/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GaussianBlurStyleSolidGradient |
| ) |  |

Definition at line 936 of file aiks_dl_blur_unittests.cc.

936 {
937 DisplayListBuilder builder;
938 builder.Scale(GetContentScale().x, GetContentScale().y);
939
940 DlPaint paint;
941 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
942 builder.DrawPaint(paint);
943
944 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
945 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
946 std::vector<Scalar> stops = {0.0, 1.0};
947
948 paint = DlPaint{};
949 paint.setColorSource(DlColorSource::MakeLinear(
950 /*start_point=*/{0, 0},
951 /*end_point=*/{200, 200},
952 /*stop_count=*/colors.size(),
953 /*colors=*/colors.data(),
954 /*stops=*/stops.data(),
955 /*tile_mode=*/DlTileMode::kMirror));
956 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
957
958 DlPathBuilder path_builder;
959 path_builder.MoveTo(DlPoint(200, 200));
960 path_builder.LineTo(DlPoint(300, 400));
961 path_builder.LineTo(DlPoint(100, 400));
962 path_builder.Close();
963 builder.DrawPath(DlPath(path_builder), paint);
964
965 // Draw another thing to make sure the clip area is reset.
966 DlPaint red;
967 red.setColor(DlColor::kRed());
968 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
969 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
970 }

References x.

## ◆ TEST_P() [228/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlur |
| ) |  |

Definition at line 102 of file aiks_dl_blur_unittests.cc.

102 {
103 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
104 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
105 }
impeller::testing::DoGradientOvalStrokeMaskBlur
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
Definition: aiks_dl_blur_unittests.cc:61

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [229/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurInner |
| ) |  |

Definition at line 117 of file aiks_dl_blur_unittests.cc.

117 {
118 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
119 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
120 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [230/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurOuter |
| ) |  |

Definition at line 112 of file aiks_dl_blur_unittests.cc.

112 {
113 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
114 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
115 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [231/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSigmaZero |
| ) |  |

Definition at line 107 of file aiks_dl_blur_unittests.cc.

107 {
108 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
109 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
110 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [232/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientOvalStrokeMaskBlurSolid |
| ) |  |

Definition at line 122 of file aiks_dl_blur_unittests.cc.

122 {
123 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
124 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
125 }

References DoGradientOvalStrokeMaskBlur().

## ◆ TEST_P() [233/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientStrokesRenderCorrectly |
| ) |  |

Definition at line 733 of file aiks_dl_gradient_unittests.cc.

733 {
734 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
735 auto callback = [&]() -> sk_sp<DisplayList> {
736 static float scale = 3;
737 static bool add_circle_clip = true;
738 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
739 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
740 DlTileMode::kMirror, DlTileMode::kDecal};
741 static int selected_tile_mode = 0;
742 static float alpha = 1;
743
744 if (AiksTest::ImGuiBegin("Controls", nullptr,
745 ImGuiWindowFlags_AlwaysAutoResize)) {
746 ImGui::SliderFloat("Scale", &scale, 0, 6);
747 ImGui::Checkbox("Circle clip", &add_circle_clip);
748 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
749 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
750 sizeof(tile_mode_names) / sizeof(char*));
751 ImGui::End();
752 }
753
754 DisplayListBuilder builder;
755 builder.Scale(GetContentScale().x, GetContentScale().y);
756 DlPaint paint;
757 paint.setColor(DlColor::kWhite());
758 builder.DrawPaint(paint);
759
760 paint.setDrawStyle(DlDrawStyle::kStroke);
761 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
762 paint.setStrokeWidth(10);
763 auto tile_mode = tile_modes[selected_tile_mode];
764
765 std::vector<DlColor> colors = {
766 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
767 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
768 std::vector<Scalar> stops = {0.0, 1.0};
769
770 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
771 stops.size(), colors.data(),
772 stops.data(), tile_mode));
773
774 DlPathBuilder path_builder;
775 path_builder.MoveTo(DlPoint(20, 20));
776 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
777 path_builder.Close();
778 path_builder.MoveTo(DlPoint(60, 20));
779 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
780 DlPath path(path_builder);
781
782 builder.Scale(scale, scale);
783
784 if (add_circle_clip) {
785 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
786 Color::Red());
787 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
788 Color::Red());
789 auto [handle_a, handle_b] =
790 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
791
792 Matrix ip_matrix = builder.GetMatrix();
793 if (!ip_matrix.IsInvertible()) {
794 return nullptr;
795 }
796 ip_matrix = ip_matrix.Invert();
797 Point point_a = ip_matrix * handle_a * GetContentScale();
798 Point point_b = ip_matrix * handle_b * GetContentScale();
799
800 Point middle = (point_a + point_b) / 2;
801 auto radius = point_a.GetDistance(middle);
802 builder.ClipPath(DlPath::MakeCircle(middle, radius));
803 }
804
805 for (auto join :
806 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
807 paint.setStrokeJoin(join);
808 for (auto cap :
809 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
810 paint.setStrokeCap(cap);
811 builder.DrawPath(path, paint);
812 builder.Translate(80, 0);
813 }
814 builder.Translate(-240, 60);
815 }
816
817 return builder.Build();
818 };
819
820 ASSERT_TRUE(OpenPlaygroundHere(callback));
821 }
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(), scale, impeller::Color::ToARGB(), and x.

## ◆ TEST_P() [234/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HairlineDrawLine |
| ) |  |

Definition at line 305 of file aiks_dl_path_unittests.cc.

305 {
306 Scalar scale = 1.f;
307 Scalar rotation = 0.f;
308 Scalar offset = 0.f;
309 auto callback = [&]() -> sk_sp<DisplayList> {
310 if (AiksTest::ImGuiBegin("Controls", nullptr,
311 ImGuiWindowFlags_AlwaysAutoResize)) {
312 ImGui::SliderFloat("Scale", &scale, 0, 6);
313 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
314 ImGui::SliderFloat("Offset", &offset, 0, 2);
315 ImGui::End();
316 }
317
318 DisplayListBuilder builder;
319 builder.Scale(GetContentScale().x, GetContentScale().y);
320 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
321
322 DlPaint paint;
323 paint.setStrokeWidth(0.f);
324 paint.setColor(DlColor::kWhite());
325
326 builder.Translate(512, 384);
327 builder.Scale(scale, scale);
328 builder.Rotate(rotation);
329 builder.Translate(-512, -384 + offset);
330
331 for (int i = 0; i < 5; ++i) {
332 Scalar yoffset = i * 25.25f + 300.f;
333
334 builder.DrawLine(DlPoint(100, yoffset), DlPoint(924, yoffset), paint);
335 }
336
337 return builder.Build();
338 };
339
340 ASSERT_TRUE(OpenPlaygroundHere(callback));
341 }

References impeller::AiksPlayground::ImGuiBegin(), offset, scale, and x.

## ◆ TEST_P() [235/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HairlinePath |
| ) |  |

Definition at line 261 of file aiks_dl_path_unittests.cc.

261 {
262 Scalar scale = 1.f;
263 Scalar rotation = 0.f;
264 Scalar offset = 0.f;
265 auto callback = [&]() -> sk_sp<DisplayList> {
266 if (AiksTest::ImGuiBegin("Controls", nullptr,
267 ImGuiWindowFlags_AlwaysAutoResize)) {
268 ImGui::SliderFloat("Scale", &scale, 0, 6);
269 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
270 ImGui::SliderFloat("Offset", &offset, 0, 2);
271 ImGui::End();
272 }
273
274 DisplayListBuilder builder;
275 builder.Scale(GetContentScale().x, GetContentScale().y);
276 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
277
278 DlPaint paint;
279 paint.setStrokeWidth(0.f);
280 paint.setColor(DlColor::kWhite());
281 paint.setStrokeCap(DlStrokeCap::kRound);
282 paint.setStrokeJoin(DlStrokeJoin::kRound);
283 paint.setDrawStyle(DlDrawStyle::kStroke);
284
285 builder.Translate(512, 384);
286 builder.Scale(scale, scale);
287 builder.Rotate(rotation);
288 builder.Translate(-512, -384 + offset);
289
290 for (int i = 0; i < 5; ++i) {
291 Scalar yoffset = i * 25.25f + 300.f;
292 DlPathBuilder path_builder;
293
294 path_builder.MoveTo(DlPoint(100, yoffset));
295 path_builder.LineTo(DlPoint(924, yoffset));
296 builder.DrawPath(DlPath(path_builder), paint);
297 }
298
299 return builder.Build();
300 };
301
302 ASSERT_TRUE(OpenPlaygroundHere(callback));
303 }

References impeller::AiksPlayground::ImGuiBegin(), offset, scale, and x.

## ◆ TEST_P() [236/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | HexagonExperimentAntialiasLines |
| ) |  |

Definition at line 676 of file aiks_dl_path_unittests.cc.

676 {
677 float scale = 5.0f;
678 float line_width = 10.f;
679 float rotation = 0.f;
680
681 auto callback = [&]() -> sk_sp<DisplayList> {
682 if (AiksTest::ImGuiBegin("Controls", nullptr,
683 ImGuiWindowFlags_AlwaysAutoResize)) {
684 // Use ImGui::SliderFloat for consistency
685 ImGui::SliderFloat("Scale", &scale, 0.001f, 5.0f);
686 ImGui::SliderFloat("Width", &line_width, 1.0f, 20.0f);
687 ImGui::SliderFloat("Rotation", &rotation, 0.0f, 180.0f);
688
689 ImGui::End();
690 }
691 DisplayListBuilder builder;
692 builder.Scale(static_cast<float>(GetContentScale().x),
693 static_cast<float>(GetContentScale().y));
694
695 builder.DrawPaint(DlPaint(DlColor(0xff111111))); // Background
696
697 {
698 DlPaint hex_paint;
699 hex_paint.setColor(
700 DlColor::kGreen()); // Changed color to Red for visibility
701 hex_paint.setStrokeWidth(line_width); // Use the interactive width
702
703 float cx = 512.0f; // Center X
704 float cy = 384.0f; // Center Y
705 float r = 80.0f; // Radius (distance from center to vertex)
706
707 float r_sin60 = r * std::sqrt(3.0f) / 2.0f;
708 float r_cos60 = r / 2.0f;
709
710 DlPoint v0 = DlPoint(cx + r, cy); // Right vertex
711 DlPoint v1 = DlPoint(cx + r_cos60, cy - r_sin60); // Top-right vertex
712 DlPoint v2 = DlPoint(
713 cx - r_cos60,
714 cy - r_sin60); // Top-left vertex (v1-v2 is top horizontal side)
715 DlPoint v3 = DlPoint(cx - r, cy); // Left vertex
716 DlPoint v4 = DlPoint(cx - r_cos60, cy + r_sin60); // Bottom-left vertex
717 DlPoint v5 =
718 DlPoint(cx + r_cos60, cy + r_sin60); // Bottom-right vertex (v4-v5 is
719 // bottom horizontal side)
720
721 builder.Translate(cx, cy);
722 builder.Scale(scale, scale);
723 builder.Rotate(rotation);
724 builder.Translate(-cx, -cy);
725
726 builder.DrawLine(v0, v1, hex_paint);
727 builder.DrawLine(v1, v2, hex_paint); // Top side
728 builder.DrawLine(v2, v3, hex_paint);
729 builder.DrawLine(v3, v4, hex_paint);
730 builder.DrawLine(v4, v5, hex_paint); // Bottom side
731 builder.DrawLine(v5, v0, hex_paint); // Close the hexagon
732 }
733
734 return builder.Build();
735 };
736 ASSERT_TRUE(OpenPlaygroundHere(callback));
737 }

References impeller::AiksPlayground::ImGuiBegin(), scale, and x.

## ◆ TEST_P() [237/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ImageColorSourceEffectTransform |
| ) |  |

Definition at line 901 of file aiks_dl_basic_unittests.cc.

901 {
902 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
903
904 DisplayListBuilder builder;
905 auto texture = DlImageImpeller::Make(CreateTextureForFixture("monkey.png"));
906
907 DlPaint paint;
908 paint.setColor(DlColor::kWhite());
909 builder.DrawPaint(paint);
910
911 // Translation
912 {
913 DlMatrix matrix = DlMatrix::MakeTranslation({50, 50});
914 DlPaint paint;
915 paint.setColorSource(DlColorSource::MakeImage(
916 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
917 DlImageSampling::kNearestNeighbor, &matrix));
918
919 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), paint);
920 }
921
922 // Rotation/skew
923 {
924 builder.Save();
925 builder.Rotate(45);
926 DlPaint paint;
927
928 Matrix matrix(1, -1, 0, 0, //
929 1, 1, 0, 0, //
930 0, 0, 1, 0, //
931 0, 0, 0, 1);
932 paint.setColorSource(DlColorSource::MakeImage(
933 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
934 DlImageSampling::kNearestNeighbor, &matrix));
935 builder.DrawRect(DlRect::MakeLTRB(100, 0, 200, 100), paint);
936 builder.Restore();
937 }
938
939 // Scale
940 {
941 builder.Save();
942 builder.Translate(100, 0);
943 builder.Scale(100, 100);
944 DlPaint paint;
945
946 DlMatrix matrix = DlMatrix::MakeScale({0.005, 0.005, 1});
947 paint.setColorSource(DlColorSource::MakeImage(
948 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
949 DlImageSampling::kNearestNeighbor, &matrix));
950
951 builder.DrawRect(DlRect::MakeLTRB(0, 0, 1, 1), paint);
952 builder.Restore();
953 }
954
955 // Perspective
956 {
957 builder.Save();
958 builder.Translate(150, 150);
959 DlPaint paint;
960
961 DlMatrix matrix =
962 DlMatrix::MakePerspective(Radians{0.5}, ISize{200, 200}, 0.05, 1);
963 paint.setColorSource(DlColorSource::MakeImage(
964 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
965 DlImageSampling::kNearestNeighbor, &matrix));
966
967 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
968 builder.Restore();
969 }
970
971 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
972 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [238/525]

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() [239/525]

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() [240/525]

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() [241/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurDoesntStretchContents |
| ) |  |

Definition at line 758 of file aiks_dl_blur_unittests.cc.

758 {
759 Scalar sigma = 70;
760 auto callback = [&]() -> sk_sp<DisplayList> {
761 if (AiksTest::ImGuiBegin("Controls", nullptr,
762 ImGuiWindowFlags_AlwaysAutoResize)) {
763 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
764 ImGui::End();
765 }
766
767 DisplayListBuilder builder;
768 builder.Scale(GetContentScale().x, GetContentScale().y);
769
770 DlPaint paint;
771 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
772 builder.DrawPaint(paint);
773
774 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
775
776 builder.Transform(Matrix::MakeTranslation({100, 100}) *
777 Matrix::MakeScale({0.5, 0.5, 1.0f}));
778
779 paint.setColorSource(DlColorSource::MakeImage(
780 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
781 DlImageSampling::kMipmapLinear));
782 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
783
784 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
785 boston->GetSize().height),
786 paint);
787
788 return builder.Build();
789 };
790 ASSERT_TRUE(OpenPlaygroundHere(callback));
791 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and x.

## ◆ TEST_P() [242/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurOnZeroDimensionIsSkippedWideGamut |
| ) |  |

Definition at line 473 of file aiks_dl_blur_unittests.cc.

473 {
474 // Making sure this test is run on a wide gamut enabled backend
475 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
476 PixelFormat::kB10G10R10A10XR);
477
478 DisplayListBuilder builder;
479 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
480
481 DlPaint paint;
482 paint.setColor(DlColor::kBlue());
483 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
484
485 // Zero height above
486 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
487 // Regular rect
488 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
489 // Zero width to the right
490 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
491
492 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
493 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [243/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurTexture |
| ) |  |

Definition at line 729 of file aiks_dl_blur_unittests.cc.

729 {
730 Scalar sigma = 30;
731 auto callback = [&]() -> sk_sp<DisplayList> {
732 if (AiksTest::ImGuiBegin("Controls", nullptr,
733 ImGuiWindowFlags_AlwaysAutoResize)) {
734 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
735 ImGui::End();
736 }
737
738 DisplayListBuilder builder;
739 builder.Scale(GetContentScale().x, GetContentScale().y);
740
741 DlPaint paint;
742 paint.setColor(DlColor::kGreen());
743 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
744
745 builder.DrawImage(
746 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
747 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
748
749 DlPaint red;
750 red.setColor(DlColor::kRed());
751 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
752
753 return builder.Build();
754 };
755 ASSERT_TRUE(OpenPlaygroundHere(callback));
756 }

References impeller::AiksPlayground::ImGuiBegin(), impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [244/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurWithZeroSigmaIsSkipped |
| ) |  |

Definition at line 460 of file aiks_dl_blur_unittests.cc.

460 {
461 DisplayListBuilder builder;
462
463 DlPaint paint;
464 paint.setColor(DlColor::kBlue());
465 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
466
467 builder.DrawCircle(DlPoint(300, 300), 200, paint);
468 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
469
470 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
471 }

## ◆ TEST_P() [245/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScaleConvertToPath |
| ) |  |

Definition at line 194 of file aiks_dl_text_unittests.cc.

194 {
195 Scalar scale = 16.0;
196 auto callback = [&]() -> sk_sp<DisplayList> {
197 if (AiksTest::ImGuiBegin("Controls", nullptr,
198 ImGuiWindowFlags_AlwaysAutoResize)) {
199 ImGui::SliderFloat("Scale", &scale, 4, 20);
200 ImGui::End();
201 }
202
203 DisplayListBuilder builder;
204 DlPaint paint;
205 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
206 builder.DrawPaint(paint);
207
208 builder.Scale(scale, scale);
209 RenderTextInCanvasSkia(
210 GetContext(), builder, "HELLO", "Roboto-Regular.ttf",
211 TextRenderOptions{.font_size = 16,
212 .color = (16 * scale >= 250) ? DlColor::kYellow()
213 : DlColor::kOrange(),
214 .position = DlPoint(0, 20)});
215 return builder.Build();
216 };
217
218 ASSERT_TRUE(OpenPlaygroundHere(callback));
219 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and scale.

## ◆ TEST_P() [246/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MassiveScalingMatrixImageFilter |
| ) |  |

Definition at line 1545 of file aiks_dl_basic_unittests.cc.

1545 {
1546 if (GetBackend() == PlaygroundBackend::kVulkan) {
1547 GTEST_SKIP() << "Swiftshader is running out of memory on this example.";
1548 }
1549 DisplayListBuilder builder(DlRect::MakeSize(DlSize(1000, 1000)));
1550
1551 auto filter = DlImageFilter::MakeMatrix(
1552 DlMatrix::MakeScale({0.001, 0.001, 1}), DlImageSampling::kLinear);
1553
1554 DlPaint paint;
1555 paint.setImageFilter(filter);
1556 builder.SaveLayer(std::nullopt, &paint);
1557 {
1558 DlPaint paint;
1559 paint.setColor(DlColor::kRed());
1560 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100000, 100000), paint);
1561 }
1562 builder.Restore();
1563
1564 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1565 }

References impeller::kVulkan.

## ◆ TEST_P() [247/525]

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() [248/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen |
| ) |  |

Definition at line 1024 of file aiks_dl_basic_unittests.cc.

1025 {
1026 DisplayListBuilder builder;
1027 builder.Scale(GetContentScale().x, GetContentScale().y);
1028 builder.Translate(100, 100);
1029 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1030 // +300 translation applied by a SaveLayer image filter.
1031
1032 DlPaint paint;
1033 paint.setImageFilter(DlImageFilter::MakeMatrix(
1034 DlMatrix::MakeTranslation({300, 0}) * DlMatrix::MakeScale({2, 2, 1}),
1035 DlImageSampling::kNearestNeighbor));
1036 builder.SaveLayer(std::nullopt, &paint);
1037
1038 DlPaint circle_paint;
1039 circle_paint.setColor(DlColor::kGreen());
1040 builder.DrawCircle(DlPoint(-150, 0), 50, circle_paint);
1041 builder.Restore();
1042
1043 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1044 }

References x.

## ◆ TEST_P() [249/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen |
| ) |  |

Definition at line 1003 of file aiks_dl_basic_unittests.cc.

1003 {
1004 DisplayListBuilder builder;
1005 builder.Scale(GetContentScale().x, GetContentScale().y);
1006 builder.Translate(100, 100);
1007 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
1008 // +300 translation applied by a SaveLayer image filter.
1009 DlPaint paint;
1010 DlMatrix translate = DlMatrix::MakeTranslation({300, 0});
1011 paint.setImageFilter(
1012 DlImageFilter::MakeMatrix(translate, DlImageSampling::kLinear));
1013 builder.SaveLayer(std::nullopt, &paint);
1014
1015 DlPaint circle_paint;
1016 circle_paint.setColor(DlColor::kGreen());
1017 builder.DrawCircle(DlPoint(-300, 0), 100, circle_paint);
1018 builder.Restore();
1019
1020 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1021 }

References x.

## ◆ TEST_P() [250/525]

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(), scale, and x.

## ◆ TEST_P() [251/525]

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() [252/525]

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() [253/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MultipleTextWithShadowCache |
| ) |  |

Definition at line 802 of file aiks_dl_text_unittests.cc.

802 {
803 DisplayListBuilder builder;
804 builder.Scale(GetContentScale().x, GetContentScale().y);
805 DlPaint paint;
806 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
807 builder.DrawPaint(paint);
808
809 AiksContext aiks_context(GetContext(),
810 std::make_shared<TypographerContextSkia>());
811 // Cache empty
812 EXPECT_EQ(aiks_context.GetContentContext()
813 .GetTextShadowCache()
814 .GetCacheSizeForTesting(),
815 0u);
816
817 for (auto i = 0; i < 5; i++) {
818 ASSERT_TRUE(RenderTextInCanvasSkia(
819 GetContext(), builder, "Hello World", kFontFixture,
820 TextRenderOptions{
821 .color = DlColor::kBlue(),
822 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
823 }
824
825 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
826
827 // Text should be cached. Each text gets its own entry as we don't analyze the
828 // strings.
829 EXPECT_EQ(aiks_context.GetContentContext()
830 .GetTextShadowCache()
831 .GetCacheSizeForTesting(),
832 5u);
833 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [254/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | NoDimplesInRRectPath |
| ) |  |

Definition at line 1567 of file aiks_dl_basic_unittests.cc.

1567 {
1568 Scalar width = 200.f;
1569 Scalar height = 60.f;
1570 Scalar corner = 1.f;
1571 auto callback = [&]() -> sk_sp<DisplayList> {
1572 if (AiksTest::ImGuiBegin("Controls", nullptr,
1573 ImGuiWindowFlags_AlwaysAutoResize)) {
1574 ImGui::SliderFloat("width", &width, 0, 200);
1575 ImGui::SliderFloat("height", &height, 0, 200);
1576 ImGui::SliderFloat("corner", &corner, 0, 1);
1577 ImGui::End();
1578 }
1579
1580 DisplayListBuilder builder;
1581 builder.Scale(GetContentScale().x, GetContentScale().y);
1582
1583 DlPaint background_paint;
1584 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
1585 builder.DrawPaint(background_paint);
1586
1587 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
1588 std::vector<Scalar> stops = {0.0, 1.0};
1589
1590 DlPaint paint;
1591 auto gradient = DlColorSource::MakeLinear(DlPoint(0, 0), DlPoint(200, 200),
1592 2, colors.data(), stops.data(),
1593 DlTileMode::kClamp);
1594 paint.setColorSource(gradient);
1595 paint.setColor(DlColor::kWhite());
1596 paint.setDrawStyle(DlDrawStyle::kStroke);
1597 paint.setStrokeWidth(20);
1598
1599 builder.Save();
1600 builder.Translate(100, 100);
1601
1602 Scalar corner_x = ((1 - corner) * 50) + 50;
1603 Scalar corner_y = corner * 50 + 50;
1604 DlRoundRect rrect = DlRoundRect::MakeRectXY(
1605 DlRect::MakeXYWH(0, 0, width, height), corner_x, corner_y);
1606 builder.DrawRoundRect(rrect, paint);
1607 builder.Restore();
1608 return builder.Build();
1609 };
1610 ASSERT_TRUE(OpenPlaygroundHere(callback));
1611 }

References impeller::AiksPlayground::ImGuiBegin(), and x.

## ◆ TEST_P() [255/525]

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() [256/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PipelineBlendSingleParameter |
| ) |  |

Definition at line 1519 of file aiks_dl_basic_unittests.cc.

1519 {
1520 DisplayListBuilder builder;
1521
1522 // Should render a green square in the middle of a blue circle.
1523 DlPaint paint;
1524 builder.SaveLayer(std::nullopt, &paint);
1525 {
1526 builder.Translate(100, 100);
1527 paint.setColor(DlColor::kBlue());
1528 builder.DrawCircle(DlPoint(200, 200), 200, paint);
1529 builder.ClipRect(DlRect::MakeXYWH(100, 100, 200, 200));
1530
1531 paint.setColor(DlColor::kGreen());
1532 paint.setBlendMode(DlBlendMode::kSrcOver);
1533 paint.setImageFilter(DlImageFilter::MakeColorFilter(
1534 DlColorFilter::MakeBlend(DlColor::kWhite(), DlBlendMode::kDst)));
1535 builder.DrawCircle(DlPoint(200, 200), 200, paint);
1536 builder.Restore();
1537 }
1538
1539 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1540 }

## ◆ TEST_P() [257/525]

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() [258/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RotateColorFilteredPath |
| ) |  |

Definition at line 25 of file aiks_dl_path_unittests.cc.

25 {
26 DisplayListBuilder builder;
27 builder.Transform(DlMatrix::MakeTranslation(DlPoint(300, 300)) *
28 DlMatrix::MakeRotationZ(DlDegrees(90)));
29
30 DlPathBuilder arrow_stem;
31 DlPathBuilder arrow_head;
32
33 arrow_stem.MoveTo(DlPoint(120, 190)).LineTo(DlPoint(120, 50));
34 arrow_head.MoveTo(DlPoint(50, 120))
35 .LineTo(DlPoint(120, 190))
36 .LineTo(DlPoint(190, 120));
37
38 auto filter =
39 DlColorFilter::MakeBlend(DlColor::kAliceBlue(), DlBlendMode::kSrcIn);
40
41 DlPaint paint;
42 paint.setStrokeWidth(15.0);
43 paint.setStrokeCap(DlStrokeCap::kRound);
44 paint.setStrokeJoin(DlStrokeJoin::kRound);
45 paint.setDrawStyle(DlDrawStyle::kStroke);
46 paint.setColorFilter(filter);
47 paint.setColor(DlColor::kBlack());
48
49 builder.DrawPath(DlPath(arrow_stem), paint);
50 builder.DrawPath(DlPath(arrow_head), paint);
51
52 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
53 }

## ◆ TEST_P() [259/525]

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() [260/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerDrawsBehindSubsequentEntities |
| ) |  |

Definition at line 1374 of file aiks_dl_basic_unittests.cc.

1374 {
1375 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1376 DisplayListBuilder builder;
1377 DlPaint paint;
1378
1379 paint.setColor(DlColor::kBlack());
1380 DlRect rect = DlRect::MakeXYWH(25, 25, 25, 25);
1381 builder.DrawRect(rect, paint);
1382
1383 builder.Translate(10, 10);
1384
1385 DlPaint save_paint;
1386 builder.SaveLayer(std::nullopt, &save_paint);
1387
1388 paint.setColor(DlColor::kGreen());
1389 builder.DrawRect(rect, paint);
1390
1391 builder.Restore();
1392
1393 builder.Translate(10, 10);
1394 paint.setColor(DlColor::kRed());
1395 builder.DrawRect(rect, paint);
1396
1397 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1398 }

## ◆ TEST_P() [261/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerFiltersScaleWithTransform |
| ) |  |

Definition at line 1466 of file aiks_dl_basic_unittests.cc.

1466 {
1467 DisplayListBuilder builder;
1468
1469 builder.Scale(GetContentScale().x, GetContentScale().y);
1470 builder.Translate(100, 100);
1471
1472 auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg"));
1473 auto draw_image_layer = [&builder, &texture](const DlPaint& paint) {
1474 builder.SaveLayer(std::nullopt, &paint);
1475 builder.DrawImage(texture, DlPoint(), DlImageSampling::kLinear);
1476 builder.Restore();
1477 };
1478
1479 DlPaint effect_paint;
1480 effect_paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 6));
1481 draw_image_layer(effect_paint);
1482
1483 builder.Translate(300, 300);
1484 builder.Scale(3, 3);
1485 draw_image_layer(effect_paint);
1486
1487 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1488 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [262/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaledK |
| ) |  |

Definition at line 172 of file aiks_dl_text_unittests.cc.

172 {
173 DisplayListBuilder builder;
174 DlPaint paint;
175 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
176 builder.DrawPaint(paint);
177 for (int i = 0; i < 6; ++i) {
178 builder.Save();
179 builder.Translate(300 * i, 0);
180 Scalar scale = 0.445 - (i / 1000.f);
181 builder.Scale(scale, scale);
182 RenderTextInCanvasSkia(
183 GetContext(), builder, "k", "Roboto-Regular.ttf",
184 TextRenderOptions{.font_size = 600, .position = DlPoint(10, 500)});
185 RenderTextInCanvasSkia(
186 GetContext(), builder, "k", "Roboto-Regular.ttf",
187 TextRenderOptions{.font_size = 300, .position = DlPoint(10, 800)});
188 builder.Restore();
189 }
190 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
191 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and scale.

## ◆ TEST_P() [263/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ScaleExperimentAntialiasLines |
| ) |  |

Definition at line 624 of file aiks_dl_path_unittests.cc.

624 {
625 Scalar scale = 5.0;
626 Scalar line_width = 10.f;
627 auto callback = [&]() -> sk_sp<DisplayList> {
628 if (AiksTest::ImGuiBegin("Controls", nullptr,
629 ImGuiWindowFlags_AlwaysAutoResize)) {
630 ImGui::SliderFloat("Scale", &scale, 0.001, 5);
631 ImGui::SliderFloat("Width", &line_width, 1, 20);
632
633 ImGui::End();
634 }
635 DisplayListBuilder builder;
636 builder.Scale(GetContentScale().x, GetContentScale().y);
637
638 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
639
640 {
641 DlPaint paint;
642 paint.setColor(DlColor::kGreenYellow());
643 paint.setStrokeWidth(line_width);
644
645 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 100), paint);
646 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 150), paint);
647
648 builder.Save();
649 builder.Translate(100, 300);
650 builder.Scale(scale, scale);
651 builder.Translate(-100, -300);
652 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 300), paint);
653 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 450), paint);
654 builder.Restore();
655 }
656
657 {
658 DlPaint paint;
659 paint.setColor(DlColor::kGreenYellow());
660 paint.setStrokeWidth(2.0);
661
662 builder.Save();
663 builder.Translate(100, 500);
664 builder.Scale(0.2, 0.2);
665 builder.Translate(-100, -500);
666 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 500), paint);
667 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 650), paint);
668 builder.Restore();
669 }
670
671 return builder.Build();
672 };
673 ASSERT_TRUE(OpenPlaygroundHere(callback));
674 }

References impeller::AiksPlayground::ImGuiBegin(), scale, and x.

## ◆ TEST_P() [264/525]

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() [265/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SiblingSaveLayerBoundsAreRespected |
| ) |  |

Definition at line 1400 of file aiks_dl_basic_unittests.cc.

1400 {
1401 DisplayListBuilder builder;
1402 DlPaint paint;
1403 DlRect rect = DlRect::MakeXYWH(0, 0, 1000, 1000);
1404
1405 // Black, green, and red squares offset by [10, 10].
1406 {
1407 DlPaint save_paint;
1408 DlRect bounds = DlRect::MakeXYWH(25, 25, 25, 25);
1409 builder.SaveLayer(bounds, &save_paint);
1410 paint.setColor(DlColor::kBlack());
1411 builder.DrawRect(rect, paint);
1412 builder.Restore();
1413 }
1414
1415 {
1416 DlPaint save_paint;
1417 DlRect bounds = DlRect::MakeXYWH(35, 35, 25, 25);
1418 builder.SaveLayer(bounds, &save_paint);
1419 paint.setColor(DlColor::kGreen());
1420 builder.DrawRect(rect, paint);
1421 builder.Restore();
1422 }
1423
1424 {
1425 DlPaint save_paint;
1426 DlRect bounds = DlRect::MakeXYWH(45, 45, 25, 25);
1427 builder.SaveLayer(bounds, &save_paint);
1428 paint.setColor(DlColor::kRed());
1429 builder.DrawRect(rect, paint);
1430 builder.Restore();
1431 }
1432
1433 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1434 }

## ◆ TEST_P() [266/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SimpleExperimentAntialiasLines |
| ) |  |

Definition at line 739 of file aiks_dl_path_unittests.cc.

739 {
740 DisplayListBuilder builder;
741 builder.Scale(GetContentScale().x, GetContentScale().y);
742
743 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
744
745 DlPaint paint;
746 paint.setColor(DlColor::kGreenYellow());
747 paint.setStrokeWidth(10);
748
749 auto draw = [&builder](DlPaint& paint) {
750 for (auto cap :
751 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
752 paint.setStrokeCap(cap);
753 DlPoint origin = {100, 100};
754 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
755 for (int d = 15; d < 90; d += 15) {
756 Matrix m = Matrix::MakeRotationZ(Degrees(d));
757 Point origin = {100, 100};
758 Point p0 = {50, 0};
759 Point p1 = {150, 0};
760 auto a = origin + m * p0;
761 auto b = origin + m * p1;
762
763 builder.DrawLine(a, b, paint);
764 }
765 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
766 builder.DrawCircle(origin, 35, paint);
767
768 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
769
770 builder.Translate(250, 0);
771 }
772 builder.Translate(-750, 250);
773 };
774
775 draw(paint);
776
777 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
778 }

References impeller::saturated::b, impeller::Matrix::MakeRotationZ(), and x.

## ◆ TEST_P() [267/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SingleIconShadowTest |
| ) |  |

Definition at line 835 of file aiks_dl_text_unittests.cc.

835 {
836 DisplayListBuilder builder;
837 builder.Scale(GetContentScale().x, GetContentScale().y);
838 DlPaint paint;
839 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
840 builder.DrawPaint(paint);
841
842 AiksContext aiks_context(GetContext(),
843 std::make_shared<TypographerContextSkia>());
844 // Cache empty
845 EXPECT_EQ(aiks_context.GetContentContext()
846 .GetTextShadowCache()
847 .GetCacheSizeForTesting(),
848 0u);
849
850 // Create font instance outside loop so all draws use identical font instance.
851 auto c_font_fixture = std::string(kFontFixture);
852 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
853 ASSERT_TRUE(mapping);
854 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
855 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
856
857 for (auto i = 0; i < 10; i++) {
858 ASSERT_TRUE(RenderTextInCanvasSkia(
859 GetContext(), builder, "A", kFontFixture,
860 TextRenderOptions{
861 .color = DlColor::kBlue(),
862 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
863 sk_font));
864 }
865
866 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
867
868 // Text should be cached. All 10 glyphs use the same cache entry.
869 EXPECT_EQ(aiks_context.GetContentContext()
870 .GetTextShadowCache()
871 .GetCacheSizeForTesting(),
872 1u);
873 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [268/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCircleMaskBlurTinySigma |
| ) |  |

Definition at line 127 of file aiks_dl_blur_unittests.cc.

127 {
128 DisplayListBuilder builder;
129 builder.Scale(GetContentScale().x, GetContentScale().y);
130
131 std::vector<float> sigmas = {0.0, 0.01, 1.0};
132 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
133 DlColor::kRed()};
134 for (uint32_t i = 0; i < sigmas.size(); ++i) {
135 DlPaint paint;
136 paint.setColor(colors[i]);
137 paint.setMaskFilter(
138 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
139
140 builder.Save();
141 builder.Translate(100 + (i * 100), 100);
142 DlRoundRect rrect = DlRoundRect::MakeRectXY(
143 DlRect::MakeXYWH(0, 0, 100.0f, 100.0f), 100, 100);
144 builder.DrawRoundRect(rrect, paint);
145 builder.Restore();
146 }
147
148 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
149 }

References x.

## ◆ TEST_P() [269/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorCirclesOvalsRRectsMaskBlurCorrectly |
| ) |  |

Definition at line 735 of file aiks_dl_basic_unittests.cc.

735 {
736 DisplayListBuilder builder;
737 builder.Scale(GetContentScale().x, GetContentScale().y);
738 DlPaint paint;
739 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1.0f));
740
741 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
742
743 paint.setColor(
744 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f));
745 Scalar y = 100.0f;
746 for (int i = 0; i < 5; i++) {
747 Scalar x = (i + 1) * 100;
748 Scalar radius = x / 10.0f;
749 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
750 radius, 60.0f - radius),
751 paint);
752 }
753
754 paint.setColor(DlColor::kBlue());
755 y += 100.0f;
756 for (int i = 0; i < 5; i++) {
757 Scalar x = (i + 1) * 100;
758 Scalar radius = x / 10.0f;
759 builder.DrawCircle(DlPoint(x + 25, y + 25), radius, paint);
760 }
761
762 paint.setColor(DlColor::kGreen());
763 y += 100.0f;
764 for (int i = 0; i < 5; i++) {
765 Scalar x = (i + 1) * 100;
766 Scalar radius = x / 10.0f;
767 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
768 radius, 60.0f - radius),
769 paint);
770 }
771
772 paint.setColor(
773 DlColor::RGBA(128.0f / 255.0f, 0.0f / 255.0f, 128.0f / 255.0f, 1.0f));
774 y += 100.0f;
775 for (int i = 0; i < 5; i++) {
776 Scalar x = (i + 1) * 100;
777 Scalar radius = x / 20.0f;
778 builder.DrawRoundRect(
779 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
780 radius, radius),
781 paint);
782 }
783
784 paint.setColor(
785 DlColor::RGBA(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f, 1.0f));
786 y += 100.0f;
787 for (int i = 0; i < 5; i++) {
788 Scalar x = (i + 1) * 100;
789 Scalar radius = x / 20.0f;
790 builder.DrawRoundRect(
791 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
792 radius, 5.0f),
793 paint);
794 }
795
796 auto dl = builder.Build();
797 ASSERT_TRUE(OpenPlaygroundHere(dl));
798 }

References x.

## ◆ TEST_P() [270/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorOvalsMaskBlurTinySigma |
| ) |  |

Definition at line 37 of file aiks_dl_blur_unittests.cc.

37 {
38 DisplayListBuilder builder;
39 builder.Scale(GetContentScale().x, GetContentScale().y);
40
41 std::vector<float> sigmas = {0.0, 0.01, 1.0};
42 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
43 DlColor::kRed()};
44 for (uint32_t i = 0; i < sigmas.size(); ++i) {
45 DlPaint paint;
46 paint.setColor(colors[i]);
47 paint.setMaskFilter(
48 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
49
50 builder.Save();
51 builder.Translate(100 + (i * 100), 100);
52 DlRoundRect rrect =
53 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 60.0f, 160.0f), 50, 100);
54 builder.DrawRoundRect(rrect, paint);
55 builder.Restore();
56 }
57
58 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
59 }

References x.

## ◆ TEST_P() [271/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidStrokesRenderCorrectly |
| ) |  |

Definition at line 469 of file aiks_dl_path_unittests.cc.

469 {
470 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
471 auto callback = [&]() -> sk_sp<DisplayList> {
472 static Color color = Color::Black().WithAlpha(0.5);
473 static float scale = 3;
474 static bool add_circle_clip = true;
475
476 if (AiksTest::ImGuiBegin("Controls", nullptr,
477 ImGuiWindowFlags_AlwaysAutoResize)) {
478 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
479 ImGui::SliderFloat("Scale", &scale, 0, 6);
480 ImGui::Checkbox("Circle clip", &add_circle_clip);
481 ImGui::End();
482 }
483
484 DisplayListBuilder builder;
485 builder.Scale(GetContentScale().x, GetContentScale().y);
486 DlPaint paint;
487
488 paint.setColor(DlColor::kWhite());
489 builder.DrawPaint(paint);
490
491 paint.setColor(
492 DlColor::ARGB(color.alpha, color.red, color.green, color.blue));
493 paint.setDrawStyle(DlDrawStyle::kStroke);
494 paint.setStrokeWidth(10);
495
496 DlPathBuilder path_builder;
497 path_builder.MoveTo(DlPoint(20, 20));
498 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
499 path_builder.Close();
500 path_builder.MoveTo(DlPoint(60, 20));
501 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
502 DlPath path(path_builder);
503
504 builder.Scale(scale, scale);
505
506 if (add_circle_clip) {
507 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
508 Color::Red());
509 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
510 Color::Red());
511 auto [handle_a, handle_b] =
512 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
513
514 Matrix screen_to_canvas = builder.GetMatrix();
515 if (!screen_to_canvas.IsInvertible()) {
516 return nullptr;
517 }
518 screen_to_canvas = screen_to_canvas.Invert();
519
520 Point point_a = screen_to_canvas * handle_a;
521 Point point_b = screen_to_canvas * handle_b;
522
523 Point middle = point_a + point_b;
524 middle *= GetContentScale().x / 2;
525
526 auto radius = point_a.GetDistance(middle);
527
528 builder.ClipPath(DlPath::MakeCircle(middle, radius));
529 }
530
531 for (auto join :
532 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
533 paint.setStrokeJoin(join);
534 for (auto cap :
535 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
536 paint.setStrokeCap(cap);
537 builder.DrawPath(path, paint);
538 builder.Translate(80, 0);
539 }
540 builder.Translate(-240, 60);
541 }
542
543 return builder.Build();
544 };
545
546 ASSERT_TRUE(OpenPlaygroundHere(callback));
547 }
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(), scale, impeller::Color::WithAlpha(), x, and impeller::TPoint< T >::x.

## ◆ TEST_P() [272/525]

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() [273/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | StrokedCirclesRenderCorrectly |
| ) |  |

Definition at line 488 of file aiks_dl_basic_unittests.cc.

488 {
489 DisplayListBuilder builder;
490 builder.Scale(GetContentScale().x, GetContentScale().y);
491 DlPaint paint;
492 const int color_count = 3;
493 DlColor colors[color_count] = {
494 DlColor::kBlue(),
495 DlColor::kGreen(),
496 DlColor::RGBA(220.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, 1.0f),
497 };
498
499 paint.setColor(DlColor::kWhite());
500 builder.DrawPaint(paint);
501
502 int c_index = 0;
503
504 auto draw = [&paint, &colors, &c_index](DlCanvas& canvas, DlPoint center,
505 Scalar r, Scalar dr, int n) {
506 for (int i = 0; i < n; i++) {
507 paint.setColor(colors[(c_index++) % color_count]);
508 canvas.DrawCircle(center, r, paint);
509 r += dr;
510 }
511 };
512
513 paint.setDrawStyle(DlDrawStyle::kStroke);
514 paint.setStrokeWidth(1);
515 draw(builder, DlPoint(10, 10), 2, 2, 14); // r = [2, 28], covers [1,29]
516 paint.setStrokeWidth(5);
517 draw(builder, DlPoint(10, 10), 35, 10, 56); // r = [35, 585], covers [30,590]
518
519 DlColor gradient_colors[7] = {
520 DlColor::RGBA(0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0),
521 DlColor::RGBA(0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0),
522 DlColor::RGBA(0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0),
523 DlColor::RGBA(0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0),
524 DlColor::RGBA(0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0),
525 DlColor::RGBA(0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0),
526 DlColor::RGBA(0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0),
527 };
528 DlScalar stops[7] = {
529 0.0,
530 (1.0 / 6.0) * 1,
531 (1.0 / 6.0) * 2,
532 (1.0 / 6.0) * 3,
533 (1.0 / 6.0) * 4,
534 (1.0 / 6.0) * 5,
535 1.0,
536 };
537 auto texture = CreateTextureForFixture("airplane.jpg",
538 /*enable_mipmapping=*/true);
539 auto image = DlImageImpeller::Make(texture);
540
541 paint.setColorSource(DlColorSource::MakeRadial(
542 DlPoint(500, 600), 75, 7, gradient_colors, stops, DlTileMode::kMirror));
543 draw(builder, DlPoint(500, 600), 5, 10, 10);
544
545 DlMatrix local_matrix = DlMatrix::MakeTranslation({700, 200});
546 paint.setColorSource(DlColorSource::MakeImage(
547 image, DlTileMode::kRepeat, DlTileMode::kRepeat,
548 DlImageSampling::kNearestNeighbor, &local_matrix));
549 draw(builder, DlPoint(800, 300), 5, 10, 10);
550
551 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
552 }

References impeller::DlImageImpeller::Make(), and x.

## ◆ TEST_P() [274/525]

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);
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() [275/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SubpassWithClearColorOptimization |
| ) |  |

Definition at line 974 of file aiks_dl_basic_unittests.cc.

974 {
975 DisplayListBuilder builder;
976
977 // Use a non-srcOver blend mode to ensure that we don't detect this as an
978 // opacity peephole optimization.
979 DlPaint paint;
980 paint.setColor(DlColor::kBlue().modulateOpacity(0.5));
981 paint.setBlendMode(DlBlendMode::kSrc);
982
983 DlRect bounds = DlRect::MakeLTRB(0, 0, 200, 200);
984 builder.SaveLayer(bounds, &paint);
985
986 paint.setColor(DlColor::kTransparent());
987 paint.setBlendMode(DlBlendMode::kSrc);
988 builder.DrawPaint(paint);
989 builder.Restore();
990
991 paint.setColor(DlColor::kBlue());
992 paint.setBlendMode(DlBlendMode::kDstOver);
993 builder.SaveLayer(std::nullopt, &paint);
994 builder.Restore();
995
996 // This playground should appear blank on CI since we are only drawing
997 // transparent black. If the clear color optimization is broken, the texture
998 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
999 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1000 }

## ◆ TEST_P() [276/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SupportsBlitToOnscreen |
| ) |  |

Definition at line 376 of file canvas_unittests.cc.

376 {
377 ContentContext context(GetContext(), nullptr);
378 auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
379 /*requires_readback=*/true);
380
381 if (GetBackend() != PlaygroundBackend::kMetal) {
382 EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
383 } else {
384 EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
385 }
386 }

References CreateTestCanvas(), impeller::kMetal, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [277/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextContentsMismatchedTransformTest |
| ) |  |

Definition at line 706 of file aiks_dl_text_unittests.cc.

706 {
707 AiksContext aiks_context(GetContext(),
708 std::make_shared<TypographerContextSkia>());
709
710 // Verifies that TextContents only use the scale/transform that is
711 // computed during preroll.
712 constexpr const char* font_fixture = "Roboto-Regular.ttf";
713
714 // Construct the text blob.
715 auto c_font_fixture = std::string(font_fixture);
716 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
717 ASSERT_TRUE(mapping);
718
719 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
720 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
721
722 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
723 ASSERT_TRUE(blob);
724
725 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
726
727 // Simulate recording the text frame during preroll.
728 Matrix preroll_matrix =
729 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
730 Point preroll_point = Point{23, 45};
731 {
732 auto scale = TextFrame::RoundScaledFontSize(
733 (preroll_matrix * Matrix::MakeTranslation(preroll_point))
734 .GetMaxBasisLengthXY());
735
736 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
737 text_frame, //
738 scale, //
739 preroll_point, //
740 preroll_matrix,
741 std::nullopt //
742 );
743 }
744
745 // Now simulate rendering with a slightly different scale factor.
746 RenderTarget render_target =
747 aiks_context.GetContentContext()
748 .GetRenderTargetCache()
749 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
750
751 TextContents text_contents;
752 text_contents.SetTextFrame(text_frame);
753 text_contents.SetOffset(preroll_point);
754 text_contents.SetScale(1.6);
755 text_contents.SetColor(Color::Aqua());
756
757 Matrix not_preroll_matrix =
758 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
759
760 Entity entity;
761 entity.SetTransform(not_preroll_matrix);
762
763 std::shared_ptr<CommandBuffer> command_buffer =
764 aiks_context.GetContext()->CreateCommandBuffer();
765 std::shared_ptr<RenderPass> render_pass =
766 command_buffer->CreateRenderPass(render_target);
767
768 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
769 *render_pass));
770 }

References impeller::AiksContext::GetContentContext(), impeller::AiksContext::GetContext(), impeller::ContentContext::GetLazyGlyphAtlas(), impeller::ContentContext::GetRenderTargetCache(), impeller::MakeTextFrameFromTextBlobSkia(), impeller::TextContents::Render(), scale, impeller::TextContents::SetColor(), impeller::TextContents::SetOffset(), impeller::TextContents::SetScale(), impeller::TextContents::SetTextFrame(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [278/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextForegroundShaderWithTransform |
| ) |  |

Definition at line 591 of file aiks_dl_text_unittests.cc.

591 {
592 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
593 ASSERT_NE(mapping, nullptr);
594
595 Scalar font_size = 100;
596 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
597 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
598
599 DlPaint text_paint;
600 text_paint.setColor(DlColor::kBlue());
601
602 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
603 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
604 std::vector<Scalar> stops = {
605 0.0,
606 1.0,
607 };
608 text_paint.setColorSource(DlColorSource::MakeLinear(
609 /*start_point=*/DlPoint(0, 0), //
610 /*end_point=*/DlPoint(100, 100), //
611 /*stop_count=*/2, //
612 /*colors=*/colors.data(), //
613 /*stops=*/stops.data(), //
614 /*tile_mode=*/DlTileMode::kRepeat //
615 ));
616
617 DisplayListBuilder builder;
618 builder.Translate(100, 100);
619 builder.Rotate(45);
620
621 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
622 ASSERT_NE(blob, nullptr);
623 auto frame = MakeTextFrameFromTextBlobSkia(blob);
624 builder.DrawTextFrame(frame, 0, 0, text_paint);
625
626 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
627 }

References font_size, and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [279/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextFrameSubpixelAlignment |
| ) |  |

Definition at line 315 of file aiks_dl_text_unittests.cc.

315 {
316 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
317 std::array<Scalar, 20> phase_offsets = {
318 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
319 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
320 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
321 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
322 auto callback = [&]() -> sk_sp<DisplayList> {
323 static float font_size = 20;
324 static float phase_variation = 0.2;
325 static float speed = 0.5;
326 static float magnitude = 100;
327 if (AiksTest::ImGuiBegin("Controls", nullptr,
328 ImGuiWindowFlags_AlwaysAutoResize)) {
329 ImGui::SliderFloat("Font size", &font_size, 5, 50);
330 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
331 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
332 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
333 ImGui::End();
334 }
335
336 DisplayListBuilder builder;
337 builder.Scale(GetContentScale().x, GetContentScale().y);
338
339 for (size_t i = 0; i < phase_offsets.size(); i++) {
340 DlPoint position = DlPoint(
341 200 +
342 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
343 GetSecondsElapsed() * speed)), //
344 200 + i * font_size * 1.1 //
345 );
346 if (!RenderTextInCanvasSkia(
347 GetContext(), builder,
348 "the quick brown fox jumped over "
349 "the lazy dog!.?",
350 "Roboto-Regular.ttf",
351 {.font_size = font_size, .position = position})) {
352 return nullptr;
353 }
354 }
355 return builder.Build();
356 };
357
358 ASSERT_TRUE(OpenPlaygroundHere(callback));
359 }

References font_size, impeller::k2Pi, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [280/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated |
| ) |  |

Definition at line 487 of file aiks_dl_text_unittests.cc.

487 {
488 DisplayListBuilder builder;
489
490 builder.Scale(GetContentScale().x, GetContentScale().y);
491 DlPaint paint;
492 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
493 builder.DrawPaint(paint);
494
495 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
496 0, 0.5, 0, 0, //
497 0, 0, 0.3, 0, //
498 100, 100, 0, 1.3));
499 ASSERT_TRUE(RenderTextInCanvasSkia(
500 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
501 "Roboto-Regular.ttf"));
502
503 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
504 }

References RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [281/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated180Degrees |
| ) |  |

Definition at line 278 of file aiks_dl_text_unittests.cc.

278 {
279 float fpivot[2] = {200 + 30, 200 - 20};
280 float rotation = 180;
281 float foffset[2] = {200, 200};
282
283 auto callback = [&]() -> sk_sp<DisplayList> {
284 if (AiksTest::ImGuiBegin("Controls", nullptr,
285 ImGuiWindowFlags_AlwaysAutoResize)) {
286 ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
287 ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
288 ImGui::SliderFloat("rotation", &rotation, 0, 360);
289 ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
290 ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
291 ImGui::End();
292 }
293 DisplayListBuilder builder;
294 builder.Scale(GetContentScale().x, GetContentScale().y);
295 builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
296
297 builder.Save();
298 DlPoint pivot = Point(fpivot[0], fpivot[1]);
299 builder.Translate(pivot.x, pivot.y);
300 builder.Rotate(rotation);
301 builder.Translate(-pivot.x, -pivot.y);
302
303 RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
304 TextRenderOptions{
305 .color = DlColor::kBlack(),
306 .position = DlPoint(foffset[0], foffset[1]),
307 });
308
309 builder.Restore();
310 return builder.Build();
311 };
312 ASSERT_TRUE(OpenPlaygroundHere(callback));
313 }

References impeller::testing::TextRenderOptions::color, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [282/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextWithShadowCache |
| ) |  |

Definition at line 772 of file aiks_dl_text_unittests.cc.

772 {
773 DisplayListBuilder builder;
774 builder.Scale(GetContentScale().x, GetContentScale().y);
775 DlPaint paint;
776 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
777 builder.DrawPaint(paint);
778
779 AiksContext aiks_context(GetContext(),
780 std::make_shared<TypographerContextSkia>());
781 // Cache empty
782 EXPECT_EQ(aiks_context.GetContentContext()
783 .GetTextShadowCache()
784 .GetCacheSizeForTesting(),
785 0u);
786
787 ASSERT_TRUE(RenderTextInCanvasSkia(
788 GetContext(), builder, "Hello World", kFontFixture,
789 TextRenderOptions{
790 .color = DlColor::kBlue(),
791 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
792
793 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
794
795 // Text should be cached.
796 EXPECT_EQ(aiks_context.GetContentContext()
797 .GetTextShadowCache()
798 .GetCacheSizeForTesting(),
799 1u);
800 }

References impeller::testing::TextRenderOptions::color, impeller::DisplayListToTexture(), impeller::TextShadowCache::GetCacheSizeForTesting(), impeller::AiksContext::GetContentContext(), impeller::ContentContext::GetTextShadowCache(), kFontFixture, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [283/525]

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() [284/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransformMultipliesCorrectly |
| ) |  |

Definition at line 69 of file canvas_unittests.cc.

69 {
70 ContentContext context(GetContext(), nullptr);
71 auto canvas = CreateTestCanvas(context);
72
73 ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix());
74
75 // clang-format off
76 canvas->Translate(Vector3(100, 200));
77 ASSERT_MATRIX_NEAR(
78 canvas->GetCurrentTransform(),
79 Matrix( 1, 0, 0, 0,
80 0, 1, 0, 0,
81 0, 0, 1, 0,
82 100, 200, 0, 1));
83
84 canvas->Rotate(Radians(kPiOver2));
85 ASSERT_MATRIX_NEAR(
86 canvas->GetCurrentTransform(),
87 Matrix( 0, 1, 0, 0,
88 -1, 0, 0, 0,
89 0, 0, 1, 0,
90 100, 200, 0, 1));
91
92 canvas->Scale(Vector3(2, 3));
93 ASSERT_MATRIX_NEAR(
94 canvas->GetCurrentTransform(),
95 Matrix( 0, 2, 0, 0,
96 -3, 0, 0, 0,
97 0, 0, 0, 0,
98 100, 200, 0, 1));
99
100 canvas->Translate(Vector3(100, 200));
101 ASSERT_MATRIX_NEAR(
102 canvas->GetCurrentTransform(),
103 Matrix( 0, 2, 0, 0,
104 -3, 0, 0, 0,
105 0, 0, 0, 0,
106 -500, 400, 0, 1));
107 // clang-format on
108 }

References ASSERT_MATRIX_NEAR, CreateTestCanvas(), and impeller::kPiOver2.

## ◆ TEST_P() [285/525]

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() [286/525]

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() [287/525]

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() [288/525]

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() [289/525]

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() [290/525]

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() [291/525]

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() [292/525]

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() [293/525]

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() [294/525]

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() [295/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TwoContourPathWithSinglePointContour |
| ) |  |

Definition at line 963 of file aiks_dl_path_unittests.cc.

963 {
964 DisplayListBuilder builder;
965
966 DlPaint paint;
967 paint.setColor(DlColor::kRed());
968 paint.setDrawStyle(DlDrawStyle::kStroke);
969 paint.setStrokeWidth(15.0);
970 paint.setStrokeCap(DlStrokeCap::kRound);
971
972 DlPathBuilder path_builder;
973 path_builder.MoveTo(DlPoint(100, 100));
974 path_builder.LineTo(DlPoint(150, 150));
975 path_builder.MoveTo(DlPoint(200, 200));
976 path_builder.LineTo(DlPoint(200, 200));
977
978 builder.DrawPath(DlPath(path_builder), paint);
979
980 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
981 }

## ◆ TEST_P() [296/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VarietyOfTextScalesShowingRasterAndPath |
| ) |  |

Definition at line 875 of file aiks_dl_text_unittests.cc.

875 {
876 DisplayListBuilder builder;
877 DlPaint paint;
878 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
879 builder.DrawPaint(paint);
880 builder.Scale(GetContentScale().x, GetContentScale().y);
881
882 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
883 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
884 Scalar space = 16;
885 Scalar x = 0;
886 for (auto i = 0u; i < scales.size(); i++) {
887 builder.Save();
888 builder.Scale(scales[i], scales[i]);
889 RenderTextInCanvasSkia(
890 GetContext(), builder, "lo", "Roboto-Regular.ttf",
891 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
892 space += spacing[i];
893 if (i == 3) {
894 x = 10;
895 space = 16;
896 }
897 builder.Restore();
898 }
899 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
900 }

References impeller::testing::TextRenderOptions::font_size, RenderTextInCanvasSkia(), and x.

## ◆ TEST_P() [297/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerifyNonOptimizedGradient |
| ) |  |

Definition at line 915 of file aiks_dl_gradient_unittests.cc.

915 {
916 DisplayListBuilder builder;
917 DlPaint paint;
918 builder.Translate(100.0f, 0);
919
920 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
921 DlColor::kGreen()};
922 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
923
924 // Inset the start and end point to verify that we do not apply
925 // the fast gradient condition.
926 paint.setColorSource(
927 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
928 stops.data(), DlTileMode::kRepeat));
929
930 paint.setColor(DlColor::kWhite());
931 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
932 builder.Translate(400, 0);
933 builder.DrawRoundRect(
934 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
935
936 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
937 }

## ◆ TEST_P() [298/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionData |
| ) |  |

Definition at line 96 of file aiks_dl_vertices_unittests.cc.

96 {
97 DisplayListBuilder builder;
98 DlPaint paint;
99 auto image =
100 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
101 auto size = image->impeller_texture()->GetSize();
102
103 paint.setColorSource(
104 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
105
106 std::vector<DlPoint> positions = {
107 DlPoint(0, 0), DlPoint(size.width, 0),
108 DlPoint(0, size.height), DlPoint(size.width, 0),
109 DlPoint(0, 0), DlPoint(size.width, size.height),
110 };
111 std::vector<DlColor> colors = {
112 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
113 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
114 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
115 };
116
117 auto vertices =
118 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
119
120 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
121 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
122 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [299/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryColorUVPositionDataAdvancedBlend |
| ) |  |

Definition at line 124 of file aiks_dl_vertices_unittests.cc.

124 {
125 DisplayListBuilder builder;
126 DlPaint paint;
127 auto image =
128 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
129 auto size = image->impeller_texture()->GetSize();
130
131 paint.setColorSource(
132 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
133
134 std::vector<DlPoint> positions = {
135 DlPoint(0, 0), DlPoint(size.width, 0),
136 DlPoint(0, size.height), DlPoint(size.width, 0),
137 DlPoint(0, 0), DlPoint(size.width, size.height),
138 };
139 std::vector<DlColor> colors = {
140 DlColor::kRed().modulateOpacity(0.5),
141 DlColor::kBlue().modulateOpacity(0.5),
142 DlColor::kGreen().modulateOpacity(0.5),
143 DlColor::kRed().modulateOpacity(0.5),
144 DlColor::kBlue().modulateOpacity(0.5),
145 DlColor::kGreen().modulateOpacity(0.5),
146 };
147
148 auto vertices =
149 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
150
151 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
152 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
153 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [300/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionData |
| ) |  |

Definition at line 48 of file aiks_dl_vertices_unittests.cc.

48 {
49 DisplayListBuilder builder;
50 DlPaint paint;
51 auto image =
52 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
53 auto size = image->impeller_texture()->GetSize();
54
55 paint.setColorSource(
56 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp));
57
58 std::vector<DlPoint> vertex_coordinates = {
59 DlPoint(0, 0),
60 DlPoint(size.width, 0),
61 DlPoint(0, size.height),
62 };
63 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
64 {0, 1, 2}, {}, {});
65
66 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
67 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
68 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [301/525]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionDataWithTranslate |
| ) |  |

Definition at line 71 of file aiks_dl_vertices_unittests.cc.

71 {
72 DisplayListBuilder builder;
73 DlPaint paint;
74 auto image =
75 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
76 auto size = image->impeller_texture()->GetSize();
77
78 DlMatrix matrix = DlMatrix::MakeTranslation({100, 100});
79 paint.setColorSource(
80 DlColorSource::MakeImage(image, DlTileMode::kClamp, DlTileMode::kClamp,
81 DlImageSampling::kLinear, &matrix));
82
83 std::vector<DlPoint> positions = {
84 DlPoint(0, 0),
85 DlPoint(size.width, 0),
86 DlPoint(0, size.height),
87 };
88 auto vertices =
89 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
90
91 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [302/525]

impeller::testing::TEST_P | ( | AllocatorMTLTest | ,
|  | DebugTraceMemoryStatistics |
| ) |  |

Definition at line 29 of file allocator_mtl_unittests.mm.

29 {
30 auto& context_mtl = ContextMTL::Cast(*GetContext());
31 const auto& allocator = context_mtl.GetResourceAllocator();
32
33 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
34 0u);
35
36 // Memoryless texture does not increase allocated size.
37 {
38 TextureDescriptor desc;
39 desc.format = PixelFormat::kR8G8B8A8UNormInt;
40 desc.storage_mode = StorageMode::kDeviceTransient;
41 desc.size = {1024, 1024};
42 auto texture_1 = allocator->CreateTexture(desc);
43
44 // Private storage texture increases allocated size.
45 desc.storage_mode = StorageMode::kDevicePrivate;
46 auto texture_2 = allocator->CreateTexture(desc);
47
48 #ifdef IMPELLER_DEBUG
49 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
50 4u);
51 #else
52 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
53 0u);
54 #endif // IMPELLER_DEBUG
55
56 // Host storage texture increases allocated size.
57 desc.storage_mode = StorageMode::kHostVisible;
58 auto texture_3 = allocator->CreateTexture(desc);
59
60 #ifdef IMPELLER_DEBUG
61 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
62 8u);
63 #else
64 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
65 0u);
66 #endif // IMPELLER_DEBUG
67 }
68
69 // After all textures are out of scope, memory has been decremented.
70 EXPECT_EQ(allocator->DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize(),
71 0u);
72 }

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() [303/525]

impeller::testing::TEST_P | ( | AllocatorMTLTest | ,
|  | ManagedMemory |
| ) |  |

Definition at line 74 of file allocator_mtl_unittests.mm.

74 {
75 auto& context_mtl = ContextMTL::Cast(*GetContext());
76 auto allocator = std::make_unique<AllocatorMTL>(context_mtl.GetMTLDevice(),
77 "test-allocator");
78 allocator->DebugSetSupportsUMA(false);
79
80 DeviceBufferDescriptor desc;
81 desc.size = 100;
82 desc.storage_mode = StorageMode::kHostVisible;
83
84 auto buffer = allocator->CreateBuffer(desc);
85 ASSERT_TRUE(buffer);
86
87 EXPECT_NE(buffer->OnGetContents(), nullptr);
88 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::kHostVisible, impeller::DeviceBufferDescriptor::size, and impeller::DeviceBufferDescriptor::storage_mode.

## ◆ TEST_P() [304/525]

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() [305/525]

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() [306/525]

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() [307/525]

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() [308/525]

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() [309/525]

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() [310/525]

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() [311/525]

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() [312/525]

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() [313/525]

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() [314/525]

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() [315/525]

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() [316/525]

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() [317/525]

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() [318/525]

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() [319/525]

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() [320/525]

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() [321/525]

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() [322/525]

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() [323/525]

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() [324/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1174 of file dl_unittests.cc.

1174 {
1175 flutter::DisplayListBuilder builder;
1176
1177 {
1178 builder.SaveLayer(std::nullopt, nullptr);
1179 builder.Translate(100, 100);
1180 flutter::DlPaint paint;
1181 paint.setColor(flutter::DlColor::kRed());
1182 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1183 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1184 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1185 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1186 builder.Restore();
1187 }
1188 {
1189 builder.SaveLayer(std::nullopt, nullptr);
1190 builder.Translate(300, 100);
1191 flutter::DlPaint paint;
1192 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1193 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1194 paint.setColor(flutter::DlColor::kRed());
1195 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1196 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1197 builder.Restore();
1198 }
1199 {
1200 builder.SaveLayer(std::nullopt, nullptr);
1201 builder.Translate(100, 300);
1202 flutter::DlPaint paint;
1203 paint.setColor(flutter::DlColor::kRed());
1204 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1205 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1206 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1207 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1208 builder.Restore();
1209 }
1210 {
1211 builder.SaveLayer(std::nullopt, nullptr);
1212 builder.Translate(300, 300);
1213 flutter::DlPaint paint;
1214 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1215 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1216 paint.setColor(flutter::DlColor::kRed());
1217 paint.setBlendMode(flutter::DlBlendMode::kDst);
1218 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1219 builder.Restore();
1220 }
1221
1222 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1223 }

## ◆ TEST_P() [325/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 620 of file dl_unittests.cc.

620 {
621 auto texture = CreateTextureForFixture("boston.jpg");
622 const float inner_color_matrix[20] = {
623 1, 0, 0, 0, 0, //
624 0, 1, 0, 0, 0, //
625 0, 0, 1, 0, 0, //
626 0, 0, 0, 2, 0, //
627 };
628 const float outer_color_matrix[20] = {
629 1, 0, 0, 0, 0, //
630 0, 1, 0, 0, 0, //
631 0, 0, 1, 0, 0, //
632 0, 0, 0, 0.5, 0, //
633 };
634 auto inner_color_filter =
635 flutter::DlColorFilter::MakeMatrix(inner_color_matrix);
636 auto outer_color_filter =
637 flutter::DlColorFilter::MakeMatrix(outer_color_matrix);
638 auto inner = flutter::DlImageFilter::MakeColorFilter(inner_color_filter);
639 auto outer = flutter::DlImageFilter::MakeColorFilter(outer_color_filter);
640 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
641
642 flutter::DisplayListBuilder builder;
643 flutter::DlPaint paint;
644 paint.setImageFilter(compose.get());
645 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
646 flutter::DlImageSampling::kNearestNeighbor, &paint);
647 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
648 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [326/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 412 of file dl_unittests.cc.

412 {
413 flutter::DisplayListBuilder builder;
414 flutter::DlPaint paint;
415
416 paint.setColor(flutter::DlColor::kRed());
417 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
418 paint.setStrokeWidth(10);
419
420 builder.Translate(300, 300);
421
422 // Move to (50, 50) and draw lines from:
423 // 1. (50, height)
424 // 2. (width, height)
425 // 3. (width, 50)
426 flutter::DlPathBuilder path_builder;
427 path_builder.MoveTo(DlPoint(50, 50));
428 path_builder.LineTo(DlPoint(50, 100));
429 path_builder.LineTo(DlPoint(100, 100));
430 path_builder.LineTo(DlPoint(100, 50));
431 builder.DrawPath(DlPath(path_builder), paint);
432
433 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
434 }

## ◆ TEST_P() [327/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 151 of file dl_unittests.cc.

151 {
152 auto callback = [&]() {
153 static float start_angle = 45;
154 static float sweep_angle = 270;
155 static float stroke_width = 10;
156 static bool use_center = true;
157
158 static int selected_cap = 0;
159 const char* cap_names[] = {"Butt", "Round", "Square"};
160 flutter::DlStrokeCap cap;
161
162 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
163 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
164 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
165 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
166 ImGui::Combo("Cap", &selected_cap, cap_names,
167 sizeof(cap_names) / sizeof(char*));
168 ImGui::Checkbox("Use center", &use_center);
169 ImGui::End();
170
171 switch (selected_cap) {
172 case 0:
173 cap = flutter::DlStrokeCap::kButt;
174 break;
175 case 1:
176 cap = flutter::DlStrokeCap::kRound;
177 break;
178 case 2:
179 cap = flutter::DlStrokeCap::kSquare;
180 break;
181 default:
182 cap = flutter::DlStrokeCap::kButt;
183 break;
184 }
185
186 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
187 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
188 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
189
190 flutter::DisplayListBuilder builder;
191 flutter::DlPaint paint;
192
193 Vector2 scale = GetContentScale();
194 builder.Scale(scale.x, scale.y);
195 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
196 paint.setStrokeCap(cap);
197 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
198 paint.setStrokeMiter(10);
199 auto rect = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
200 paint.setColor(flutter::DlColor::kGreen());
201 paint.setStrokeWidth(2);
202 builder.DrawRect(rect, paint);
203 paint.setColor(flutter::DlColor::kRed());
204 paint.setStrokeWidth(stroke_width);
205 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
206
207 return builder.Build();
208 };
209 ASSERT_TRUE(OpenPlaygroundHere(callback));
210 }

References impeller::DrawPlaygroundLine(), scale, stroke_width, and impeller::Color::White().

## ◆ TEST_P() [328/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 650 of file dl_unittests.cc.

650 {
651 auto texture = CreateTextureForFixture("embarcadero.jpg");
652
653 auto callback = [&]() {
654 static float sigma[] = {10, 10};
655 static float ctm_scale = 1;
656 static bool use_bounds = true;
657 static bool draw_circle = true;
658 static bool add_clip = true;
659
660 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
661 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
662 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
663 ImGui::NewLine();
664 ImGui::TextWrapped(
665 "If everything is working correctly, none of the options below should "
666 "impact the filter's appearance.");
667 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
668 ImGui::Checkbox("Draw child element", &draw_circle);
669 ImGui::Checkbox("Add pre-clip", &add_clip);
670 ImGui::End();
671
672 flutter::DisplayListBuilder builder;
673
674 Vector2 scale = ctm_scale * GetContentScale();
675 builder.Scale(scale.x, scale.y);
676
677 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
678 flutter::DlTileMode::kClamp);
679
680 std::optional<DlRect> bounds;
681 if (use_bounds) {
682 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
683 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
684 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
685 bounds = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
686 }
687
688 // Insert a clip to test that the backdrop filter handles stencil depths > 0
689 // correctly.
690 if (add_clip) {
691 builder.ClipRect(DlRect::MakeLTRB(0, 0, 99999, 99999),
692 flutter::DlClipOp::kIntersect, true);
693 }
694
695 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
696 flutter::DlImageSampling::kNearestNeighbor, nullptr);
697 builder.SaveLayer(bounds, nullptr, &filter);
698
699 if (draw_circle) {
700 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
701 auto circle_center = DrawPlaygroundPoint(center_point);
702
703 flutter::DlPaint paint;
704 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
705 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
706 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
707 paint.setStrokeWidth(10);
708 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
709 builder.DrawCircle(DlPoint(circle_center.x, circle_center.y), 100, paint);
710 }
711
712 return builder.Build();
713 };
714
715 ASSERT_TRUE(OpenPlaygroundHere(callback));
716 }

References impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::DlImageImpeller::Make(), impeller::Color::Red(), scale, and impeller::Color::White().

## ◆ TEST_P() [329/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 102 of file dl_unittests.cc.

102 {
103 flutter::DisplayListBuilder builder;
104 flutter::DlPaint paint;
105
106 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
107 paint.setStrokeWidth(30);
108 paint.setColor(flutter::DlColor::kRed());
109
110 flutter::DlPathBuilder path_builder;
111 path_builder.MoveTo(DlPoint(-50, 0));
112 path_builder.LineTo(DlPoint(0, -50));
113 path_builder.LineTo(DlPoint(50, 0));
114 flutter::DlPath path(path_builder);
115
116 builder.Translate(100, 100);
117 {
118 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
119 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
120 paint.setStrokeMiter(4);
121 builder.DrawPath(path, paint);
122 }
123
124 {
125 builder.Save();
126 builder.Translate(0, 100);
127 // The joint in the path is 45 degrees. A miter length of 1 convert to a
128 // bevel in this case.
129 paint.setStrokeMiter(1);
130 builder.DrawPath(path, paint);
131 builder.Restore();
132 }
133
134 builder.Translate(150, 0);
135 {
136 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
137 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
138 builder.DrawPath(path, paint);
139 }
140
141 builder.Translate(150, 0);
142 {
143 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
144 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
145 builder.DrawPath(path, paint);
146 }
147
148 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
149 }

## ◆ TEST_P() [330/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1225 of file dl_unittests.cc.

1225 {
1226 flutter::DisplayListBuilder builder;
1227 const float green_color_matrix[20] = {
1228 0, 0, 0, 0, 0, //
1229 0, 0, 0, 0, 1, //
1230 0, 0, 0, 0, 0, //
1231 0, 0, 0, 1, 0, //
1232 };
1233 const float blue_color_matrix[20] = {
1234 0, 0, 0, 0, 0, //
1235 0, 0, 0, 0, 0, //
1236 0, 0, 0, 0, 1, //
1237 0, 0, 0, 1, 0, //
1238 };
1239 auto green_color_filter =
1240 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1241 auto blue_color_filter =
1242 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1243 auto blue_image_filter =
1244 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1245
1246 flutter::DlPaint paint;
1247 paint.setColor(flutter::DlColor::kRed());
1248 paint.setColorFilter(green_color_filter);
1249 paint.setImageFilter(blue_image_filter);
1250 builder.DrawRect(DlRect::MakeLTRB(100, 100, 500, 500), paint);
1251 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1252 }

## ◆ TEST_P() [331/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 94 of file dl_unittests.cc.

94 {
95 auto texture = CreateTextureForFixture("embarcadero.jpg");
96 flutter::DisplayListBuilder builder;
97 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
98 flutter::DlImageSampling::kNearestNeighbor, nullptr);
99 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
100 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [332/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 718 of file dl_unittests.cc.

718 {
719 // Image is drawn with corners to scale and center pieces stretched to fit.
720 auto texture = CreateTextureForFixture("embarcadero.jpg");
721 flutter::DisplayListBuilder builder;
722 auto size = texture->GetSize();
723 builder.DrawImageNine(
724 DlImageImpeller::Make(texture),
725 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
726 size.height * 3 / 4),
727 DlRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
728 flutter::DlFilterMode::kNearest, nullptr);
729 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
730 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [333/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 764 of file dl_unittests.cc.

764 {
765 // Edge case, the width and height of the corners does not leave any
766 // room for the center slices. Only the corners are displayed.
767 auto texture = CreateTextureForFixture("embarcadero.jpg");
768 flutter::DisplayListBuilder builder;
769 auto size = texture->GetSize();
770 builder.DrawImageNine(
771 DlImageImpeller::Make(texture),
772 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
773 size.height * 3 / 4),
774 DlRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
775 flutter::DlFilterMode::kNearest, nullptr);
776 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
777 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [334/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 748 of file dl_unittests.cc.

748 {
749 // Edge case, the height of the corners does not leave any room for the
750 // center slice. The center (across the horizontal axis) is folded out of the
751 // resulting image.
752 auto texture = CreateTextureForFixture("embarcadero.jpg");
753 flutter::DisplayListBuilder builder;
754 auto size = texture->GetSize();
755 builder.DrawImageNine(
756 DlImageImpeller::Make(texture),
757 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
758 size.height * 3 / 4),
759 DlRect::MakeLTRB(0, 0, size.width, size.height / 2),
760 flutter::DlFilterMode::kNearest, nullptr);
761 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
762 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [335/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 732 of file dl_unittests.cc.

732 {
733 // Edge case, the width of the corners does not leave any room for the
734 // center slice. The center (across the vertical axis) is folded out of the
735 // resulting image.
736 auto texture = CreateTextureForFixture("embarcadero.jpg");
737 flutter::DisplayListBuilder builder;
738 auto size = texture->GetSize();
739 builder.DrawImageNine(
740 DlImageImpeller::Make(texture),
741 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
742 size.height * 3 / 4),
743 DlRect::MakeLTRB(0, 0, size.width / 2, size.height),
744 flutter::DlFilterMode::kNearest, nullptr);
745 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
746 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [336/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 779 of file dl_unittests.cc.

779 {
780 // Edge case, there is not enough room for the corners to be drawn
781 // without scaling them down.
782 auto texture = CreateTextureForFixture("embarcadero.jpg");
783 flutter::DisplayListBuilder builder;
784 auto size = texture->GetSize();
785 builder.DrawImageNine(
786 DlImageImpeller::Make(texture),
787 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
788 size.height * 3 / 4),
789 DlRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
790 flutter::DlFilterMode::kNearest, nullptr);
791 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
792 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [337/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1122 of file dl_unittests.cc.

1122 {
1123 const flutter::DlColor colors[2] = {
1124 flutter::DlColor(0xFFF44336),
1125 flutter::DlColor(0xFF2196F3),
1126 };
1127 const float stops[2] = {0.0, 1.0};
1128 flutter::DlPaint paint;
1129 flutter::DisplayListBuilder builder;
1130 auto clip_bounds = DlRect::MakeWH(300.0, 300.0);
1131 builder.Save();
1132 builder.Translate(100, 100);
1133 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1134 auto linear =
1135 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1136 stops, flutter::DlTileMode::kRepeat);
1137 paint.setColorSource(linear);
1138 builder.DrawPaint(paint);
1139 builder.Restore();
1140
1141 builder.Save();
1142 builder.Translate(500, 100);
1143 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1144 auto radial = flutter::DlColorSource::MakeRadial(
1145 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1146 paint.setColorSource(radial);
1147 builder.DrawPaint(paint);
1148 builder.Restore();
1149
1150 builder.Save();
1151 builder.Translate(100, 500);
1152 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1153 auto sweep =
1154 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1155 stops, flutter::DlTileMode::kRepeat);
1156 paint.setColorSource(sweep);
1157 builder.DrawPaint(paint);
1158 builder.Restore();
1159
1160 builder.Save();
1161 builder.Translate(500, 500);
1162 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1163 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1164 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1165 flutter::DlTileMode::kRepeat,
1166 flutter::DlTileMode::kRepeat);
1167 paint.setColorSource(image);
1168 builder.DrawPaint(paint);
1169 builder.Restore();
1170
1171 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1172 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [338/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 806 of file dl_unittests.cc.

806 {
807 flutter::DisplayListBuilder builder;
808 DlPoint points[7] = {
809 {0, 0}, //
810 {100, 100}, //
811 {100, 0}, //
812 {0, 100}, //
813 {0, 0}, //
814 {48, 48}, //
815 {52, 52}, //
816 };
817 std::vector<flutter::DlStrokeCap> caps = {
818 flutter::DlStrokeCap::kButt,
819 flutter::DlStrokeCap::kRound,
820 flutter::DlStrokeCap::kSquare,
821 };
822 flutter::DlPaint paint =
823 flutter::DlPaint() //
824 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
825 .setStrokeWidth(20);
826 builder.Translate(50, 50);
827 for (auto cap : caps) {
828 paint.setStrokeCap(cap);
829 builder.Save();
830 builder.DrawPoints(flutter::DlPointMode::kPoints, 7, points, paint);
831 builder.Translate(150, 0);
832 builder.DrawPoints(flutter::DlPointMode::kLines, 5, points, paint);
833 builder.Translate(150, 0);
834 builder.DrawPoints(flutter::DlPointMode::kPolygon, 5, points, paint);
835 builder.Restore();
836 builder.Translate(0, 150);
837 }
838 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
839 }

## ◆ TEST_P() [339/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 45 of file dl_unittests.cc.

45 {
46 flutter::DisplayListBuilder builder;
47 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100),
48 flutter::DlPaint(flutter::DlColor::kBlue()));
49 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
50 }

## ◆ TEST_P() [340/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1108 of file dl_unittests.cc.

1108 {
1109 flutter::DlPaint paint;
1110 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1111 flutter::DisplayListBuilder builder;
1112 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1113 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1114 builder.Translate(0, 200);
1115
1116 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1117 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1118
1119 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1120 }

## ◆ TEST_P() [341/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 864 of file dl_unittests.cc.

864 {
865 flutter::DisplayListBuilder builder;
866 flutter::DlPaint paint;
867
868 auto content_scale = GetContentScale() * 0.8;
869 builder.Scale(content_scale.x, content_scale.y);
870
871 constexpr size_t star_spikes = 5;
872 constexpr DlScalar half_spike_rotation = kPi / star_spikes;
873 constexpr DlScalar radius = 40;
874 constexpr DlScalar spike_size = 10;
875 constexpr DlScalar outer_radius = radius + spike_size;
876 constexpr DlScalar inner_radius = radius - spike_size;
877 std::array<DlPoint, star_spikes * 2> star;
878 for (size_t i = 0; i < star_spikes; i++) {
879 const DlScalar rotation = half_spike_rotation * i * 2;
880 star[i * 2] = DlPoint(50 + std::sin(rotation) * outer_radius,
881 50 - std::cos(rotation) * outer_radius);
882 star[i * 2 + 1] =
883 DlPoint(50 + std::sin(rotation + half_spike_rotation) * inner_radius,
884 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
885 }
886
887 std::array<DlPath, 4> paths = {
888 DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100)),
889 DlPath::MakeRoundRectXY(DlRect::MakeXYWH(20, 0, 200, 100), 30, 30),
890 DlPath::MakeCircle(DlPoint(100, 50), 50),
891 DlPath::MakePoly(star.data(), star.size(), true),
892 };
893 paint.setColor(flutter::DlColor::kWhite());
894 builder.DrawPaint(paint);
895 paint.setColor(flutter::DlColor::kCyan());
896 builder.Translate(100, 50);
897 for (size_t x = 0; x < paths.size(); x++) {
898 builder.Save();
899 for (size_t y = 0; y < 6; y++) {
900 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
901 1);
902 builder.DrawPath(paths[x], paint);
903 builder.Translate(0, 150);
904 }
905 builder.Restore();
906 builder.Translate(250, 0);
907 }
908
909 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
910 }

References impeller::kPi, and x.

## ◆ TEST_P() [342/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 472 of file dl_unittests.cc.

472 {
473 flutter::DisplayListBuilder builder;
474 flutter::DlPaint paint;
475
476 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
477 paint.setColor(flutter::DlColor::kRed());
478 builder.DrawTextBlob(
479 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
480 250, 250, paint);
481
482 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
483 }

## ◆ TEST_P() [343/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 52 of file dl_unittests.cc.

52 {
53 flutter::DisplayListBuilder builder;
54 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
55 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
56 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
57 }

## ◆ TEST_P() [344/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 59 of file dl_unittests.cc.

59 {
60 flutter::DisplayListBuilder builder;
61
62 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
63 flutter::DlColor::kRed()};
64 const float stops[2] = {0.0, 1.0};
65
66 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
67 2, colors.data(), stops,
68 flutter::DlTileMode::kClamp);
69 flutter::DlPaint paint;
70 paint.setColorSource(linear);
71
72 builder.DrawTextBlob(
73 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
74 paint);
75 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
76 }

## ◆ TEST_P() [345/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 78 of file dl_unittests.cc.

78 {
79 flutter::DisplayListBuilder builder;
80 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
81 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
82
83 flutter::DlPaint save_paint;
84 float alpha = 0.5;
85 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
86 builder.SaveLayer(std::nullopt, &save_paint);
87 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
88 CreateTestFontOfSize(100)),
89 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
90 builder.Restore();
91 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
92 }

## ◆ TEST_P() [346/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 524 of file dl_unittests.cc.

524 {
525 auto texture = CreateTextureForFixture("embarcadero.jpg");
526 flutter::DisplayListBuilder builder;
527 flutter::DlPaint paint;
528
529 // Pipeline blended image.
530 {
531 auto filter = flutter::DlColorFilter::MakeBlend(
532 flutter::DlColor::kYellow(), flutter::DlBlendMode::kModulate);
533 paint.setColorFilter(filter);
534 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
535 flutter::DlImageSampling::kNearestNeighbor, &paint);
536 }
537
538 // Advanced blended image.
539 {
540 auto filter = flutter::DlColorFilter::MakeBlend(
541 flutter::DlColor::kRed(), flutter::DlBlendMode::kScreen);
542 paint.setColorFilter(filter);
543 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(250, 250),
544 flutter::DlImageSampling::kNearestNeighbor, &paint);
545 }
546
547 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
548 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [347/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 550 of file dl_unittests.cc.

550 {
551 const float invert_color_matrix[20] = {
552 -1, 0, 0, 0, 1, //
553 0, -1, 0, 0, 1, //
554 0, 0, -1, 0, 1, //
555 0, 0, 0, 1, 0, //
556 };
557 auto texture = CreateTextureForFixture("boston.jpg");
558 flutter::DisplayListBuilder builder;
559 flutter::DlPaint paint;
560
561 auto color_filter = flutter::DlColorFilter::MakeMatrix(invert_color_matrix);
562 auto image_filter = flutter::DlImageFilter::MakeColorFilter(color_filter);
563
564 paint.setImageFilter(image_filter);
565 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
566 flutter::DlImageSampling::kNearestNeighbor, &paint);
567
568 builder.Translate(0, 700);
569 paint.setColorFilter(color_filter);
570 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
571 flutter::DlImageSampling::kNearestNeighbor, &paint);
572 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
573 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [348/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 600 of file dl_unittests.cc.

600 {
601 auto texture = CreateTextureForFixture("boston.jpg");
602 flutter::DisplayListBuilder builder;
603 flutter::DlPaint paint;
604
605 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
606 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
607 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
608 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
609
610 paint.setImageFilter(open.get());
611 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
612 flutter::DlImageSampling::kNearestNeighbor, &paint);
613 builder.Translate(0, 700);
614 paint.setImageFilter(close.get());
615 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
616 flutter::DlImageSampling::kNearestNeighbor, &paint);
617 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
618 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [349/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 575 of file dl_unittests.cc.

575 {
576 auto texture = CreateTextureForFixture("embarcadero.jpg");
577
578 auto callback = [&]() {
579 static float sigma[] = {10, 10};
580
581 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
582 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
583 ImGui::End();
584
585 flutter::DisplayListBuilder builder;
586 flutter::DlPaint paint;
587
588 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
589 flutter::DlTileMode::kClamp);
590 paint.setImageFilter(&filter);
591 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
592 flutter::DlImageSampling::kNearestNeighbor, &paint);
593
594 return builder.Build();
595 };
596
597 ASSERT_TRUE(OpenPlaygroundHere(callback));
598 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [350/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 436 of file dl_unittests.cc.

436 {
437 auto texture = CreateTextureForFixture("embarcadero.jpg");
438 flutter::DisplayListBuilder builder;
439 flutter::DlPaint paint;
440
441 // Mask blurred image.
442 {
443 auto filter =
444 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
445 paint.setMaskFilter(&filter);
446 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
447 flutter::DlImageSampling::kNearestNeighbor, &paint);
448 }
449
450 // Mask blurred filled path.
451 {
452 paint.setColor(flutter::DlColor::kYellow());
453 auto filter =
454 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
455 paint.setMaskFilter(&filter);
456 builder.DrawArc(DlRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
457 }
458
459 // Mask blurred text.
460 {
461 auto filter =
462 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
463 paint.setMaskFilter(&filter);
464 builder.DrawTextBlob(
465 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
466 paint);
467 }
468
469 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
470 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [351/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 946 of file dl_unittests.cc.

946 {
947 auto boston = CreateTextureForFixture("boston.jpg");
948
949 auto callback = [&]() {
950 static int selected_matrix_type = 0;
951 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
952
953 static float ctm_translation[2] = {200, 200};
954 static float ctm_scale[2] = {0.65, 0.65};
955 static float ctm_skew[2] = {0, 0};
956
957 static bool enable = true;
958 static float translation[2] = {100, 100};
959 static float scale[2] = {0.8, 0.8};
960 static float skew[2] = {0.2, 0.2};
961
962 static bool enable_savelayer = true;
963
964 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
965 {
966 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
967 sizeof(matrix_type_names) / sizeof(char*));
968
969 ImGui::TextWrapped("Current Transform");
970 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
971 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
972 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
973
974 ImGui::TextWrapped(
975 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
976 "The only difference is that MatrixFilter doesn't affect the effect "
977 "transform, whereas LocalMatrixFilter does.");
978 // Note: See this behavior in:
979 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
980 ImGui::Checkbox("Enable", &enable);
981 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
982 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
983 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
984
985 ImGui::TextWrapped(
986 "Rendering the filtered image within a layer can expose bounds "
987 "issues. If the rendered image gets cut off when this setting is "
988 "enabled, there's a coverage bug in the filter.");
989 ImGui::Checkbox("Render in layer", &enable_savelayer);
990 }
991 ImGui::End();
992
993 flutter::DisplayListBuilder builder;
994 flutter::DlPaint paint;
995
996 if (enable_savelayer) {
997 builder.SaveLayer(std::nullopt, nullptr);
998 }
999 {
1000 auto content_scale = GetContentScale();
1001 builder.Scale(content_scale.x, content_scale.y);
1002
1003 // Set the current transform
1004 auto ctm_matrix = Matrix::MakeRow(
1005 ctm_scale[0], ctm_skew[0], 0.0f, ctm_translation[0], //
1006 ctm_skew[1], ctm_scale[1], 0.0f, ctm_translation[1], //
1007 0, 0, 1, 0, //
1008 0, 0, 0, 1);
1009 builder.Transform(ctm_matrix);
1010
1011 // Set the matrix filter
1012 auto filter_matrix =
1013 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1014 skew[1], scale[1], 0.0f, translation[1], //
1015 0.0f, 0.0f, 1.0f, 0.0f, //
1016 0.0f, 0.0f, 0.0f, 1.0f);
1017
1018 if (enable) {
1019 switch (selected_matrix_type) {
1020 case 0: {
1021 auto filter = flutter::DlMatrixImageFilter(
1022 filter_matrix, flutter::DlImageSampling::kLinear);
1023 paint.setImageFilter(&filter);
1024 break;
1025 }
1026 case 1: {
1027 auto internal_filter =
1028 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1029 .shared();
1030 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1031 internal_filter);
1032 paint.setImageFilter(&filter);
1033 break;
1034 }
1035 }
1036 }
1037
1038 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(),
1039 flutter::DlImageSampling::kLinear, &paint);
1040 }
1041 if (enable_savelayer) {
1042 builder.Restore();
1043 }
1044
1045 return builder.Build();
1046 };
1047
1048 ASSERT_TRUE(OpenPlaygroundHere(callback));
1049 }

References impeller::DlImageImpeller::Make(), impeller::Matrix::MakeRow(), and scale.

## ◆ TEST_P() [352/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1051 of file dl_unittests.cc.

1051 {
1052 auto callback = [&]() {
1053 static float translation[2] = {0, 0};
1054 static bool enable_save_layer = true;
1055
1056 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1057 ImGui::SliderFloat2("Translation", translation, -130, 130);
1058 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1059 ImGui::End();
1060
1061 flutter::DisplayListBuilder builder;
1062 builder.Save();
1063 builder.Scale(2.0, 2.0);
1064 flutter::DlPaint paint;
1065 paint.setColor(flutter::DlColor::kYellow());
1066 builder.DrawRect(DlRect::MakeWH(300, 300), paint);
1067 paint.setStrokeWidth(1.0);
1068 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1069 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1070 builder.DrawLine(DlPoint(150, 0), DlPoint(150, 300), paint);
1071 builder.DrawLine(DlPoint(0, 150), DlPoint(300, 150), paint);
1072
1073 flutter::DlPaint save_paint;
1074 DlRect bounds = DlRect::MakeXYWH(100, 100, 100, 100);
1075 Matrix translate_matrix =
1076 Matrix::MakeTranslation({translation[0], translation[1]});
1077 if (enable_save_layer) {
1078 auto filter = flutter::DlMatrixImageFilter(
1079 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1080 save_paint.setImageFilter(filter.shared());
1081 builder.SaveLayer(bounds, &save_paint);
1082 } else {
1083 builder.Save();
1084 builder.Transform(translate_matrix);
1085 }
1086
1087 Matrix filter_matrix;
1088 filter_matrix.Translate({150, 150});
1089 filter_matrix.Scale({0.2f, 0.2f});
1090 filter_matrix.Translate({-150, -150});
1091 auto filter = flutter::DlMatrixImageFilter(
1092 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1093
1094 save_paint.setImageFilter(filter.shared());
1095
1096 builder.SaveLayer(bounds, &save_paint);
1097 flutter::DlPaint paint2;
1098 paint2.setColor(flutter::DlColor::kBlue());
1099 builder.DrawRect(bounds, paint2);
1100 builder.Restore();
1101 builder.Restore();
1102 return builder.Build();
1103 };
1104
1105 ASSERT_TRUE(OpenPlaygroundHere(callback));
1106 }

References impeller::Matrix::MakeTranslation(), impeller::Matrix::Scale(), and impeller::Matrix::Translate().

## ◆ TEST_P() [353/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 393 of file dl_unittests.cc.

393 {
394 flutter::DisplayListBuilder builder;
395 flutter::DlPaint paint;
396
397 paint.setColor(flutter::DlColor::kRed());
398 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
399
400 builder.Translate(300, 300);
401 flutter::DlPathBuilder path_builder;
402 path_builder.AddCircle(DlPoint(0, 0), 100);
403 path_builder.AddCircle(DlPoint(0, 0), 50);
404 builder.DrawPath(DlPath(path_builder, flutter::DlPathFillType::kOdd), paint);
405
406 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
407 }

## ◆ TEST_P() [354/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 841 of file dl_unittests.cc.

841 {
842 flutter::DisplayListBuilder builder;
843 std::vector<flutter::DlStrokeCap> caps = {
844 flutter::DlStrokeCap::kButt,
845 flutter::DlStrokeCap::kRound,
846 flutter::DlStrokeCap::kSquare,
847 };
848 flutter::DlPaint paint =
849 flutter::DlPaint() //
850 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
851 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
852 .setStrokeCap(flutter::DlStrokeCap::kButt) //
853 .setStrokeWidth(20);
854 DlPath path = DlPath::MakeLine({150, 50}, {150, 50});
855 for (auto cap : caps) {
856 paint.setStrokeCap(cap);
857 builder.DrawLine(DlPoint(50, 50), DlPoint(50, 50), paint);
858 builder.DrawPath(path, paint);
859 builder.Translate(0, 150);
860 }
861 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
862 }

## ◆ TEST_P() [355/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 912 of file dl_unittests.cc.

912 {
913 flutter::DisplayListBuilder builder;
914 std::vector<flutter::DlStrokeCap> caps = {
915 flutter::DlStrokeCap::kButt,
916 flutter::DlStrokeCap::kRound,
917 flutter::DlStrokeCap::kSquare,
918 };
919 flutter::DlPaint paint = //
920 flutter::DlPaint() //
921 .setColor(flutter::DlColor::kWhite()) //
922 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
923 .setStrokeWidth(0);
924 flutter::DlPaint outline_paint = //
925 flutter::DlPaint() //
926 .setColor(flutter::DlColor::kYellow()) //
927 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
928 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
929 .setStrokeWidth(1);
930 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
931 for (auto cap : caps) {
932 paint.setStrokeCap(cap);
933 builder.DrawLine(DlPoint(50, 50), DlPoint(60, 50), paint);
934 builder.DrawRect(DlRect::MakeLTRB(45, 45, 65, 55), outline_paint);
935 builder.DrawLine(DlPoint{100, 50}, DlPoint{100, 50}, paint);
936 if (cap != flutter::DlStrokeCap::kButt) {
937 builder.DrawRect(DlRect::MakeLTRB(95, 45, 105, 55), outline_paint);
938 }
939 builder.DrawPath(path, paint);
940 builder.DrawRect(path.GetBounds().Expand(5, 5), outline_paint);
941 builder.Translate(0, 150);
942 }
943 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
944 }

## ◆ TEST_P() [356/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1341 of file dl_unittests.cc.

1341 {
1342 flutter::DisplayListBuilder builder;
1343
1344 flutter::DlPaint fill_paint = //
1345 flutter::DlPaint() //
1346 .setColor(flutter::DlColor::kBlue()) //
1347 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1348 .setStrokeWidth(10);
1349 flutter::DlPaint stroke_paint = //
1350 flutter::DlPaint() //
1351 .setColor(flutter::DlColor::kGreen()) //
1352 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1353 .setStrokeWidth(10);
1354
1355 builder.DrawRoundRect(
1356 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1357 fill_paint);
1358 builder.DrawRoundRect(
1359 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1360 stroke_paint);
1361
1362 builder.DrawRoundRect(
1363 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1364 fill_paint);
1365 builder.DrawRoundRect(
1366 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1367 stroke_paint);
1368
1369 flutter::DlPaint reference_paint = //
1370 flutter::DlPaint() //
1371 .setColor(flutter::DlColor::kMidGrey()) //
1372 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1373 .setStrokeWidth(10);
1374
1375 builder.DrawRoundRect(
1376 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1377 reference_paint);
1378 builder.DrawRoundRect(
1379 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1380 reference_paint);
1381
1382 flutter::DlPaint clip_fill_paint = //
1383 flutter::DlPaint() //
1384 .setColor(flutter::DlColor::kCyan()) //
1385 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1386 .setStrokeWidth(10);
1387
1388 builder.Save();
1389 builder.ClipRoundRect(
1390 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1391 builder.DrawPaint(clip_fill_paint);
1392 builder.Restore();
1393
1394 builder.Save();
1395 builder.ClipRoundRect(
1396 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1397 builder.DrawPaint(clip_fill_paint);
1398 builder.Restore();
1399
1400 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1401 }

## ◆ TEST_P() [357/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1517 of file dl_unittests.cc.

1517 {
1518 flutter::DisplayListBuilder builder;
1519 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1520 Vector2 scale = GetContentScale();
1521 builder.Scale(scale.x, scale.y);
1522
1523 builder.Save();
1524 // We need a small transform op to avoid a deferred save
1525 builder.Translate(1.0f, 1.0f);
1526 auto solid_filter =
1527 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1528 flutter::DlPaint solid_alpha_paint =
1529 flutter::DlPaint() //
1530 .setMaskFilter(solid_filter) //
1531 .setColor(flutter::DlColor::kBlue()) //
1532 .setAlpha(0x7f);
1533 for (int x = 1; x <= 4; x++) {
1534 for (int y = 1; y <= 4; y++) {
1535 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1536 solid_alpha_paint);
1537 }
1538 }
1539 builder.Restore();
1540
1541 builder.Save();
1542 builder.Translate(500.0f, 0.0f);
1543 auto normal_filter =
1544 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1545 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1546 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1547 flutter::DlPaint normal_if_paint =
1548 flutter::DlPaint() //
1549 .setMaskFilter(solid_filter) //
1550 .setImageFilter(rotate_if) //
1551 .setColor(flutter::DlColor::kGreen()) //
1552 .setAlpha(0x7f);
1553 for (int x = 1; x <= 4; x++) {
1554 for (int y = 1; y <= 4; y++) {
1555 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1556 normal_if_paint);
1557 }
1558 }
1559 builder.Restore();
1560
1561 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1562 }

References impeller::Matrix::MakeRotationZ(), scale, and x.

## ◆ TEST_P() [358/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1494 of file dl_unittests.cc.

1494 {
1495 flutter::DisplayListBuilder builder;
1496 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1497
1498 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1499 builder.DrawCircle(DlPoint(300, 300), 200,
1500 flutter::DlPaint().setMaskFilter(&filter));
1501
1502 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1503 flutter::DlColor::kGreen()};
1504 const float stops[2] = {0.0, 1.0};
1505 auto linear = flutter::DlColorSource::MakeLinear(
1506 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1507 flutter::DlTileMode::kRepeat);
1508 flutter::DlPaint blend_paint =
1509 flutter::DlPaint() //
1510 .setColorSource(linear) //
1511 .setBlendMode(flutter::DlBlendMode::kScreen);
1512 builder.DrawPaint(blend_paint);
1513
1514 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1515 }

## ◆ TEST_P() [359/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1302 of file dl_unittests.cc.

1302 {
1303 flutter::DisplayListBuilder builder;
1304 std::vector<flutter::DlStrokeJoin> joins = {
1305 flutter::DlStrokeJoin::kBevel,
1306 flutter::DlStrokeJoin::kRound,
1307 flutter::DlStrokeJoin::kMiter,
1308 };
1309 flutter::DlPaint paint = //
1310 flutter::DlPaint() //
1311 .setColor(flutter::DlColor::kWhite()) //
1312 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1313 .setStrokeWidth(10);
1314 flutter::DlPaint stroke_paint = //
1315 flutter::DlPaint() //
1316 .setColor(flutter::DlColor::kWhite()) //
1317 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1318 .setStrokeWidth(10);
1319 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1320
1321 builder.Translate(300, 50);
1322 builder.Scale(0.8, 0.8);
1323 for (auto join : joins) {
1324 paint.setStrokeJoin(join);
1325 stroke_paint.setStrokeJoin(join);
1326 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1327 builder.DrawRect(DlRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1328 builder.DrawRoundRect(
1329 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 0, 100, 100), 30, 30),
1330 paint);
1331 builder.DrawRoundRect(
1332 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1333 stroke_paint);
1334 builder.DrawCircle(DlPoint(350, 50), 50, paint);
1335 builder.DrawCircle(DlPoint(350, 200), 50, stroke_paint);
1336 builder.Translate(0, 300);
1337 }
1338 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1339 }

## ◆ TEST_P() [360/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1403 of file dl_unittests.cc.

1403 {
1404 std::vector<const char*> blend_mode_names;
1405 std::vector<flutter::DlBlendMode> blend_mode_values;
1406 {
1407 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1408 // Pipeline blends (Porter-Duff alpha compositing)
1409 {"Clear", flutter::DlBlendMode::kClear},
1410 {"Source", flutter::DlBlendMode::kSrc},
1411 {"Destination", flutter::DlBlendMode::kDst},
1412 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1413 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1414 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1415 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1416 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1417 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1418 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1419 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1420 {"Xor", flutter::DlBlendMode::kXor},
1421 {"Plus", flutter::DlBlendMode::kPlus},
1422 {"Modulate", flutter::DlBlendMode::kModulate},
1423 // Advanced blends (color component blends)
1424 {"Screen", flutter::DlBlendMode::kScreen},
1425 {"Overlay", flutter::DlBlendMode::kOverlay},
1426 {"Darken", flutter::DlBlendMode::kDarken},
1427 {"Lighten", flutter::DlBlendMode::kLighten},
1428 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1429 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1430 {"HardLight", flutter::DlBlendMode::kHardLight},
1431 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1432 {"Difference", flutter::DlBlendMode::kDifference},
1433 {"Exclusion", flutter::DlBlendMode::kExclusion},
1434 {"Multiply", flutter::DlBlendMode::kMultiply},
1435 {"Hue", flutter::DlBlendMode::kHue},
1436 {"Saturation", flutter::DlBlendMode::kSaturation},
1437 {"Color", flutter::DlBlendMode::kColor},
1438 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1439 };
1440 assert(blends.size() ==
1441 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1442 for (const auto& [name, mode] : blends) {
1443 blend_mode_names.push_back(name);
1444 blend_mode_values.push_back(mode);
1445 }
1446 }
1447
1448 auto callback = [&]() {
1449 static int current_blend_index = 3;
1450 static float dst_alpha = 1;
1451 static float src_alpha = 1;
1452 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1453 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1454 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1455 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1456
1457 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1458 {
1459 ImGui::ListBox("Blending mode", &current_blend_index,
1460 blend_mode_names.data(), blend_mode_names.size());
1461 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1462 ImGui::ColorEdit4("Color A", color0);
1463 ImGui::ColorEdit4("Color B", color1);
1464 ImGui::ColorEdit4("Color C", color2);
1465 ImGui::ColorEdit4("Source Color", src_color);
1466 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1467 }
1468 ImGui::End();
1469
1470 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1471 DlPoint(200, 100), //
1472 DlPoint(300, 300)};
1473 std::vector<flutter::DlColor> colors = {
1474 toColor(color0).modulateOpacity(dst_alpha),
1475 toColor(color1).modulateOpacity(dst_alpha),
1476 toColor(color2).modulateOpacity(dst_alpha)};
1477
1478 auto vertices = flutter::DlVertices::Make(
1479 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1480 /*texture_coordinates=*/nullptr, colors.data());
1481
1482 flutter::DisplayListBuilder builder;
1483 flutter::DlPaint paint;
1484
1485 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1486 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1487 paint);
1488 return builder.Build();
1489 };
1490
1491 ASSERT_TRUE(OpenPlaygroundHere(callback));
1492 }
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:37

References toColor().

## ◆ TEST_P() [361/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 511 of file dl_unittests.cc.

511 {
512 auto texture = CreateTextureForFixture("embarcadero.jpg");
513 flutter::DisplayListBuilder builder;
514 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
515 flutter::DlPaint paint;
516 paint.setMaskFilter(&filter);
517 builder.SaveLayer(std::nullopt, &paint);
518 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
519 flutter::DlImageSampling::kNearestNeighbor);
520 builder.Restore();
521 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
522 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [362/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1254 of file dl_unittests.cc.

1254 {
1255 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1256 flutter::DlBlurStyle::kNormal, 10);
1257
1258 flutter::DisplayListBuilder builder;
1259
1260 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1261 flutter::DlColor::kGreen()};
1262 std::array<float, 2> stops = {0, 1};
1263 auto texture = CreateTextureForFixture("airplane.jpg");
1264 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1265 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1266 flutter::DlColorSource::MakeImage(
1267 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1268 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1269 &matrix),
1270 flutter::DlColorSource::MakeLinear(
1271 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1272 stops.data(), flutter::DlTileMode::kClamp),
1273 };
1274
1275 builder.Save();
1276 builder.Translate(0, 100);
1277 for (const auto& color_source : color_sources) {
1278 flutter::DlPaint paint;
1279 paint.setColorSource(color_source);
1280 paint.setMaskFilter(blur_filter);
1281
1282 builder.Save();
1283 builder.Translate(100, 0);
1284 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1285 builder.DrawRoundRect(
1286 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1287
1288 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1289 paint.setStrokeWidth(10);
1290 builder.Translate(200, 0);
1291 builder.DrawRoundRect(
1292 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1293
1294 builder.Restore();
1295 builder.Translate(0, 100);
1296 }
1297 builder.Restore();
1298
1299 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1300 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [363/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 794 of file dl_unittests.cc.

794 {
795 // Draw a nine patch image with colored corners and verify that the corner
796 // color does not leak outside the intended region.
797 auto texture = CreateTextureForFixture("nine_patch_corners.png");
798 flutter::DisplayListBuilder builder;
799 builder.DrawImageNine(DlImageImpeller::Make(texture),
800 DlIRect::MakeXYWH(10, 10, 1, 1),
801 DlRect::MakeXYWH(0, 0, 200, 100),
802 flutter::DlFilterMode::kNearest, nullptr);
803 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
804 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [364/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 212 of file dl_unittests.cc.

212 {
213 auto callback = [&]() {
214 flutter::DisplayListBuilder builder;
215 flutter::DlPaint paint;
216
217 paint.setColor(flutter::DlColor::kRed());
218 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
219
220 static float stroke_width = 10.0f;
221 static int selected_stroke_type = 0;
222 static int selected_join_type = 0;
223 const char* stroke_types[] = {"Butte", "Round", "Square"};
224 const char* join_type[] = {"kMiter", "Round", "kBevel"};
225
226 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
227 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
228 sizeof(stroke_types) / sizeof(char*));
229 ImGui::Combo("Join", &selected_join_type, join_type,
230 sizeof(join_type) / sizeof(char*));
231 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
232 ImGui::End();
233
234 flutter::DlStrokeCap cap;
235 flutter::DlStrokeJoin join;
236 switch (selected_stroke_type) {
237 case 0:
238 cap = flutter::DlStrokeCap::kButt;
239 break;
240 case 1:
241 cap = flutter::DlStrokeCap::kRound;
242 break;
243 case 2:
244 cap = flutter::DlStrokeCap::kSquare;
245 break;
246 default:
247 cap = flutter::DlStrokeCap::kButt;
248 break;
249 }
250 switch (selected_join_type) {
251 case 0:
252 join = flutter::DlStrokeJoin::kMiter;
253 break;
254 case 1:
255 join = flutter::DlStrokeJoin::kRound;
256 break;
257 case 2:
258 join = flutter::DlStrokeJoin::kBevel;
259 break;
260 default:
261 join = flutter::DlStrokeJoin::kMiter;
262 break;
263 }
264 paint.setStrokeCap(cap);
265 paint.setStrokeJoin(join);
266 paint.setStrokeWidth(stroke_width);
267
268 // Make rendering better to watch.
269 builder.Scale(1.5f, 1.5f);
270
271 // Rectangle
272 builder.Translate(100, 100);
273 builder.DrawRect(DlRect::MakeWH(100, 100), paint);
274
275 // Rounded rectangle
276 builder.Translate(150, 0);
277 builder.DrawRoundRect(
278 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10), paint);
279
280 // Double rounded rectangle
281 builder.Translate(150, 0);
282 builder.DrawDiffRoundRect(
283 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10),
284 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 10, 80, 30), 10, 10),
285 paint);
286
287 // Contour with duplicate join points
288 {
289 builder.Translate(150, 0);
290 flutter::DlPathBuilder path_builder;
291 path_builder.MoveTo(DlPoint(0, 0));
292 path_builder.LineTo(DlPoint(0, 0));
293 path_builder.LineTo(DlPoint(100, 0));
294 path_builder.LineTo(DlPoint(100, 0));
295 path_builder.LineTo(DlPoint(100, 100));
296 builder.DrawPath(DlPath(path_builder), paint);
297 }
298
299 // Contour with duplicate start and end points
300
301 // Line.
302 builder.Translate(200, 0);
303 {
304 builder.Save();
305
306 flutter::DlPathBuilder line_path_builder;
307 line_path_builder.MoveTo(DlPoint(0, 0));
308 line_path_builder.MoveTo(DlPoint(0, 0));
309 line_path_builder.LineTo(DlPoint(0, 0));
310 line_path_builder.LineTo(DlPoint(0, 0));
311 line_path_builder.LineTo(DlPoint(50, 50));
312 line_path_builder.LineTo(DlPoint(50, 50));
313 line_path_builder.LineTo(DlPoint(100, 0));
314 line_path_builder.LineTo(DlPoint(100, 0));
315 DlPath line_path(line_path_builder);
316 builder.DrawPath(line_path, paint);
317
318 builder.Translate(0, 100);
319 builder.DrawPath(line_path, paint);
320
321 builder.Translate(0, 100);
322 flutter::DlPathBuilder line_path_builder2;
323 line_path_builder2.MoveTo(DlPoint(0, 0));
324 line_path_builder2.LineTo(DlPoint(0, 0));
325 line_path_builder2.LineTo(DlPoint(0, 0));
326 builder.DrawPath(DlPath(line_path_builder2), paint);
327
328 builder.Restore();
329 }
330
331 // Cubic.
332 builder.Translate(150, 0);
333 {
334 builder.Save();
335
336 flutter::DlPathBuilder cubic_path;
337 cubic_path.MoveTo(DlPoint(0, 0));
338 cubic_path.CubicCurveTo(DlPoint(0, 0), //
339 DlPoint(140.0, 100.0), //
340 DlPoint(140, 20));
341 builder.DrawPath(DlPath(cubic_path), paint);
342
343 builder.Translate(0, 100);
344 flutter::DlPathBuilder cubic_path2;
345 cubic_path2.MoveTo(DlPoint(0, 0));
346 cubic_path2.CubicCurveTo(DlPoint(0, 0), //
347 DlPoint(0, 0), //
348 DlPoint(150, 150));
349 builder.DrawPath(DlPath(cubic_path2), paint);
350
351 builder.Translate(0, 100);
352 flutter::DlPathBuilder cubic_path3;
353 cubic_path3.MoveTo(DlPoint(0, 0));
354 cubic_path3.CubicCurveTo(DlPoint(0, 0), //
355 DlPoint(0, 0), //
356 DlPoint(0, 0));
357 builder.DrawPath(DlPath(cubic_path3), paint);
358
359 builder.Restore();
360 }
361
362 // Quad.
363 builder.Translate(200, 0);
364 {
365 builder.Save();
366
367 flutter::DlPathBuilder quad_path;
368 quad_path.MoveTo(DlPoint(0, 0));
369 quad_path.MoveTo(DlPoint(0, 0));
370 quad_path.QuadraticCurveTo(DlPoint(100, 40), DlPoint(50, 80));
371 builder.DrawPath(DlPath(quad_path), paint);
372
373 builder.Translate(0, 150);
374 flutter::DlPathBuilder quad_path2;
375 quad_path2.MoveTo(DlPoint(0, 0));
376 quad_path2.MoveTo(DlPoint(0, 0));
377 quad_path2.QuadraticCurveTo(DlPoint(0, 0), DlPoint(100, 100));
378 builder.DrawPath(DlPath(quad_path2), paint);
379
380 builder.Translate(0, 100);
381 flutter::DlPathBuilder quad_path3;
382 quad_path3.MoveTo(DlPoint(0, 0));
383 quad_path3.QuadraticCurveTo(DlPoint(0, 0), DlPoint(0, 0));
384 builder.DrawPath(DlPath(quad_path3), paint);
385
386 builder.Restore();
387 }
388 return builder.Build();
389 };
390 ASSERT_TRUE(OpenPlaygroundHere(callback));
391 }

References stroke_width.

## ◆ TEST_P() [365/525]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 486 of file dl_unittests.cc.

486 {
487 flutter::DisplayListBuilder builder;
488 flutter::DlPaint paint;
489 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
490
491 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
492 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
493
494 // Draw a blue filled rectangle so the text is easier to see.
495 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
496 paint.setColor(mat_blue);
497 builder.DrawRect(DlRect::MakeXYWH(0, 0, 500, 500), paint);
498
499 // Draw stacked text, with stroked text on top.
500 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
501 paint.setColor(flutter::DlColor::kWhite());
502 builder.DrawTextBlob(text_blob, 250, 250, paint);
503
504 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
505 paint.setColor(flutter::DlColor::kBlack());
506 builder.DrawTextBlob(text_blob, 250, 250, paint);
507
508 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
509 }

## ◆ TEST_P() [366/525]

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() [367/525]

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() [368/525]

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() [369/525]

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() [370/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 829 of file entity_unittests.cc.

829 {
830 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
831 static float scale = 20;
832
833 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
834 ImGui::SliderFloat("Scale", &scale, 1, 100);
835 ImGui::End();
836
837 Entity entity;
838 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
839 auto path = PathBuilder{}
840 .MoveTo({97.325, 34.818})
841 .CubicCurveTo({98.50862885295136, 34.81812293973836},
842 {99.46822048142015, 33.85863261475589},
843 {99.46822048142015, 32.67499810206613})
844 .CubicCurveTo({99.46822048142015, 31.491363589376355},
845 {98.50862885295136, 30.53187326439389},
846 {97.32499434685802, 30.531998226542708})
847 .CubicCurveTo({96.14153655073771, 30.532123170035373},
848 {95.18222070648729, 31.491540299350355},
849 {95.18222070648729, 32.67499810206613})
850 .CubicCurveTo({95.18222070648729, 33.85845590478189},
851 {96.14153655073771, 34.81787303409686},
852 {97.32499434685802, 34.81799797758954})
853 .Close()
854 .TakePath();
855 entity.SetTransform(
856 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
857
858 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
859
860 auto contents = std::make_shared<SolidColorContents>();
861 contents->SetColor(Color::Red());
862 contents->SetGeometry(geom.get());
863
864 entity.SetContents(contents);
865 return entity.Render(context, pass);
866 };
867 ASSERT_TRUE(OpenPlaygroundHere(callback));
868 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [371/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 698 of file entity_unittests.cc.

698 {
699 std::vector<const char*> blend_mode_names;
700 std::vector<BlendMode> blend_mode_values;
701 {
702 // Force an exhausiveness check with a switch. When adding blend modes,
703 // update this switch with a new name/value to make it selectable in the
704 // test GUI.
705
706 const BlendMode b{};
707 static_assert(b == BlendMode::kClear); // Ensure the first item in
708 // the switch is the first
709 // item in the enum.
710 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
711 switch (b) {
712 case BlendMode::kClear:
713 blend_mode_names.push_back("Clear");
714 blend_mode_values.push_back(BlendMode::kClear);
715 case BlendMode::kSrc:
716 blend_mode_names.push_back("Source");
717 blend_mode_values.push_back(BlendMode::kSrc);
718 case BlendMode::kDst:
719 blend_mode_names.push_back("Destination");
720 blend_mode_values.push_back(BlendMode::kDst);
721 case BlendMode::kSrcOver:
722 blend_mode_names.push_back("SourceOver");
723 blend_mode_values.push_back(BlendMode::kSrcOver);
724 case BlendMode::kDstOver:
725 blend_mode_names.push_back("DestinationOver");
726 blend_mode_values.push_back(BlendMode::kDstOver);
727 case BlendMode::kSrcIn:
728 blend_mode_names.push_back("SourceIn");
729 blend_mode_values.push_back(BlendMode::kSrcIn);
730 case BlendMode::kDstIn:
731 blend_mode_names.push_back("DestinationIn");
732 blend_mode_values.push_back(BlendMode::kDstIn);
733 case BlendMode::kSrcOut:
734 blend_mode_names.push_back("SourceOut");
735 blend_mode_values.push_back(BlendMode::kSrcOut);
736 case BlendMode::kDstOut:
737 blend_mode_names.push_back("DestinationOut");
738 blend_mode_values.push_back(BlendMode::kDstOut);
739 case BlendMode::kSrcATop:
740 blend_mode_names.push_back("SourceATop");
741 blend_mode_values.push_back(BlendMode::kSrcATop);
742 case BlendMode::kDstATop:
743 blend_mode_names.push_back("DestinationATop");
744 blend_mode_values.push_back(BlendMode::kDstATop);
745 case BlendMode::kXor:
746 blend_mode_names.push_back("Xor");
747 blend_mode_values.push_back(BlendMode::kXor);
748 case BlendMode::kPlus:
749 blend_mode_names.push_back("Plus");
750 blend_mode_values.push_back(BlendMode::kPlus);
751 case BlendMode::kModulate:
752 blend_mode_names.push_back("Modulate");
753 blend_mode_values.push_back(BlendMode::kModulate);
754 };
755 }
756
757 auto callback = [&](ContentContext& context, RenderPass& pass) {
758 auto world_matrix = Matrix::MakeScale(GetContentScale());
759 auto draw_rect = [&context, &pass, &world_matrix](
760 Rect rect, Color color, BlendMode blend_mode) -> bool {
761 using VS = SolidFillPipeline::VertexShader;
762 using FS = SolidFillPipeline::FragmentShader;
763
764 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
765 {
766 auto r = rect.GetLTRB();
767 vtx_builder.AddVertices({
768 {Point(r[0], r[1])},
769 {Point(r[2], r[1])},
770 {Point(r[2], r[3])},
771 {Point(r[0], r[1])},
772 {Point(r[2], r[3])},
773 {Point(r[0], r[3])},
774 });
775 }
776
777 pass.SetCommandLabel("Blended Rectangle");
778 auto options = OptionsFromPass(pass);
779 options.blend_mode = blend_mode;
780 options.primitive_type = PrimitiveType::kTriangle;
781 pass.SetPipeline(context.GetSolidFillPipeline(options));
782 pass.SetVertexBuffer(
783 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
784
785 VS::FrameInfo frame_info;
786 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
787 VS::BindFrameInfo(
788 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
789 FS::FragInfo frag_info;
790 frag_info.color = color.Premultiply();
791 FS::BindFragInfo(
792 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
793 return pass.Draw().ok();
794 };
795
796 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
797 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
798 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
799 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
800 static int current_blend_index = 3;
801 ImGui::ListBox("Blending mode", &current_blend_index,
802 blend_mode_names.data(), blend_mode_names.size());
803 ImGui::End();
804
805 BlendMode selected_mode = blend_mode_values[current_blend_index];
806
807 Point a, b, c, d;
808 PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
809 PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
810 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
811 PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
812 PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
813 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
814
815 bool result = true;
816 result = result &&
817 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
818 pass.GetRenderTargetSize().height),
819 Color(), BlendMode::kClear);
820 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
821 BlendMode::kSrcOver);
822 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
823 selected_mode);
824 return result;
825 };
826 ASSERT_TRUE(OpenPlaygroundHere(callback));
827 }
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() [372/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1258 of file entity_unittests.cc.

1258 {
1259 auto fill = std::make_shared<SolidColorContents>();
1260 auto geom = Geometry::MakeFillPath(
1261 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1262 fill->SetGeometry(geom.get());
1263 fill->SetColor(Color::CornflowerBlue());
1264 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1265 FilterInput::Make(fill), Radius{3}, Radius{4});
1266
1267 {
1268 Entity e;
1269 e.SetTransform(Matrix());
1270 auto actual = border_mask_blur->GetCoverage(e);
1271 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1272 ASSERT_TRUE(actual.has_value());
1273 ASSERT_RECT_NEAR(actual.value(), expected);
1274 }
1275
1276 {
1277 Entity e;
1278 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1279 auto actual = border_mask_blur->GetCoverage(e);
1280 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1281 ASSERT_TRUE(actual.has_value());
1282 ASSERT_RECT_NEAR(actual.value(), expected);
1283 }
1284 }

References impeller::PathBuilder::AddRect(), 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() [373/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2251 of file entity_unittests.cc.

2251 {
2252 PathBuilder builder = {};
2253 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2254 Path path = builder.TakePath();
2255
2256 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2257
2258 auto geom = Geometry::MakeFillPath(path);
2259
2260 Entity entity;
2261 RenderTarget target =
2262 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2263 *GetContext(), {1, 1}, 1u);
2264 testing::MockRenderPass render_pass(GetContext(), target);
2265 auto position_result =
2266 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2267
2268 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2269
2270 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2271 }

References impeller::PathBuilder::AddRect(), impeller::Path::GetBoundingBox(), impeller::GeometryResult::kNormal, impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [374/525]

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() [375/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 366 of file entity_unittests.cc.

366 {
367 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
368 const char* input_axis[] = {"X", "Y", "Z"};
369 static int rotation_axis_index = 0;
370 static float rotation = 0;
371 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
372 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
373 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
374 sizeof(input_axis) / sizeof(char*));
375 Matrix rotation_matrix;
376 switch (rotation_axis_index) {
377 case 0:
378 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
379 break;
380 case 1:
381 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
382 break;
383 case 2:
384 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
385 break;
386 default:
387 rotation_matrix = Matrix{};
388 break;
389 }
390
391 if (ImGui::Button("Reset")) {
392 rotation = 0;
393 }
394 ImGui::End();
395 Matrix current_transform =
396 Matrix::MakeScale(GetContentScale())
397 .MakeTranslation(
398 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
399 pass.GetRenderTargetSize().height / 2.0)));
400 Matrix result_transform = current_transform * rotation_matrix;
401 Path path =
402 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
403
404 Entity entity;
405 entity.SetTransform(result_transform);
406
407 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
408
409 auto contents = std::make_shared<SolidColorContents>();
410 contents->SetColor(Color::Red());
411 contents->SetGeometry(geom.get());
412
413 entity.SetContents(contents);
414 return entity.Render(context, pass);
415 };
416 ASSERT_TRUE(OpenPlaygroundHere(callback));
417 }

References impeller::PathBuilder::AddRect(), 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(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [376/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2273 of file entity_unittests.cc.

2273 {
2274 PathBuilder builder = {};
2275 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2276 Path path = builder.TakePath();
2277
2278 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2279
2280 auto contents = std::make_shared<SolidColorContents>();
2281 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
2282 contents->SetGeometry(geom.get());
2283 contents->SetColor(Color::Red());
2284
2285 Entity entity;
2286 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2287 entity.SetContents(contents);
2288
2289 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2290 }

References impeller::PathBuilder::AddRect(), impeller::Path::GetBoundingBox(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [377/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2092 of file entity_unittests.cc.

2092 {
2093 Entity entity;
2094 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2095 auto src_contents = std::make_shared<SolidColorContents>();
2096 auto src_geom = Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000));
2097 src_contents->SetGeometry(src_geom.get());
2098 src_contents->SetColor(Color::Red());
2099
2100 auto dst_contents = std::make_shared<SolidColorContents>();
2101 auto dst_geom = Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000));
2102 dst_contents->SetGeometry(dst_geom.get());
2103 dst_contents->SetColor(Color::Blue());
2104
2105 auto contents = ColorFilterContents::MakeBlend(
2106 BlendMode::kSrcOver, {FilterInput::Make(dst_contents, false),
2107 FilterInput::Make(src_contents, false)});
2108 entity.SetContents(std::move(contents));
2109 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2110 }

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() [378/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 1859 of file entity_unittests.cc.

1859 {
1860 auto image = CreateTextureForFixture("boston.jpg");
1861 auto filter = ColorFilterContents::MakeBlend(
1862 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
1863
1864 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1865 Entity entity;
1866 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1867 Matrix::MakeTranslation({500, 300}) *
1868 Matrix::MakeScale(Vector2{0.5, 0.5}));
1869 entity.SetContents(filter);
1870 return entity.Render(context, pass);
1871 };
1872 ASSERT_TRUE(OpenPlaygroundHere(callback));
1873 }

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() [379/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 1875 of file entity_unittests.cc.

1875 {
1876 auto image = CreateTextureForFixture("boston.jpg");
1877 auto filter = ColorFilterContents::MakeBlend(
1878 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
1879
1880 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1881 Entity entity;
1882 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1883 Matrix::MakeTranslation({500, 300}) *
1884 Matrix::MakeScale(Vector2{0.5, 0.5}));
1885 entity.SetContents(filter);
1886 return entity.Render(context, pass);
1887 };
1888 ASSERT_TRUE(OpenPlaygroundHere(callback));
1889 }

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() [380/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 1907 of file entity_unittests.cc.

1907 {
1908 auto image = CreateTextureForFixture("boston.jpg");
1909 auto filter = ColorFilterContents::MakeBlend(
1910 BlendMode::kDst, FilterInput::Make({image}), Color::Red());
1911
1912 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1913 Entity entity;
1914 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1915 Matrix::MakeTranslation({500, 300}) *
1916 Matrix::MakeScale(Vector2{0.5, 0.5}));
1917 entity.SetContents(filter);
1918 return entity.Render(context, pass);
1919 };
1920 ASSERT_TRUE(OpenPlaygroundHere(callback));
1921 }

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() [381/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 1891 of file entity_unittests.cc.

1891 {
1892 auto image = CreateTextureForFixture("boston.jpg");
1893 auto filter = ColorFilterContents::MakeBlend(
1894 BlendMode::kSrc, FilterInput::Make({image}), Color::Red());
1895
1896 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1897 Entity entity;
1898 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1899 Matrix::MakeTranslation({500, 300}) *
1900 Matrix::MakeScale(Vector2{0.5, 0.5}));
1901 entity.SetContents(filter);
1902 return entity.Render(context, pass);
1903 };
1904 ASSERT_TRUE(OpenPlaygroundHere(callback));
1905 }

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() [382/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 1923 of file entity_unittests.cc.

1923 {
1924 auto image = CreateTextureForFixture("boston.jpg");
1925 auto filter = ColorFilterContents::MakeBlend(
1926 BlendMode::kSrcIn, FilterInput::Make({image}), Color::Red());
1927
1928 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1929 Entity entity;
1930 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1931 Matrix::MakeTranslation({500, 300}) *
1932 Matrix::MakeScale(Vector2{0.5, 0.5}));
1933 entity.SetContents(filter);
1934 return entity.Render(context, pass);
1935 };
1936 ASSERT_TRUE(OpenPlaygroundHere(callback));
1937 }

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() [383/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1385 of file entity_unittests.cc.

1385 {
1386 // Set up a simple color background.
1387 auto fill = std::make_shared<SolidColorContents>();
1388 auto geom = Geometry::MakeFillPath(
1389 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1390 fill->SetGeometry(geom.get());
1391 fill->SetColor(Color::Coral());
1392
1393 // Set the color matrix filter.
1394 ColorMatrix matrix = {
1395 1, 1, 1, 1, 1, //
1396 1, 1, 1, 1, 1, //
1397 1, 1, 1, 1, 1, //
1398 1, 1, 1, 1, 1, //
1399 };
1400
1401 auto filter =
1402 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1403
1404 Entity e;
1405 e.SetTransform(Matrix());
1406
1407 // Confirm that the actual filter coverage matches the expected coverage.
1408 auto actual = filter->GetCoverage(e);
1409 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1410
1411 ASSERT_TRUE(actual.has_value());
1412 ASSERT_RECT_NEAR(actual.value(), expected);
1413 }

References impeller::PathBuilder::AddRect(), 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() [384/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1415 of file entity_unittests.cc.

1415 {
1416 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1417 ASSERT_TRUE(bay_bridge);
1418
1419 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1420 // UI state.
1421 static ColorMatrix color_matrix = {
1422 1, 0, 0, 0, 0, //
1423 0, 3, 0, 0, 0, //
1424 0, 0, 1, 0, 0, //
1425 0, 0, 0, 1, 0, //
1426 };
1427 static float offset[2] = {500, 400};
1428 static float rotation = 0;
1429 static float scale[2] = {0.65, 0.65};
1430 static float skew[2] = {0, 0};
1431
1432 // Define the ImGui
1433 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1434 {
1435 std::string label = "##1";
1436 for (int i = 0; i < 20; i += 5) {
1437 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1438 &(color_matrix.array[i]), 5, nullptr, nullptr,
1439 "%.2f", 0);
1440 label[2]++;
1441 }
1442
1443 ImGui::SliderFloat2("Translation", &offset[0], 0,
1444 pass.GetRenderTargetSize().width);
1445 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1446 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1447 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1448 }
1449 ImGui::End();
1450
1451 // Set the color matrix filter.
1452 auto filter = ColorFilterContents::MakeColorMatrix(
1453 FilterInput::Make(bay_bridge), color_matrix);
1454
1455 // Define the entity with the color matrix filter.
1456 Entity entity;
1457 entity.SetTransform(
1458 Matrix::MakeScale(GetContentScale()) *
1459 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1460 Matrix::MakeRotationZ(Radians(rotation)) *
1461 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1462 Matrix::MakeSkew(skew[0], skew[1]) *
1463 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1464 entity.SetContents(filter);
1465 entity.Render(context, pass);
1466
1467 return true;
1468 };
1469
1470 ASSERT_TRUE(OpenPlaygroundHere(callback));
1471 }

References impeller::ColorMatrix::array, impeller::kPi, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [385/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 1980 of file entity_unittests.cc.

1980 {
1981 Matrix matrix;
1982 ConicalGradientContents contents;
1983 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
1984 contents.SetGeometry(geom.get());
1985
1986 contents.SetColors({Color::CornflowerBlue()});
1987 EXPECT_FALSE(contents.IsOpaque(matrix));
1988 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
1989 EXPECT_FALSE(contents.IsOpaque(matrix));
1990
1991 // Create stroked path that required alpha coverage.
1992 geom = Geometry::MakeStrokePath(
1993 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
1994 /*stroke_width=*/0.05);
1995 contents.SetGeometry(geom.get());
1996 contents.SetColors({Color::CornflowerBlue()});
1997
1998 EXPECT_FALSE(contents.IsOpaque(matrix));
1999 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Geometry::MakeStrokePath(), impeller::ConicalGradientContents::SetColors(), impeller::ColorSourceContents::SetGeometry(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [386/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2159 of file entity_unittests.cc.

2159 {
2160 ContentContextOptions opts;
2161 auto hash_a = opts.ToKey();
2162
2163 opts.blend_mode = BlendMode::kColorBurn;
2164 auto hash_b = opts.ToKey();
2165
2166 opts.has_depth_stencil_attachments = false;
2167 auto hash_c = opts.ToKey();
2168
2169 opts.primitive_type = PrimitiveType::kPoint;
2170 auto hash_d = opts.ToKey();
2171
2172 EXPECT_NE(hash_a, hash_b);
2173 EXPECT_NE(hash_b, hash_c);
2174 EXPECT_NE(hash_c, hash_d);
2175 }

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() [387/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1196 of file entity_unittests.cc.

1196 {
1197 Entity entity;
1198 entity.SetContents(std::make_shared<SolidColorContents>());
1199 ASSERT_FALSE(entity.GetCoverage().has_value());
1200 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [388/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 1939 of file entity_unittests.cc.

1939 {
1940 auto arrow_head = PathBuilder{}
1941 .MoveTo({50, 120})
1942 .LineTo({120, 190})
1943 .LineTo({190, 120})
1944 .TakePath();
1945 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
1946 Join::kRound);
1947
1948 auto transform = Matrix::MakeTranslation({300, 300}) *
1949 Matrix::MakeRotationZ(Radians(kPiOver2));
1950 // Note that e[0][0] used to be tested here, but it was -epsilon solely
1951 // due to floating point inaccuracy in the transcendental trig functions.
1952 // e[1][0] is the intended negative value that we care about (-1.0) as it
1953 // comes from the rotation of pi/2.
1954 EXPECT_LT(transform.e[1][0], 0.0f);
1955 auto coverage = geometry->GetCoverage(transform);
1956 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
1957 }

References ASSERT_RECT_NEAR, impeller::kPiOver2, impeller::kRound, impeller::LineTo(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PathBuilder::MoveTo(), and transform.

## ◆ TEST_P() [389/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 419 of file entity_unittests.cc.

419 {
420 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
421 Path path =
422 PathBuilder{}
423 .MoveTo({359.934, 96.6335})
424 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
425 {354.673, 96.8895})
426 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
427 {354.367, 96.9075})
428 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
429 {349.259, 97.2355})
430 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
431 {348.625, 97.2834})
432 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
433 {343.789, 97.6722})
434 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
435 {342.703, 97.7734})
436 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
437 {338.246, 98.207})
438 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
439 {336.612, 98.3894})
440 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
441 {332.623, 98.8476})
442 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
443 {332.237, 98.8982})
444 .LineTo({332.237, 102.601})
445 .LineTo({321.778, 102.601})
446 .LineTo({321.778, 100.382})
447 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
448 {321.161, 100.476})
449 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
450 {315.332, 101.479})
451 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
452 {315.301, 101.484})
453 .LineTo({310.017, 105.94})
454 .LineTo({309.779, 105.427})
455 .LineTo({314.403, 101.651})
456 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
457 {314.368, 101.658})
458 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
459 {308.846, 102.748})
460 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
461 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
462 {303.425, 103.936})
463 .LineTo({299.105, 107.578})
464 .LineTo({298.867, 107.065})
465 .LineTo({302.394, 104.185})
466 .LineTo({302.412, 104.171})
467 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
468 {299.344, 104.921})
469 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
470 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
471 {291.462, 106.979})
472 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
473 {290.471, 107.257})
474 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
475 {287.449, 108.139})
476 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
477 {284.536, 109.035})
478 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
479 {281.952, 109.859})
480 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
481 {279.633, 110.638})
482 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
483 {276.803, 111.607})
484 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
485 {276.672, 111.653})
486 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
487 {271.721, 113.463})
488 .LineTo({271.717, 113.449})
489 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
490 {270.963, 113.628})
491 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
492 {270.748, 113.682})
493 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
494 {269.839, 113.926})
495 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
496 {269.681, 113.972})
497 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
498 {268.756, 114.239})
499 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
500 {268.367, 114.354})
501 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
502 {267.752, 114.54})
503 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
504 {253.564, 119.252})
505 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
506 {253.538, 119.261})
507 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
508 {248.189, 121.131})
509 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
510 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
511 {245.975, 121.912})
512 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
513 {244.698, 122.364})
514 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
515 {242.794, 123.04})
516 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
517 {240.961, 123.693})
518 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
519 {240.052, 124.018})
520 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
521 .LineTo({237.164, 125.003})
522 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
523 {235.81, 125.538})
524 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
525 {234.592, 125.977})
526 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
527 {234.59, 125.977})
528 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
529 {192.381, 141.429})
530 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
531 .LineTo({360, 160})
532 .LineTo({360, 119.256})
533 .LineTo({360, 106.332})
534 .LineTo({360, 96.6307})
535 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
536 {359.934, 96.6335})
537 .Close()
538 .MoveTo({337.336, 124.143})
539 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
540 {338.903, 121.511})
541 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
542 {337.336, 124.143})
543 .Close()
544 .MoveTo({340.082, 121.849})
545 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
546 {340.046, 122.075})
547 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
548 {340.023, 122.177})
549 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
550 {339.952, 122.437})
551 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
552 {339.918, 122.544})
553 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
554 {339.75, 122.938})
555 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
556 {339.74, 122.955})
557 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
558 {339.501, 123.328})
559 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
560 {339.41, 123.438})
561 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
562 {339.145, 123.714})
563 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
564 {339.025, 123.821})
565 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
566 {338.539, 124.143})
567 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
568 {338.58, 123.626})
569 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
570 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
571 {338.704, 123.151})
572 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
573 {338.714, 123.117})
574 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
575 {338.905, 122.712})
576 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
577 {338.922, 122.682})
578 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
579 {339.155, 122.34})
580 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
581 {339.172, 122.319})
582 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
583 {339.425, 122.037})
584 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
585 {339.435, 122.027})
586 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
587 {340.106, 121.511})
588 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
589 {340.082, 121.849})
590 .Close()
591 .MoveTo({340.678, 113.245})
592 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
593 {340.135, 113.775})
594 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
595 {339.115, 114.151})
596 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
597 {336.448, 114.516})
598 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
599 {334.384, 114.513})
600 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
601 {333.605, 114.424})
602 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
603 {331.41, 113.883})
604 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
605 {330.672, 112.813})
606 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
607 {334.526, 113.833})
608 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
609 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
610 {332.76, 110.402})
611 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
612 {335.228, 113.395})
613 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
614 {335.661, 109.592})
615 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
616 {336.07, 113.389})
617 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
618 {338.563, 110.402})
619 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
620 {336.753, 113.784})
621 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
622 {336.796, 113.833})
623 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
624 {340.65, 112.813})
625 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
626 {340.678, 113.245})
627 .Close()
628 .MoveTo({346.357, 106.771})
629 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
630 {347.924, 104.139})
631 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
632 {346.357, 106.771})
633 .Close()
634 .MoveTo({347.56, 106.771})
635 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
636 {349.127, 104.139})
637 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
638 {347.56, 106.771})
639 .Close()
640 .TakePath();
641 Entity entity;
642 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
643
644 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
645
646 auto contents = std::make_shared<SolidColorContents>();
647 contents->SetColor(Color::Red());
648 contents->SetGeometry(geom.get());
649
650 entity.SetContents(contents);
651 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
652 }

References impeller::Close(), impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [390/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 337 of file entity_unittests.cc.

337 {
338 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
339 Path path =
340 PathBuilder{}
341 .MoveTo({237.164, 125.003})
342 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
343 {235.81, 125.538})
344 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
345 {234.592, 125.977})
346 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
347 {234.59, 125.977})
348 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
349 {192.381, 141.429})
350 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
351 .Close()
352 .TakePath();
353 Entity entity;
354 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
355
356 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(path);
357
358 auto contents = std::make_shared<SolidColorContents>();
359 contents->SetColor(Color::Red());
360 contents->SetGeometry(geom.get());
361
362 entity.SetContents(contents);
363 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
364 }

References impeller::Close(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [391/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2143 of file entity_unittests.cc.

2143 {
2144 auto content_context = GetContentContext();
2145 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2146 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2147 });
2148
2149 auto decal_supported = static_cast<Scalar>(
2150 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2151 std::vector<Scalar> expected_constants = {decal_supported};
2152 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2153 expected_constants);
2154 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [392/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawRoundSuperEllipse |
| ) |  |

Definition at line 2325 of file entity_unittests.cc.

2325 {
2326 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2327 // UI state.
2328 static int style_index = 0;
2329 static float center[2] = {830, 830};
2330 static float size[2] = {600, 600};
2331 static bool horizontal_symmetry = true;
2332 static bool vertical_symmetry = true;
2333 static bool corner_symmetry = true;
2334
2335 const char* style_options[] = {"Fill", "Stroke"};
2336
2337 // Initially radius_tl[0] will be mirrored to all 8 values since all 3
2338 // symmetries are enabled.
2339 static std::array<float, 2> radius_tl = {200};
2340 static std::array<float, 2> radius_tr;
2341 static std::array<float, 2> radius_bl;
2342 static std::array<float, 2> radius_br;
2343
2344 auto AddRadiusControl = [](std::array<float, 2>& radii, const char* tb_name,
2345 const char* lr_name) {
2346 std::string name = "Radius";
2347 if (!horizontal_symmetry || !vertical_symmetry) {
2348 name += ":";
2349 }
2350 if (!vertical_symmetry) {
2351 name = name + " " + tb_name;
2352 }
2353 if (!horizontal_symmetry) {
2354 name = name + " " + lr_name;
2355 }
2356 if (corner_symmetry) {
2357 ImGui::SliderFloat(name.c_str(), radii.data(), 0, 1000);
2358 } else {
2359 ImGui::SliderFloat2(name.c_str(), radii.data(), 0, 1000);
2360 }
2361 };
2362
2363 if (corner_symmetry) {
2364 radius_tl[1] = radius_tl[0];
2365 radius_tr[1] = radius_tr[0];
2366 radius_bl[1] = radius_bl[0];
2367 radius_br[1] = radius_br[0];
2368 }
2369
2370 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2371 {
2372 ImGui::Combo("Style", &style_index, style_options,
2373 sizeof(style_options) / sizeof(char*));
2374 ImGui::SliderFloat2("Center", center, 0, 1000);
2375 ImGui::SliderFloat2("Size", size, 0, 1000);
2376 ImGui::Checkbox("Symmetry: Horizontal", &horizontal_symmetry);
2377 ImGui::Checkbox("Symmetry: Vertical", &vertical_symmetry);
2378 ImGui::Checkbox("Symmetry: Corners", &corner_symmetry);
2379 AddRadiusControl(radius_tl, "Top", "Left");
2380 if (!horizontal_symmetry) {
2381 AddRadiusControl(radius_tr, "Top", "Right");
2382 } else {
2383 radius_tr = radius_tl;
2384 }
2385 if (!vertical_symmetry) {
2386 AddRadiusControl(radius_bl, "Bottom", "Left");
2387 } else {
2388 radius_bl = radius_tl;
2389 }
2390 if (!horizontal_symmetry && !vertical_symmetry) {
2391 AddRadiusControl(radius_br, "Bottom", "Right");
2392 } else {
2393 if (horizontal_symmetry) {
2394 radius_br = radius_bl;
2395 } else {
2396 radius_br = radius_tr;
2397 }
2398 }
2399 }
2400
2401 ImGui::End();
2402
2403 RoundingRadii radii{
2404 .top_left = {radius_tl[0], radius_tl[1]},
2405 .top_right = {radius_tr[0], radius_tr[1]},
2406 .bottom_left = {radius_bl[0], radius_bl[1]},
2407 .bottom_right = {radius_br[0], radius_br[1]},
2408 };
2409
2410 auto rse = RoundSuperellipse::MakeRectRadii(
2411 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}), radii);
2412
2413 Path path;
2414 std::unique_ptr<Geometry> geom;
2415 if (style_index == 0) {
2416 geom = std::make_unique<RoundSuperellipseGeometry>(
2417 RectMakeCenterSize({center[0], center[1]}, {size[0], size[1]}),
2418 radii);
2419 } else {
2420 path = PathBuilder{}
2421 .SetConvexity(Convexity::kConvex)
2422 .AddRoundSuperellipse(rse)
2423 .SetBounds(rse.GetBounds())
2424 .TakePath();
2425 geom = Geometry::MakeStrokePath(path, /*stroke_width=*/2);
2426 }
2427
2428 auto contents = std::make_shared<SolidColorContents>();
2429 contents->SetColor(Color::Red());
2430 contents->SetGeometry(geom.get());
2431
2432 Entity entity;
2433 entity.SetContents(contents);
2434
2435 return entity.Render(context, pass);
2436 };
2437
2438 ASSERT_TRUE(OpenPlaygroundHere(callback));
2439 }
impeller::testing::RectMakeCenterSize
Rect RectMakeCenterSize(Point center, Size size)
Definition: entity_unittests.cc:68

References impeller::PathBuilder::AddRoundSuperellipse(), impeller::kConvex, impeller::RoundSuperellipse::MakeRectRadii(), impeller::Geometry::MakeStrokePath(), RectMakeCenterSize(), impeller::Color::Red(), impeller::Entity::Render(), impeller::PathBuilder::SetBounds(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::PathBuilder::TakePath(), and impeller::RoundingRadii::top_left.

## ◆ TEST_P() [393/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawSuperEllipse |
| ) |  |

Definition at line 2292 of file entity_unittests.cc.

2292 {
2293 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2294 // UI state.
2295 static float alpha = 10;
2296 static float beta = 10;
2297 static float radius = 40;
2298 static int degree = 4;
2299 static Color color = Color::Red();
2300
2301 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
2302 ImGui::SliderFloat("Alpha", &alpha, 0, 100);
2303 ImGui::SliderFloat("Beta", &beta, 0, 100);
2304 ImGui::SliderInt("Degreee", &degree, 1, 20);
2305 ImGui::SliderFloat("Radius", &radius, 0, 400);
2306 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
2307 ImGui::End();
2308
2309 auto contents = std::make_shared<SolidColorContents>();
2310 std::unique_ptr<SuperellipseGeometry> geom =
2311 std::make_unique<SuperellipseGeometry>(Point{400, 400}, radius, degree,
2312 alpha, beta);
2313 contents->SetColor(color);
2314 contents->SetGeometry(geom.get());
2315
2316 Entity entity;
2317 entity.SetContents(contents);
2318
2319 return entity.Render(context, pass);
2320 };
2321
2322 ASSERT_TRUE(OpenPlaygroundHere(callback));
2323 }

References impeller::Color::Red(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [394/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2237 of file entity_unittests.cc.

2237 {
2238 if (GetParam() != PlaygroundBackend::kVulkan) {
2239 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2240 }
2241 EXPECT_DEATH(
2242 // The easiest way to trigger a validation error is to try to compile
2243 // a shader with an unsupported pixel format.
2244 GetContentContext()->GetBlendColorBurnPipeline({
2245 .color_attachment_pixel_format = PixelFormat::kUnknown,
2246 .has_depth_stencil_attachments = false,
2247 }),
2248 "");
2249 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [395/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2203 of file entity_unittests.cc.

2203 {
2204 RenderTarget target;
2205 testing::MockRenderPass mock_pass(GetContext(), target);
2206
2207 auto get_result = [this, &mock_pass](const Path& path) {
2208 auto geometry = Geometry::MakeFillPath(
2209 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2210 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2211 };
2212
2213 // Convex path
2214 {
2215 GeometryResult result =
2216 get_result(PathBuilder{}
2217 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2218 .SetConvexity(Convexity::kConvex)
2219 .TakePath());
2220 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2221 }
2222
2223 // Concave path
2224 {
2225 Path path = PathBuilder{}
2226 .MoveTo({0, 0})
2227 .LineTo({100, 0})
2228 .LineTo({100, 100})
2229 .LineTo({50, 50})
2230 .Close()
2231 .TakePath();
2232 GeometryResult result = get_result(path);
2233 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2234 }
2235 }

References impeller::PathBuilder::AddRect(), impeller::Close(), impeller::kConvex, impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::GeometryResult::mode, and impeller::PathBuilder::MoveTo().

## ◆ TEST_P() [396/525]

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() [397/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 870 of file entity_unittests.cc.

870 {
871 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
872 auto boston = CreateTextureForFixture("boston.jpg");
873 auto kalimba = CreateTextureForFixture("kalimba.jpg");
874 ASSERT_TRUE(bridge && boston && kalimba);
875
876 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
877 auto fi_bridge = FilterInput::Make(bridge);
878 auto fi_boston = FilterInput::Make(boston);
879 auto fi_kalimba = FilterInput::Make(kalimba);
880
881 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
882 BlendMode::kModulate, {fi_kalimba, fi_boston});
883
884 auto blend1 = ColorFilterContents::MakeBlend(
885 BlendMode::kScreen,
886 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
887
888 Entity entity;
889 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
890 Matrix::MakeTranslation({500, 300}) *
891 Matrix::MakeScale(Vector2{0.5, 0.5}));
892 entity.SetContents(blend1);
893 return entity.Render(context, pass);
894 };
895 ASSERT_TRUE(OpenPlaygroundHere(callback));
896 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [398/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 898 of file entity_unittests.cc.

898 {
899 auto boston =
900 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
901 ASSERT_TRUE(boston);
902
903 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
904 const char* input_type_names[] = {"Texture", "Solid Color"};
905 const char* blur_type_names[] = {"Image blur", "Mask blur"};
906 const char* pass_variation_names[] = {"New"};
907 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
908 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
909 const FilterContents::BlurStyle blur_styles[] = {
910 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
911 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
912 const Entity::TileMode tile_modes[] = {
913 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
914 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
915
916 // UI state.
917 static int selected_input_type = 0;
918 static Color input_color = Color::Black();
919 static int selected_blur_type = 0;
920 static int selected_pass_variation = 0;
921 static bool combined_sigma = false;
922 static float blur_amount_coarse[2] = {0, 0};
923 static float blur_amount_fine[2] = {10, 10};
924 static int selected_blur_style = 0;
925 static int selected_tile_mode = 3;
926 static Color cover_color(1, 0, 0, 0.2);
927 static Color bounds_color(0, 1, 0, 0.1);
928 static float offset[2] = {500, 400};
929 static float rotation = 0;
930 static float scale[2] = {0.65, 0.65};
931 static float skew[2] = {0, 0};
932 static float path_rect[4] = {0, 0,
933 static_cast<float>(boston->GetSize().width),
934 static_cast<float>(boston->GetSize().height)};
935
936 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
937 {
938 ImGui::Combo("Input type", &selected_input_type, input_type_names,
939 sizeof(input_type_names) / sizeof(char*));
940 if (selected_input_type == 0) {
941 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
942 } else {
943 ImGui::ColorEdit4("Input color",
944 reinterpret_cast<float*>(&input_color));
945 }
946 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
947 sizeof(blur_type_names) / sizeof(char*));
948 if (selected_blur_type == 0) {
949 ImGui::Combo("Pass variation", &selected_pass_variation,
950 pass_variation_names,
951 sizeof(pass_variation_names) / sizeof(char*));
952 }
953 ImGui::Checkbox("Combined sigma", &combined_sigma);
954 if (combined_sigma) {
955 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
956 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
957 blur_amount_coarse[1] = blur_amount_coarse[0];
958 blur_amount_fine[1] = blur_amount_fine[0];
959 } else {
960 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
961 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
962 }
963 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
964 sizeof(blur_style_names) / sizeof(char*));
965 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
966 sizeof(tile_mode_names) / sizeof(char*));
967 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
968 ImGui::ColorEdit4("Bounds color ",
969 reinterpret_cast<float*>(&bounds_color));
970 ImGui::SliderFloat2("Translation", offset, 0,
971 pass.GetRenderTargetSize().width);
972 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
973 ImGui::SliderFloat2("Scale", scale, 0, 3);
974 ImGui::SliderFloat2("Skew", skew, -3, 3);
975 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
976 }
977 ImGui::End();
978
979 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
980 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
981
982 std::shared_ptr<Contents> input;
983 Size input_size;
984
985 auto input_rect =
986 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
987
988 std::unique_ptr<Geometry> solid_color_input;
989 if (selected_input_type == 0) {
990 auto texture = std::make_shared<TextureContents>();
991 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
992 texture->SetDestinationRect(input_rect);
993 texture->SetTexture(boston);
994 texture->SetOpacity(input_color.alpha);
995
996 input = texture;
997 input_size = input_rect.GetSize();
998 } else {
999 auto fill = std::make_shared<SolidColorContents>();
1000 fill->SetColor(input_color);
1001 solid_color_input =
1002 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1003
1004 fill->SetGeometry(solid_color_input.get());
1005
1006 input = fill;
1007 input_size = input_rect.GetSize();
1008 }
1009
1010 std::shared_ptr<FilterContents> blur;
1011 switch (selected_pass_variation) {
1012 case 0:
1013 blur = std::make_shared<GaussianBlurFilterContents>(
1014 blur_sigma_x.sigma, blur_sigma_y.sigma,
1015 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1016 /*geometry=*/nullptr);
1017 blur->SetInputs({FilterInput::Make(input)});
1018 break;
1019 case 1:
1020 blur = FilterContents::MakeGaussianBlur(
1021 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1022 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1023 break;
1024 };
1025 FML_CHECK(blur);
1026
1027 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1028 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1029 blur_styles[selected_blur_style]);
1030
1031 auto ctm = Matrix::MakeScale(GetContentScale()) *
1032 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1033 Matrix::MakeRotationZ(Radians(rotation)) *
1034 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1035 Matrix::MakeSkew(skew[0], skew[1]) *
1036 Matrix::MakeTranslation(-Point(input_size) / 2);
1037
1038 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1039
1040 Entity entity;
1041 entity.SetContents(target_contents);
1042 entity.SetTransform(ctm);
1043
1044 entity.Render(context, pass);
1045
1046 // Renders a red "cover" rectangle that shows the original position of the
1047 // unfiltered input.
1048 Entity cover_entity;
1049 std::unique_ptr<Geometry> geom =
1050 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1051 auto contents = std::make_shared<SolidColorContents>();
1052 contents->SetColor(cover_color);
1053 contents->SetGeometry(geom.get());
1054 cover_entity.SetContents(std::move(contents));
1055 cover_entity.SetTransform(ctm);
1056 cover_entity.Render(context, pass);
1057
1058 // Renders a green bounding rect of the target filter.
1059 Entity bounds_entity;
1060 std::optional<Rect> target_contents_coverage =
1061 target_contents->GetCoverage(entity);
1062 if (target_contents_coverage.has_value()) {
1063 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
1064 PathBuilder{}
1065 .AddRect(target_contents->GetCoverage(entity).value())
1066 .TakePath());
1067 auto contents = std::make_shared<SolidColorContents>();
1068 contents->SetColor(bounds_color);
1069 contents->SetGeometry(geom.get());
1070
1071 bounds_entity.SetContents(contents);
1072 bounds_entity.SetTransform(Matrix());
1073 bounds_entity.Render(context, pass);
1074 }
1075
1076 return true;
1077 };
1078 ASSERT_TRUE(OpenPlaygroundHere(callback));
1079 }

References impeller::PathBuilder::AddRect(), 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(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [399/525]

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() [400/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantLineStripPathAllocation |
| ) |  |

Definition at line 2531 of file entity_unittests.cc.

2531 {
2532 PathBuilder builder{};
2533 for (int i = 0; i < 10000; i++) {
2534 builder.LineTo(Point(i, i));
2535 }
2536 Path path = builder.TakePath();
2537
2538 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2539 Entity entity;
2540
2541 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
2542 GetContext()->GetIdleWaiter());
2543 auto tessellator = Tessellator();
2544
2545 auto vertex_buffer = tessellator.GenerateLineStrip(path, *host_buffer, 1.0);
2546
2547 // Validate the buffer data overflowed the small buffer
2548 EXPECT_GT(vertex_buffer.vertex_count, kPointArenaSize);
2549
2550 // Validate that there are no uninitialized points near the gap.
2551 Point* written_data = reinterpret_cast<Point*>(
2552 (vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2553 vertex_buffer.vertex_buffer.GetRange().offset));
2554
2555 std::vector<Point> expected = {
2556 Point(4093, 4093), //
2557 Point(4094, 4094), //
2558 Point(4095, 4095), //
2559 Point(4096, 4096), //
2560 Point(4097, 4097) //
2561 };
2562
2563 Point point = written_data[kPointArenaSize - 2];
2564 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2565 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2566
2567 point = written_data[kPointArenaSize - 1];
2568 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2569 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2570
2571 point = written_data[kPointArenaSize];
2572 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2573 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2574
2575 point = written_data[kPointArenaSize + 1];
2576 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2577 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2578
2579 point = written_data[kPointArenaSize + 2];
2580 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2581 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2582 }
impeller::kPointArenaSize
static constexpr size_t kPointArenaSize
The size of the point arena buffer stored on the tessellator.
Definition: tessellator.h:22

References impeller::HostBuffer::Create(), impeller::kPointArenaSize, impeller::PathBuilder::LineTo(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [401/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GiantStrokePathAllocation |
| ) |  |

Definition at line 2471 of file entity_unittests.cc.

2471 {
2472 PathBuilder builder{};
2473 for (int i = 0; i < 10000; i++) {
2474 builder.LineTo(Point(i, i));
2475 }
2476 Path path = builder.TakePath();
2477 auto geom = Geometry::MakeStrokePath(path, /*stroke_width=*/10);
2478
2479 ContentContext content_context(GetContext(), /*typographer_context=*/nullptr);
2480 Entity entity;
2481
2482 auto cmd_buffer = content_context.GetContext()->CreateCommandBuffer();
2483
2484 RenderTargetAllocator allocator(
2485 content_context.GetContext()->GetResourceAllocator());
2486
2487 auto render_target = allocator.CreateOffscreen(
2488 *content_context.GetContext(), /*size=*/{10, 10}, /*mip_count=*/1);
2489 auto pass = cmd_buffer->CreateRenderPass(render_target);
2490
2491 GeometryResult result =
2492 geom->GetPositionBuffer(content_context, entity, *pass);
2493
2494 // Validate the buffer data overflowed the small buffer
2495 EXPECT_GT(result.vertex_buffer.vertex_count, kPointArenaSize);
2496
2497 // Validate that there are no uninitialized points near the gap.
2498 Point* written_data = reinterpret_cast<Point*>(
2499 (result.vertex_buffer.vertex_buffer.GetBuffer()->OnGetContents() +
2500 result.vertex_buffer.vertex_buffer.GetRange().offset));
2501
2502 std::vector<Point> expected = {
2503 Point(1019.46, 1026.54), //
2504 Point(1026.54, 1019.46), //
2505 Point(1020.45, 1027.54), //
2506 Point(1027.54, 1020.46), //
2507 Point(1020.46, 1027.53) //
2508 };
2509
2510 Point point = written_data[kPointArenaSize - 2];
2511 EXPECT_NEAR(point.x, expected[0].x, 0.1);
2512 EXPECT_NEAR(point.y, expected[0].y, 0.1);
2513
2514 point = written_data[kPointArenaSize - 1];
2515 EXPECT_NEAR(point.x, expected[1].x, 0.1);
2516 EXPECT_NEAR(point.y, expected[1].y, 0.1);
2517
2518 point = written_data[kPointArenaSize];
2519 EXPECT_NEAR(point.x, expected[2].x, 0.1);
2520 EXPECT_NEAR(point.y, expected[2].y, 0.1);
2521
2522 point = written_data[kPointArenaSize + 1];
2523 EXPECT_NEAR(point.x, expected[3].x, 0.1);
2524 EXPECT_NEAR(point.y, expected[3].y, 0.1);
2525
2526 point = written_data[kPointArenaSize + 2];
2527 EXPECT_NEAR(point.x, expected[4].x, 0.1);
2528 EXPECT_NEAR(point.y, expected[4].y, 0.1);
2529 }

References impeller::RenderTargetAllocator::CreateOffscreen(), impeller::BufferView::GetBuffer(), impeller::ContentContext::GetContext(), impeller::BufferView::GetRange(), impeller::kPointArenaSize, impeller::PathBuilder::LineTo(), 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() [402/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2001 of file entity_unittests.cc.

2001 {
2002 Matrix matrix;
2003 LinearGradientContents contents;
2004 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2005 contents.SetGeometry(geom.get());
2006
2007 contents.SetColors({Color::CornflowerBlue()});
2008 EXPECT_TRUE(contents.IsOpaque(matrix));
2009 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2010 EXPECT_FALSE(contents.IsOpaque(matrix));
2011 contents.SetColors({Color::CornflowerBlue()});
2012 contents.SetTileMode(Entity::TileMode::kDecal);
2013 EXPECT_FALSE(contents.IsOpaque(matrix));
2014
2015 // Create stroked path that required alpha coverage.
2016 geom = Geometry::MakeStrokePath(
2017 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2018 /*stroke_width=*/0.05);
2019 contents.SetGeometry(geom.get());
2020 contents.SetColors({Color::CornflowerBlue()});
2021
2022 EXPECT_FALSE(contents.IsOpaque(matrix));
2023 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, 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() [403/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1495 of file entity_unittests.cc.

1495 {
1496 auto image = CreateTextureForFixture("kalimba.jpg");
1497 ASSERT_TRUE(image);
1498
1499 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1500 auto filtered =
1501 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1502
1503 // Define the entity that will serve as the control image as a Gaussian blur
1504 // filter with no filter at all.
1505 Entity entity_left;
1506 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1507 Matrix::MakeTranslation({100, 300}) *
1508 Matrix::MakeScale(Vector2{0.5, 0.5}));
1509 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1510 Sigma{0}, Sigma{0});
1511 entity_left.SetContents(unfiltered);
1512
1513 // Define the entity that will be filtered from linear to sRGB.
1514 Entity entity_right;
1515 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1516 Matrix::MakeTranslation({500, 300}) *
1517 Matrix::MakeScale(Vector2{0.5, 0.5}));
1518 entity_right.SetContents(filtered);
1519 return entity_left.Render(context, pass) &&
1520 entity_right.Render(context, pass);
1521 };
1522
1523 ASSERT_TRUE(OpenPlaygroundHere(callback));
1524 }

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() [404/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1473 of file entity_unittests.cc.

1473 {
1474 // Set up a simple color background.
1475 auto geom = Geometry::MakeFillPath(
1476 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1477 auto fill = std::make_shared<SolidColorContents>();
1478 fill->SetGeometry(geom.get());
1479 fill->SetColor(Color::MintCream());
1480
1481 auto filter =
1482 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1483
1484 Entity e;
1485 e.SetTransform(Matrix());
1486
1487 // Confirm that the actual filter coverage matches the expected coverage.
1488 auto actual = filter->GetCoverage(e);
1489 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1490
1491 ASSERT_TRUE(actual.has_value());
1492 ASSERT_RECT_NEAR(actual.value(), expected);
1493 }

References impeller::PathBuilder::AddRect(), 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() [405/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1081 of file entity_unittests.cc.

1081 {
1082 auto boston = CreateTextureForFixture("boston.jpg");
1083 ASSERT_TRUE(boston);
1084
1085 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1086 const char* morphology_type_names[] = {"Dilate", "Erode"};
1087 const FilterContents::MorphType morphology_types[] = {
1088 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1089 static Color input_color = Color::Black();
1090 // UI state.
1091 static int selected_morphology_type = 0;
1092 static float radius[2] = {20, 20};
1093 static Color cover_color(1, 0, 0, 0.2);
1094 static Color bounds_color(0, 1, 0, 0.1);
1095 static float offset[2] = {500, 400};
1096 static float rotation = 0;
1097 static float scale[2] = {0.65, 0.65};
1098 static float skew[2] = {0, 0};
1099 static float path_rect[4] = {0, 0,
1100 static_cast<float>(boston->GetSize().width),
1101 static_cast<float>(boston->GetSize().height)};
1102 static float effect_transform_scale = 1;
1103
1104 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1105 {
1106 ImGui::Combo("Morphology type", &selected_morphology_type,
1107 morphology_type_names,
1108 sizeof(morphology_type_names) / sizeof(char*));
1109 ImGui::SliderFloat2("Radius", radius, 0, 200);
1110 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1111 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1112 ImGui::ColorEdit4("Bounds color ",
1113 reinterpret_cast<float*>(&bounds_color));
1114 ImGui::SliderFloat2("Translation", offset, 0,
1115 pass.GetRenderTargetSize().width);
1116 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1117 ImGui::SliderFloat2("Scale", scale, 0, 3);
1118 ImGui::SliderFloat2("Skew", skew, -3, 3);
1119 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1120 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1121 3);
1122 }
1123 ImGui::End();
1124
1125 std::shared_ptr<Contents> input;
1126 Size input_size;
1127
1128 auto input_rect =
1129 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1130 auto texture = std::make_shared<TextureContents>();
1131 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1132 texture->SetDestinationRect(input_rect);
1133 texture->SetTexture(boston);
1134 texture->SetOpacity(input_color.alpha);
1135
1136 input = texture;
1137 input_size = input_rect.GetSize();
1138
1139 auto contents = FilterContents::MakeMorphology(
1140 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1141 morphology_types[selected_morphology_type]);
1142 contents->SetEffectTransform(Matrix::MakeScale(
1143 Vector2{effect_transform_scale, effect_transform_scale}));
1144
1145 auto ctm = Matrix::MakeScale(GetContentScale()) *
1146 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1147 Matrix::MakeRotationZ(Radians(rotation)) *
1148 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1149 Matrix::MakeSkew(skew[0], skew[1]) *
1150 Matrix::MakeTranslation(-Point(input_size) / 2);
1151
1152 Entity entity;
1153 entity.SetContents(contents);
1154 entity.SetTransform(ctm);
1155
1156 entity.Render(context, pass);
1157
1158 // Renders a red "cover" rectangle that shows the original position of the
1159 // unfiltered input.
1160 Entity cover_entity;
1161 std::unique_ptr<Geometry> geom =
1162 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath());
1163 auto cover_contents = std::make_shared<SolidColorContents>();
1164 cover_contents->SetColor(cover_color);
1165 cover_contents->SetGeometry(geom.get());
1166 cover_entity.SetContents(cover_contents);
1167 cover_entity.SetTransform(ctm);
1168 cover_entity.Render(context, pass);
1169
1170 // Renders a green bounding rect of the target filter.
1171 Entity bounds_entity;
1172 std::unique_ptr<Geometry> bounds_geom = Geometry::MakeFillPath(
1173 PathBuilder{}
1174 .AddRect(contents->GetCoverage(entity).value())
1175 .TakePath());
1176 auto bounds_contents = std::make_shared<SolidColorContents>();
1177 bounds_contents->SetColor(bounds_color);
1178 bounds_contents->SetGeometry(bounds_geom.get());
1179 bounds_entity.SetContents(std::move(bounds_contents));
1180 bounds_entity.SetTransform(Matrix());
1181
1182 bounds_entity.Render(context, pass);
1183
1184 return true;
1185 };
1186 ASSERT_TRUE(OpenPlaygroundHere(callback));
1187 }

References impeller::PathBuilder::AddRect(), 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(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [406/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2084 of file entity_unittests.cc.

2084 {
2085 std::vector<Point> points = {{10, 20}, {100, 200}};
2086 PointFieldGeometry geometry(points.data(), 2, 5.0, false);
2087 ASSERT_EQ(geometry.GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2088 ASSERT_EQ(geometry.GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2089 Rect::MakeLTRB(35, 15, 135, 205));
2090 }

References impeller::PointFieldGeometry::GetCoverage(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [407/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2025 of file entity_unittests.cc.

2025 {
2026 Matrix matrix;
2027 RadialGradientContents contents;
2028 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2029 contents.SetGeometry(geom.get());
2030
2031 contents.SetColors({Color::CornflowerBlue()});
2032 EXPECT_TRUE(contents.IsOpaque(matrix));
2033 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2034 EXPECT_FALSE(contents.IsOpaque(matrix));
2035 contents.SetColors({Color::CornflowerBlue()});
2036 contents.SetTileMode(Entity::TileMode::kDecal);
2037 EXPECT_FALSE(contents.IsOpaque(matrix));
2038
2039 // Create stroked path that required alpha coverage.
2040 geom = Geometry::MakeStrokePath(
2041 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2042 /*stroke_width=*/0.05);
2043 contents.SetGeometry(geom.get());
2044 contents.SetColors({Color::CornflowerBlue()});
2045
2046 EXPECT_FALSE(contents.IsOpaque(matrix));
2047 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, 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() [408/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1332 of file entity_unittests.cc.

1332 {
1333 auto callback = [&](ContentContext& context, RenderPass& pass) {
1334 static Color color = Color::Red();
1335 static float corner_radius = 100;
1336 static float blur_radius = 100;
1337 static bool show_coverage = false;
1338 static Color coverage_color = Color::Green().WithAlpha(0.2);
1339
1340 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1341 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1342 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1343 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1344 ImGui::Checkbox("Show coverage", &show_coverage);
1345 if (show_coverage) {
1346 ImGui::ColorEdit4("Coverage color",
1347 reinterpret_cast<Scalar*>(&coverage_color));
1348 }
1349 ImGui::End();
1350
1351 PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1352 PlaygroundPoint bottom_right_point(Point(600, 400), 30, Color::White());
1353 auto [top_left, bottom_right] =
1354 DrawPlaygroundLine(top_left_point, bottom_right_point);
1355 auto rect =
1356 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1357
1358 auto contents = std::make_unique<SolidRRectBlurContents>();
1359 contents->SetRRect(rect, {corner_radius, corner_radius});
1360 contents->SetColor(color);
1361 contents->SetSigma(Radius(blur_radius));
1362
1363 Entity entity;
1364 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1365 entity.SetContents(std::move(contents));
1366 entity.Render(context, pass);
1367
1368 auto coverage = entity.GetCoverage();
1369 if (show_coverage && coverage.has_value()) {
1370 auto bounds_contents = std::make_unique<SolidColorContents>();
1371 auto geom = Geometry::MakeFillPath(
1372 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
1373 bounds_contents->SetGeometry(geom.get());
1374 bounds_contents->SetColor(coverage_color.Premultiply());
1375 Entity bounds_entity;
1376 bounds_entity.SetContents(std::move(bounds_contents));
1377 bounds_entity.Render(context, pass);
1378 }
1379
1380 return true;
1381 };
1382 ASSERT_TRUE(OpenPlaygroundHere(callback));
1383 }

References impeller::PathBuilder::AddRect(), 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::PathBuilder::TakePath(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [409/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1691 of file entity_unittests.cc.

1691 {
1692 auto runtime_stages =
1693 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1694 auto runtime_stage =
1695 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1696 ASSERT_TRUE(runtime_stage);
1697 ASSERT_TRUE(runtime_stage->IsDirty());
1698
1699 bool expect_dirty = true;
1700
1701 PipelineRef first_pipeline;
1702 std::unique_ptr<Geometry> geom = Geometry::MakeCover();
1703
1704 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1705 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1706
1707 auto contents = std::make_shared<RuntimeEffectContents>();
1708 contents->SetGeometry(geom.get());
1709 contents->SetRuntimeStage(runtime_stage);
1710
1711 struct FragUniforms {
1712 Vector2 iResolution;
1713 Scalar iTime;
1714 } frag_uniforms = {
1715 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1716 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1717 };
1718 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1719 uniform_data->resize(sizeof(FragUniforms));
1720 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1721 contents->SetUniformData(uniform_data);
1722
1723 Entity entity;
1724 entity.SetContents(contents);
1725 bool result = contents->Render(context, entity, pass);
1726
1727 if (expect_dirty) {
1728 first_pipeline = pass.GetCommands().back().pipeline;
1729 } else {
1730 EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
1731 }
1732 expect_dirty = false;
1733 return result;
1734 };
1735
1736 // Simulate some renders and hot reloading of the shader.
1737 auto content_context = GetContentContext();
1738 {
1739 RenderTarget target =
1740 content_context->GetRenderTargetCache()->CreateOffscreen(
1741 *content_context->GetContext(), {1, 1}, 1u);
1742
1743 testing::MockRenderPass mock_pass(GetContext(), target);
1744 callback(*content_context, mock_pass);
1745 callback(*content_context, mock_pass);
1746
1747 // Dirty the runtime stage.
1748 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1749 runtime_stage =
1750 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1751
1752 ASSERT_TRUE(runtime_stage->IsDirty());
1753 expect_dirty = true;
1754
1755 callback(*content_context, mock_pass);
1756 }
1757 }
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() [410/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 1806 of file entity_unittests.cc.

1806 {
1807 auto runtime_stages =
1808 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1809 auto runtime_stage =
1810 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1811 ASSERT_TRUE(runtime_stage);
1812 ASSERT_TRUE(runtime_stage->IsDirty());
1813
1814 auto contents = std::make_shared<RuntimeEffectContents>();
1815 contents->SetRuntimeStage(runtime_stage);
1816
1817 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
1818 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [411/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 1759 of file entity_unittests.cc.

1759 {
1760 auto runtime_stages =
1761 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1762 auto runtime_stage =
1763 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1764 ASSERT_TRUE(runtime_stage);
1765 ASSERT_TRUE(runtime_stage->IsDirty());
1766
1767 auto contents = std::make_shared<RuntimeEffectContents>();
1768 auto geom = Geometry::MakeCover();
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
1787 // Create a render target with a depth-stencil, similar to how EntityPass
1788 // does.
1789 RenderTarget target =
1790 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
1791 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
1792 "RuntimeEffect Texture");
1793 testing::MockRenderPass pass(GetContext(), target);
1794
1795 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
1796 ASSERT_EQ(pass.GetCommands().size(), 1u);
1797 const auto& command = pass.GetCommands()[0];
1798 ASSERT_TRUE(command.pipeline->GetDescriptor()
1799 .GetDepthStencilAttachmentDescriptor()
1800 .has_value());
1801 ASSERT_TRUE(command.pipeline->GetDescriptor()
1802 .GetFrontStencilAttachmentDescriptor()
1803 .has_value());
1804 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [412/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 1820 of file entity_unittests.cc.

1820 {
1821 if (GetBackend() != PlaygroundBackend::kVulkan) {
1822 GTEST_SKIP() << "Test only applies to Vulkan";
1823 }
1824
1825 auto runtime_stages =
1826 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1827 auto runtime_stage =
1828 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1829 ASSERT_TRUE(runtime_stage);
1830 ASSERT_TRUE(runtime_stage->IsDirty());
1831
1832 auto contents = std::make_shared<RuntimeEffectContents>();
1833 auto geom = Geometry::MakeCover();
1834 contents->SetGeometry(geom.get());
1835 contents->SetRuntimeStage(runtime_stage);
1836
1837 struct FragUniforms {
1838 Vector2 iResolution;
1839 Scalar iTime;
1840 } frag_uniforms = {
1841 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1842 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1843 };
1844 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1845 uniform_data->resize(sizeof(FragUniforms));
1846 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1847
1848 auto buffer_view = RuntimeEffectContents::EmplaceVulkanUniform(
1849 uniform_data, GetContentContext()->GetTransientsBuffer(),
1850 runtime_stage->GetUniforms()[0]);
1851
1852 // 16 bytes:
1853 // 8 bytes for iResolution
1854 // 4 bytes for iTime
1855 // 4 bytes padding
1856 EXPECT_EQ(buffer_view.GetRange().length, 16u);
1857 }

References buffer_view, impeller::RuntimeEffectContents::EmplaceVulkanUniform(), impeller::kVulkan, impeller::Geometry::MakeCover(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [413/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1189 of file entity_unittests.cc.

1189 {
1190 Entity entity;
1191 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSrcOver);
1192 entity.SetBlendMode(BlendMode::kClear);
1193 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1194 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSrcOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [414/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 2441 of file entity_unittests.cc.

2441 {
2442 auto contents = SolidColorContents();
2443 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2444 auto result = contents.ApplyColorFilter([](const Color& color) {
2445 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2446 });
2447 ASSERT_TRUE(result);
2448 ASSERT_COLOR_NEAR(contents.GetColor(),
2449 Color(0.424452, 0.828743, 0.79105, 0.9375));
2450 }

References ASSERT_COLOR_NEAR, impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [415/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 1959 of file entity_unittests.cc.

1959 {
1960 Matrix matrix;
1961 SolidColorContents contents;
1962 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
1963 contents.SetGeometry(geom.get());
1964
1965 contents.SetColor(Color::CornflowerBlue());
1966 EXPECT_TRUE(contents.IsOpaque(matrix));
1967 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
1968 EXPECT_FALSE(contents.IsOpaque(matrix));
1969
1970 // Create stroked path that required alpha coverage.
1971 geom = Geometry::MakeStrokePath(
1972 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
1973 /*stroke_width=*/0.05);
1974 contents.SetGeometry(geom.get());
1975 contents.SetColor(Color::CornflowerBlue());
1976
1977 EXPECT_FALSE(contents.IsOpaque(matrix));
1978 }

References impeller::PathBuilder::AddLine(), 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() [416/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 676 of file entity_unittests.cc.

676 {
677 {
678 auto geometry = Geometry::MakeStrokePath(Path{});
679 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
680 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
681 }
682
683 {
684 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
685 /*miter_limit=*/8.0);
686 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
687 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
688 }
689
690 {
691 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0,
692 /*miter_limit=*/-1.0);
693 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
694 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
695 }
696 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [417/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 654 of file entity_unittests.cc.

654 {
655 {
656 auto geometry = Geometry::MakeStrokePath(Path{});
657 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
658 // Defaults.
659 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
660 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
661 }
662
663 {
664 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
665 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
666 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
667 }
668
669 {
670 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
671 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
672 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
673 }
674 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [418/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1286 of file entity_unittests.cc.

1286 {
1287 // No transform
1288 {
1289 auto fill = std::make_shared<SolidColorContents>();
1290 fill->SetColor(Color::CornflowerBlue());
1291 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1292 auto geom =
1293 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath());
1294 fill->SetGeometry(geom.get());
1295
1296 auto coverage = fill->GetCoverage({});
1297 ASSERT_TRUE(coverage.has_value());
1298 ASSERT_RECT_NEAR(coverage.value(), expected);
1299 }
1300
1301 // Entity transform
1302 {
1303 auto fill = std::make_shared<SolidColorContents>();
1304 auto geom = Geometry::MakeFillPath(
1305 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1306 fill->SetColor(Color::CornflowerBlue());
1307 fill->SetGeometry(geom.get());
1308
1309 Entity entity;
1310 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1311 entity.SetContents(std::move(fill));
1312
1313 auto coverage = entity.GetCoverage();
1314 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1315 ASSERT_TRUE(coverage.has_value());
1316 ASSERT_RECT_NEAR(coverage.value(), expected);
1317 }
1318
1319 // No coverage for fully transparent colors
1320 {
1321 auto fill = std::make_shared<SolidColorContents>();
1322 auto geom = Geometry::MakeFillPath(
1323 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
1324 fill->SetColor(Color::WhiteTransparent());
1325 fill->SetGeometry(geom.get());
1326
1327 auto coverage = fill->GetCoverage({});
1328 ASSERT_FALSE(coverage.has_value());
1329 }
1330 }

References impeller::PathBuilder::AddRect(), 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() [419/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1202 of file entity_unittests.cc.

1202 {
1203 {
1204 auto geometry = Geometry::MakeStrokePath(
1205 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1206 Cap::kButt, Join::kBevel);
1207
1208 Entity entity;
1209 auto contents = std::make_unique<SolidColorContents>();
1210 contents->SetGeometry(geometry.get());
1211 contents->SetColor(Color::Black());
1212 entity.SetContents(std::move(contents));
1213 auto actual = entity.GetCoverage();
1214 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1215
1216 ASSERT_TRUE(actual.has_value());
1217 ASSERT_RECT_NEAR(actual.value(), expected);
1218 }
1219
1220 // Cover the Cap::kSquare case.
1221 {
1222 auto geometry = Geometry::MakeStrokePath(
1223 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1224 Cap::kSquare, Join::kBevel);
1225
1226 Entity entity;
1227 auto contents = std::make_unique<SolidColorContents>();
1228 contents->SetGeometry(geometry.get());
1229 contents->SetColor(Color::Black());
1230 entity.SetContents(std::move(contents));
1231 auto actual = entity.GetCoverage();
1232 auto expected =
1233 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1234
1235 ASSERT_TRUE(actual.has_value());
1236 ASSERT_RECT_NEAR(actual.value(), expected);
1237 }
1238
1239 // Cover the Join::kMiter case.
1240 {
1241 auto geometry = Geometry::MakeStrokePath(
1242 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1243 Cap::kSquare, Join::kMiter);
1244
1245 Entity entity;
1246 auto contents = std::make_unique<SolidColorContents>();
1247 contents->SetGeometry(geometry.get());
1248 contents->SetColor(Color::Black());
1249 entity.SetContents(std::move(contents));
1250 auto actual = entity.GetCoverage();
1251 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1252
1253 ASSERT_TRUE(actual.has_value());
1254 ASSERT_RECT_NEAR(actual.value(), expected);
1255 }
1256 }

References impeller::PathBuilder::AddLine(), ASSERT_RECT_NEAR, impeller::Color::Black(), impeller::Entity::GetCoverage(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kSquare, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeStrokePath(), and impeller::Entity::SetContents().

## ◆ TEST_P() [420/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2120 of file entity_unittests.cc.

2120 {
2121 auto content_context = GetContentContext();
2122
2123 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2124 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2125 .has_depth_stencil_attachments = false,
2126 });
2127 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2128 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2129 .has_depth_stencil_attachments = true});
2130
2131 EXPECT_NE(default_gyph, alt_gyph);
2132 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2133 alt_gyph->GetDescriptor().GetSpecializationConstants());
2134
2135 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2136 PixelFormat::kA8UNormInt;
2137
2138 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2139 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2140 expected_constants);
2141 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [421/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1548 of file entity_unittests.cc.

1548 {
1549 auto image = CreateTextureForFixture("embarcadero.jpg");
1550 ASSERT_TRUE(image);
1551
1552 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1553 auto filtered =
1554 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1555
1556 // Define the entity that will serve as the control image as a Gaussian blur
1557 // filter with no filter at all.
1558 Entity entity_left;
1559 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1560 Matrix::MakeTranslation({100, 300}) *
1561 Matrix::MakeScale(Vector2{0.5, 0.5}));
1562 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1563 Sigma{0}, Sigma{0});
1564 entity_left.SetContents(unfiltered);
1565
1566 // Define the entity that will be filtered from sRGB to linear.
1567 Entity entity_right;
1568 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1569 Matrix::MakeTranslation({500, 300}) *
1570 Matrix::MakeScale(Vector2{0.5, 0.5}));
1571 entity_right.SetContents(filtered);
1572 return entity_left.Render(context, pass) &&
1573 entity_right.Render(context, pass);
1574 };
1575
1576 ASSERT_TRUE(OpenPlaygroundHere(callback));
1577 }

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() [422/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1526 of file entity_unittests.cc.

1526 {
1527 // Set up a simple color background.
1528 auto fill = std::make_shared<SolidColorContents>();
1529 auto geom = Geometry::MakeFillPath(
1530 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
1531 fill->SetGeometry(geom.get());
1532 fill->SetColor(Color::DeepPink());
1533
1534 auto filter =
1535 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1536
1537 Entity e;
1538 e.SetTransform(Matrix());
1539
1540 // Confirm that the actual filter coverage matches the expected coverage.
1541 auto actual = filter->GetCoverage(e);
1542 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1543
1544 ASSERT_TRUE(actual.has_value());
1545 ASSERT_RECT_NEAR(actual.value(), expected);
1546 }

References impeller::PathBuilder::AddRect(), 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() [423/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 196 of file entity_unittests.cc.

196 {
197 const Point padding(300, 250);
198 const Point margin(140, 180);
199
200 auto callback = [&](ContentContext& context, RenderPass& pass) {
201 // Slightly above sqrt(2) by default, so that right angles are just below
202 // the limit and acute angles are over the limit (causing them to get
203 // beveled).
204 static Scalar miter_limit = 1.41421357;
205 static Scalar width = 30;
206
207 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
208 {
209 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
210 ImGui::SliderFloat("Stroke width", &width, 0, 100);
211 if (ImGui::Button("Reset")) {
212 miter_limit = 1.41421357;
213 width = 30;
214 }
215 }
216 ImGui::End();
217
218 auto world_matrix = Matrix::MakeScale(GetContentScale());
219 auto render_path = [width = width, &context, &pass, &world_matrix](
220 const Path& path, Cap cap, Join join) {
221 auto contents = std::make_unique<SolidColorContents>();
222 std::unique_ptr<Geometry> geom =
223 Geometry::MakeStrokePath(path, width, miter_limit, cap, join);
224 contents->SetGeometry(geom.get());
225 contents->SetColor(Color::Red());
226
227 Entity entity;
228 entity.SetTransform(world_matrix);
229 entity.SetContents(std::move(contents));
230
231 auto coverage = entity.GetCoverage();
232 if (coverage.has_value()) {
233 auto bounds_contents = std::make_unique<SolidColorContents>();
234
235 std::unique_ptr<Geometry> geom = Geometry::MakeFillPath(
236 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
237
238 bounds_contents->SetGeometry(geom.get());
239 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
240 Entity bounds_entity;
241 bounds_entity.SetContents(std::move(bounds_contents));
242 bounds_entity.Render(context, pass);
243 }
244
245 entity.Render(context, pass);
246 };
247
248 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
249 e_def(75, 75);
250 const Scalar r = 30;
251 // Cap::kButt demo.
252 {
253 Point off = Point(0, 0) * padding + margin;
254 PlaygroundPoint point_a(off + a_def, r, Color::Black());
255 PlaygroundPoint point_b(off + b_def, r, Color::White());
256 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
257 PlaygroundPoint point_c(off + c_def, r, Color::Black());
258 PlaygroundPoint point_d(off + d_def, r, Color::White());
259 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
260 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
261 Cap::kButt, Join::kBevel);
262 }
263
264 // Cap::kSquare demo.
265 {
266 Point off = Point(1, 0) * padding + margin;
267 PlaygroundPoint point_a(off + a_def, r, Color::Black());
268 PlaygroundPoint point_b(off + b_def, r, Color::White());
269 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
270 PlaygroundPoint point_c(off + c_def, r, Color::Black());
271 PlaygroundPoint point_d(off + d_def, r, Color::White());
272 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
273 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
274 Cap::kSquare, Join::kBevel);
275 }
276
277 // Cap::kRound demo.
278 {
279 Point off = Point(2, 0) * padding + margin;
280 PlaygroundPoint point_a(off + a_def, r, Color::Black());
281 PlaygroundPoint point_b(off + b_def, r, Color::White());
282 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
283 PlaygroundPoint point_c(off + c_def, r, Color::Black());
284 PlaygroundPoint point_d(off + d_def, r, Color::White());
285 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
286 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
287 Cap::kRound, Join::kBevel);
288 }
289
290 // Join::kBevel demo.
291 {
292 Point off = Point(0, 1) * padding + margin;
293 PlaygroundPoint point_a = PlaygroundPoint(off + a_def, r, Color::White());
294 PlaygroundPoint point_b = PlaygroundPoint(off + e_def, r, Color::White());
295 PlaygroundPoint point_c = PlaygroundPoint(off + c_def, r, Color::White());
296 Point a = DrawPlaygroundPoint(point_a);
297 Point b = DrawPlaygroundPoint(point_b);
298 Point c = DrawPlaygroundPoint(point_c);
299 render_path(
300 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
301 Cap::kButt, Join::kBevel);
302 }
303
304 // Join::kMiter demo.
305 {
306 Point off = Point(1, 1) * padding + margin;
307 PlaygroundPoint point_a(off + a_def, r, Color::White());
308 PlaygroundPoint point_b(off + e_def, r, Color::White());
309 PlaygroundPoint point_c(off + c_def, r, Color::White());
310 Point a = DrawPlaygroundPoint(point_a);
311 Point b = DrawPlaygroundPoint(point_b);
312 Point c = DrawPlaygroundPoint(point_c);
313 render_path(
314 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
315 Cap::kButt, Join::kMiter);
316 }
317
318 // Join::kRound demo.
319 {
320 Point off = Point(2, 1) * padding + margin;
321 PlaygroundPoint point_a(off + a_def, r, Color::White());
322 PlaygroundPoint point_b(off + e_def, r, Color::White());
323 PlaygroundPoint point_c(off + c_def, r, Color::White());
324 Point a = DrawPlaygroundPoint(point_a);
325 Point b = DrawPlaygroundPoint(point_b);
326 Point c = DrawPlaygroundPoint(point_c);
327 render_path(
328 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
329 Cap::kButt, Join::kRound);
330 }
331
332 return true;
333 };
334 ASSERT_TRUE(OpenPlaygroundHere(callback));
335 }
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:86
impeller::Join
Join
Definition: path.h:26
impeller::Cap
Cap
Definition: path.h:20

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddRect(), 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(), impeller::PathBuilder::MoveTo(), padding, impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [424/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 131 of file entity_unittests.cc.

131 {
132 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
133 Path path = PathBuilder{}
134 .MoveTo({100, 100})
135 .LineTo({100, 200})
136 .MoveTo({100, 300})
137 .LineTo({100, 400})
138 .MoveTo({100, 500})
139 .LineTo({100, 600})
140 .TakePath();
141
142 Entity entity;
143 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
144 auto contents = std::make_unique<TiledTextureContents>();
145 std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 100.0);
146 contents->SetGeometry(geom.get());
147 contents->SetTexture(bridge);
148 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
149 entity.SetContents(std::move(contents));
150 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
151 }

References impeller::Entity::kClamp, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [425/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2049 of file entity_unittests.cc.

2049 {
2050 Matrix matrix;
2051 RadialGradientContents contents;
2052 auto geom = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 10, 10));
2053 contents.SetGeometry(geom.get());
2054
2055 contents.SetColors({Color::CornflowerBlue()});
2056 EXPECT_TRUE(contents.IsOpaque(matrix));
2057 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2058 EXPECT_FALSE(contents.IsOpaque(matrix));
2059 contents.SetColors({Color::CornflowerBlue()});
2060 contents.SetTileMode(Entity::TileMode::kDecal);
2061 EXPECT_FALSE(contents.IsOpaque(matrix));
2062
2063 // Create stroked path that required alpha coverage.
2064 geom = Geometry::MakeStrokePath(
2065 PathBuilder{}.AddLine({0, 0}, {100, 100}).TakePath(),
2066 /*stroke_width=*/0.05);
2067 contents.SetGeometry(geom.get());
2068 contents.SetColors({Color::CornflowerBlue()});
2069
2070 EXPECT_FALSE(contents.IsOpaque(matrix));
2071 }

References impeller::PathBuilder::AddLine(), impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, 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() [426/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2112 of file entity_unittests.cc.

2112 {
2113 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f), Rational(43, 100));
2114 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f), Rational(53, 100));
2115 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f), Rational(21, 10));
2116 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f), Rational(0, 1));
2117 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f), Rational(48, 1));
2118 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [427/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 110 of file entity_unittests.cc.

110 {
111 Path path = PathBuilder{}
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 = Geometry::MakeStrokePath(path, 5.0);
125 contents->SetGeometry(geom.get());
126 contents->SetColor(Color::Red());
127 entity.SetContents(std::move(contents));
128 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
129 }

References impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [428/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2073 of file entity_unittests.cc.

2073 {
2074 Matrix matrix;
2075 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2076 TiledTextureContents contents;
2077 contents.SetTexture(bay_bridge);
2078 // This is a placeholder test. Images currently never decompress as opaque
2079 // (whether in Flutter or the playground), and so this should currently always
2080 // return false in practice.
2081 EXPECT_FALSE(contents.IsOpaque(matrix));
2082 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [429/525]

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() [430/525]

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() [431/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 153 of file entity_unittests.cc.

153 {
154 auto callback = [&](ContentContext& context, RenderPass& pass) {
155 Point offset(100, 100);
156
157 PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
158 Point a = DrawPlaygroundPoint(point_a);
159 PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
160 Point b = DrawPlaygroundPoint(point_b);
161 PlaygroundPoint point_c(Point(210, 210) + offset, 20, Color::White());
162 Point c = DrawPlaygroundPoint(point_c);
163 PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
164 Point d = DrawPlaygroundPoint(point_d);
165 PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
166 Point e = DrawPlaygroundPoint(point_e);
167 PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
168 Point f = DrawPlaygroundPoint(point_f);
169 PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
170 Point g = DrawPlaygroundPoint(point_g);
171 Path path = PathBuilder{}
172 .MoveTo(a)
173 .LineTo(b)
174 .LineTo(c)
175 .LineTo(d)
176 .Close()
177 .MoveTo(e)
178 .LineTo(f)
179 .LineTo(g)
180 .Close()
181 .TakePath();
182
183 Entity entity;
184 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
185 auto contents = std::make_unique<SolidColorContents>();
186 std::unique_ptr<Geometry> geom = Geometry::MakeStrokePath(path, 20.0);
187 contents->SetGeometry(geom.get());
188 contents->SetColor(Color::Red());
189 entity.SetContents(std::move(contents));
190
191 return entity.Render(context, pass);
192 };
193 ASSERT_TRUE(OpenPlaygroundHere(callback));
194 }

References impeller::saturated::b, impeller::PathBuilder::Close(), impeller::DrawPlaygroundPoint(), impeller::PathBuilder::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::PathBuilder::MoveTo(), offset, impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [432/525]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1657 of file entity_unittests.cc.

1657 {
1658 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1659 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1660 GTEST_SKIP()
1661 << "YUV to RGB filter is not supported on OpenGLES backend yet.";
1662 }
1663
1664 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1665 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1666 YUVColorSpace::kBT601LimitedRange};
1667 for (int i = 0; i < 2; i++) {
1668 auto yuv_color_space = yuv_color_space_array[i];
1669 auto textures =
1670 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1671 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1672 textures[0], textures[1], yuv_color_space);
1673 Entity filter_entity;
1674 filter_entity.SetContents(filter_contents);
1675 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1676
1677 Entity entity;
1678 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1679 contents->SetTexture(snapshot->texture);
1680 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1681 entity.SetContents(contents);
1682 entity.SetTransform(
1683 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1684 entity.Render(context, pass);
1685 }
1686 return true;
1687 };
1688 ASSERT_TRUE(OpenPlaygroundHere(callback));
1689 }
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1596
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() [433/525]

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() [434/525]

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() [435/525]

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() [436/525]

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() [437/525]

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() [438/525]

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() [439/525]

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() [440/525]

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() [441/525]

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() [442/525]

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());
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() [443/525]

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());
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() [444/525]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithFailingAllocationDoesntCrash |
| ) |  |

Definition at line 221 of file host_buffer_unittests.cc.

221 {
222 ScopedValidationDisable disable;
223 std::shared_ptr<FailingAllocator> allocator =
224 std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
225 auto buffer = HostBuffer::Create(allocator, GetContext()->GetIdleWaiter());
226
227 auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
228
229 EXPECT_EQ(view.GetBuffer(), nullptr);
230 EXPECT_EQ(view.GetRange().offset, 0u);
231 EXPECT_EQ(view.GetRange().length, 0u);
232 }
impeller::testing::kMagicFailingAllocation
static constexpr const size_t kMagicFailingAllocation
Definition: host_buffer_unittests.cc:191

References impeller::HostBuffer::Create(), and kMagicFailingAllocation.

## ◆ TEST_P() [445/525]

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());
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() [446/525]

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());
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() [447/525]

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());
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() [448/525]

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());
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() [449/525]

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);
32 EXPECT_CALL(*mock_idle_waiter, WaitIdle());
33 }
34 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [450/525]

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());
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() [451/525]

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());
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() [452/525]

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() [453/525]

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() [454/525]

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() [455/525]

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() [456/525]

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() [457/525]

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() [458/525]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | CanPersistAndRetrievePipelineCache |
| ) |  |

Definition at line 98 of file pipeline_cache_data_vk_unittests.cc.

98 {
99 fml::ScopedTemporaryDirectory temp_dir;
100 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
101 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
102 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
103
104 {
105 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
106 ASSERT_EQ(cache.result, vk::Result::eSuccess);
107 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
108 ASSERT_TRUE(PipelineCacheDataPersist(
109 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
110 }
111 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
112
113 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(),
114 caps.GetPhysicalDeviceProperties());
115 ASSERT_NE(mapping, nullptr);
116 // Assert that the utility has stripped away the cache header giving us clean
117 // pipeline cache bootstrap information.
118 vk::PipelineCacheHeaderVersionOne vk_cache_header;
119 ASSERT_GE(mapping->GetSize(), sizeof(vk_cache_header));
120 std::memcpy(&vk_cache_header, mapping->GetMapping(), sizeof(vk_cache_header));
121 ASSERT_EQ(vk_cache_header.headerVersion,
122 vk::PipelineCacheHeaderVersion::eOne);
123 }
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:62
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::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [459/525]

impeller::testing::TEST_P | ( | PipelineCacheDataVKPlaygroundTest | ,
|  | IntegrityChecksArePerformedOnPersistedData |
| ) |  |

Definition at line 125 of file pipeline_cache_data_vk_unittests.cc.

126 {
127 fml::ScopedTemporaryDirectory temp_dir;
128 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
129 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
130 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
131
132 {
133 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
134 ASSERT_EQ(cache.result, vk::Result::eSuccess);
135 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
136 ASSERT_TRUE(PipelineCacheDataPersist(
137 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
138 }
139 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
140 auto incompatible_caps = caps.GetPhysicalDeviceProperties();
141 // Simulate a driver version bump.
142 incompatible_caps.driverVersion =
143 caps.GetPhysicalDeviceProperties().driverVersion + 1u;
144 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(), incompatible_caps);
145 ASSERT_EQ(mapping, nullptr);
146 }

References impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast(), impeller::BackendCast< ContextVK, Context >::Cast(), impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::PipelineCacheDataPersist(), and impeller::PipelineCacheDataRetrieve().

## ◆ TEST_P() [460/525]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateRenderPassAndSubmit |
| ) |  |

Definition at line 299 of file renderer_dart_unittests.cc.

299 {
300 ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
301 }

## ◆ TEST_P() [461/525]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateShaderLibrary |
| ) |  |

Definition at line 291 of file renderer_dart_unittests.cc.

291 {
292 ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
293 }

## ◆ TEST_P() [462/525]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

These test entries correspond to Dart functions located in `flutter/impeller/fixtures/dart_tests.dart`

Definition at line 287 of file renderer_dart_unittests.cc.

287 {
288 ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
289 }

## ◆ TEST_P() [463/525]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanReflectUniformStructs |
| ) |  |

Definition at line 295 of file renderer_dart_unittests.cc.

295 {
296 ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
297 }

## ◆ TEST_P() [464/525]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 272 of file renderer_dart_unittests.cc.

272 {
273 SinglePassCallback callback = [&](RenderPass& pass) {
274 ImGui::Begin("Dart test", nullptr);
275 ImGui::Text(
276 "This test executes Dart code during the playground frame callback.");
277 ImGui::End();
278
279 return RunDartFunction("sayHi");
280 };
281 ASSERT_TRUE(OpenPlaygroundHere(callback));
282 }

## ◆ TEST_P() [465/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 1017 of file renderer_unittests.cc.

1017 {
1018 using VS = ArrayVertexShader;
1019 using FS = ArrayFragmentShader;
1020
1021 auto context = GetContext();
1022 auto pipeline_descriptor =
1023 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1024 ASSERT_TRUE(pipeline_descriptor.has_value());
1025 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1026 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1027 auto pipeline =
1028 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1029 ASSERT_TRUE(pipeline && pipeline->IsValid());
1030
1031 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1032 context->GetIdleWaiter());
1033 SinglePassCallback callback = [&](RenderPass& pass) {
1034 auto size = pass.GetRenderTargetSize();
1035
1036 pass.SetPipeline(pipeline);
1037 pass.SetCommandLabel("Google Dots");
1038 VertexBufferBuilder<VS::PerVertexData> builder;
1039 builder.AddVertices({{Point()},
1040 {Point(0, size.height)},
1041 {Point(size.width, 0)},
1042 {Point(size.width, 0)},
1043 {Point(0, size.height)},
1044 {Point(size.width, size.height)}});
1045 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1046
1047 VS::FrameInfo frame_info;
1048 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1049 frame_info.mvp =
1050 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1051 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1052
1053 auto time = GetSecondsElapsed();
1054 auto y_pos = [&time](float x) {
1055 return 400 + 10 * std::cos(time * 5 + x / 6);
1056 };
1057
1058 FS::FragInfo fs_uniform = {
1059 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1060 Point(530, y_pos(2)), Point(580, y_pos(3))},
1061 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1062 Color::MakeRGBA8(219, 68, 55, 255),
1063 Color::MakeRGBA8(244, 180, 0, 255),
1064 Color::MakeRGBA8(15, 157, 88, 255)},
1065 };
1066 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1067
1068 pass.Draw();
1069 host_buffer->Reset();
1070 return true;
1071 };
1072 OpenPlaygroundHere(callback);
1073 }

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() [466/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BabysFirstTriangle |
| ) |  |

Definition at line 122 of file renderer_unittests.cc.

122 {
123 auto context = GetContext();
124 ASSERT_TRUE(context);
125
126 // Declare a shorthand for the shaders we are going to use.
127 using VS = BabyVertexShader;
128 using FS = BabyFragmentShader;
129
130 // Create a pipeline descriptor that uses the shaders together and default
131 // initializes the fixed function state.
132 //
133 // If the vertex shader outputs disagree with the fragment shader inputs, this
134 // will be a compile time error.
135 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
136 ASSERT_TRUE(desc.has_value());
137
138 // Modify the descriptor for our environment. This is specific to our test.
139 desc->SetSampleCount(SampleCount::kCount4);
140 desc->SetStencilAttachmentDescriptors(std::nullopt);
141
142 // Create a pipeline from our descriptor. This is expensive to do. So just do
143 // it once.
144 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
145
146 // Create a host side buffer to build the vertex and uniform information.
147 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
148 context->GetIdleWaiter());
149
150 // Specify the vertex buffer information.
151 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
152 vertex_buffer_builder.AddVertices({
153 {{-0.5, -0.5}, Color::Red(), Color::Green()},
154 {{0.0, 0.5}, Color::Green(), Color::Blue()},
155 {{0.5, -0.5}, Color::Blue(), Color::Red()},
156 });
157
158 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
159 *context->GetResourceAllocator());
160
161 SinglePassCallback callback = [&](RenderPass& pass) {
162 pass.SetPipeline(pipeline);
163 pass.SetVertexBuffer(vertex_buffer);
164
165 FS::FragInfo frag_info;
166 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
167
168 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
169 context->GetIdleWaiter());
170 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
171
172 return pass.Draw().ok();
173 };
174 OpenPlaygroundHere(callback);
175 }

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() [467/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BindingNullTexturesDoesNotCrash |
| ) |  |

Definition at line 1613 of file renderer_unittests.cc.

1613 {
1614 using FS = BoxFadeFragmentShader;
1615
1616 auto context = GetContext();
1617 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1618 auto command_buffer = context->CreateCommandBuffer();
1619
1620 RenderTargetAllocator allocator(context->GetResourceAllocator());
1621 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1622
1623 auto pass = command_buffer->CreateRenderPass(target);
1624 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1625 }

References impeller::RenderTargetAllocator::CreateOffscreen().

## ◆ TEST_P() [468/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebuffer |
| ) |  |

Definition at line 16 of file render_pass_cache_unittests.cc.

16 {
17 if (GetBackend() != PlaygroundBackend::kVulkan) {
18 GTEST_SKIP() << "Test only applies to Vulkan";
19 }
20
21 auto allocator = std::make_shared<RenderTargetAllocator>(
22 GetContext()->GetResourceAllocator());
23
24 RenderTarget render_target =
25 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
26 std::shared_ptr<Texture> resolve_texture =
27 render_target.GetColorAttachment(0).resolve_texture;
28 TextureVK& texture_vk = TextureVK::Cast(*resolve_texture);
29
30 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
31 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
32
33 auto buffer = GetContext()->CreateCommandBuffer();
34 auto render_pass = buffer->CreateRenderPass(render_target);
35
36 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
37 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
38
39 render_pass->EncodeCommands();
40 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer}).ok());
41
42 // Can be reused without error.
43 auto buffer_2 = GetContext()->CreateCommandBuffer();
44 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
45
46 EXPECT_TRUE(render_pass_2->EncodeCommands());
47 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
48 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), impeller::TextureVK::GetCachedFramebuffer(), impeller::TextureVK::GetCachedRenderPass(), impeller::RenderTarget::GetColorAttachment(), impeller::kVulkan, and impeller::Attachment::resolve_texture.

## ◆ TEST_P() [469/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebufferNonMSAA |
| ) |  |

Definition at line 50 of file render_pass_cache_unittests.cc.

50 {
51 if (GetBackend() != PlaygroundBackend::kVulkan) {
52 GTEST_SKIP() << "Test only applies to Vulkan";
53 }
54
55 auto allocator = std::make_shared<RenderTargetAllocator>(
56 GetContext()->GetResourceAllocator());
57
58 RenderTarget render_target =
59 allocator->CreateOffscreen(*GetContext(), {100, 100}, 1);
60 std::shared_ptr<Texture> color_texture =
61 render_target.GetColorAttachment(0).texture;
62 TextureVK& texture_vk = TextureVK::Cast(*color_texture);
63
64 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
65 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
66
67 auto buffer = GetContext()->CreateCommandBuffer();
68 auto render_pass = buffer->CreateRenderPass(render_target);
69
70 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
71 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
72
73 render_pass->EncodeCommands();
74 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer}).ok());
75
76 // Can be reused without error.
77 auto buffer_2 = GetContext()->CreateCommandBuffer();
78 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
79
80 EXPECT_TRUE(render_pass_2->EncodeCommands());
81 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
82 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), impeller::TextureVK::GetCachedFramebuffer(), impeller::TextureVK::GetCachedRenderPass(), impeller::RenderTarget::GetColorAttachment(), impeller::kVulkan, and impeller::Attachment::texture.

## ◆ TEST_P() [470/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 634 of file renderer_unittests.cc.

634 {
635 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
636 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
637 }
638 auto context = GetContext();
639 ASSERT_TRUE(context);
640
641 using VS = MipmapsVertexShader;
642 using FS = MipmapsFragmentShader;
643 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
644 ASSERT_TRUE(desc.has_value());
645 desc->SetSampleCount(SampleCount::kCount4);
646 desc->SetStencilAttachmentDescriptors(std::nullopt);
647 auto mipmaps_pipeline =
648 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
649 ASSERT_TRUE(mipmaps_pipeline);
650
651 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
652 auto boston = CreateTextureForFixture("boston.jpg");
653 ASSERT_TRUE(bridge && boston);
654 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
655 ASSERT_TRUE(sampler);
656
657 TextureDescriptor texture_desc;
658 texture_desc.storage_mode = StorageMode::kHostVisible;
659 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
660 texture_desc.size = bridge->GetTextureDescriptor().size;
661 texture_desc.mip_count = 1u;
662 texture_desc.usage = TextureUsage::kRenderTarget |
663 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
664 DeviceBufferDescriptor device_buffer_desc;
665 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
666 device_buffer_desc.size =
667 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
668 auto device_buffer =
669 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
670
671 // Vertex buffer.
672 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
673 vertex_builder.SetLabel("Box");
674 auto size = Point(boston->GetSize());
675 vertex_builder.AddVertices({
676 {{0, 0}, {0.0, 0.0}}, // 1
677 {{size.x, 0}, {1.0, 0.0}}, // 2
678 {{size.x, size.y}, {1.0, 1.0}}, // 3
679 {{0, 0}, {0.0, 0.0}}, // 1
680 {{size.x, size.y}, {1.0, 1.0}}, // 3
681 {{0, size.y}, {0.0, 1.0}}, // 4
682 });
683 auto vertex_buffer =
684 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
685 ASSERT_TRUE(vertex_buffer);
686
687 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
688 context->GetIdleWaiter());
689 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
690 {
691 auto buffer = context->CreateCommandBuffer();
692 if (!buffer) {
693 return false;
694 }
695 buffer->SetLabel("Playground Command Buffer");
696 auto pass = buffer->CreateBlitPass();
697 if (!pass) {
698 return false;
699 }
700 pass->SetLabel("Playground Blit Pass");
701
702 // Blit `bridge` to the top left corner of the texture.
703 pass->AddCopy(bridge, device_buffer);
704 pass->EncodeCommands();
705
706 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
707 return false;
708 }
709 }
710
711 {
712 auto buffer = context->CreateCommandBuffer();
713 if (!buffer) {
714 return false;
715 }
716 buffer->SetLabel("Playground Command Buffer");
717
718 auto pass = buffer->CreateRenderPass(render_target);
719 if (!pass) {
720 return false;
721 }
722 pass->SetLabel("Playground Render Pass");
723 {
724 pass->SetCommandLabel("Image");
725 pass->SetPipeline(mipmaps_pipeline);
726 pass->SetVertexBuffer(vertex_buffer);
727
728 VS::FrameInfo frame_info;
729 EXPECT_EQ(pass->GetOrthographicTransform(),
730 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
731 frame_info.mvp = pass->GetOrthographicTransform() *
732 Matrix::MakeScale(GetContentScale());
733 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
734
735 FS::FragInfo frag_info;
736 frag_info.lod = 0;
737 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
738
739 raw_ptr<const Sampler> sampler =
740 context->GetSamplerLibrary()->GetSampler({});
741 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
742 auto texture =
743 context->GetResourceAllocator()->CreateTexture(texture_desc);
744 if (!texture->SetContents(device_buffer->OnGetContents(),
745 buffer_view.GetRange().length)) {
746 VALIDATION_LOG << "Could not upload texture to device memory";
747 return false;
748 }
749 FS::BindTex(*pass, texture, sampler);
750
751 pass->Draw().ok();
752 }
753 pass->EncodeCommands();
754 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
755 return false;
756 }
757 }
758 host_buffer->Reset();
759 return true;
760 };
761 OpenPlaygroundHere(callback);
762 }
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() [471/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 523 of file renderer_unittests.cc.

523 {
524 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
525 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
526 }
527 auto context = GetContext();
528 ASSERT_TRUE(context);
529
530 using VS = MipmapsVertexShader;
531 using FS = MipmapsFragmentShader;
532 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
533 ASSERT_TRUE(desc.has_value());
534 desc->SetSampleCount(SampleCount::kCount4);
535 desc->SetStencilAttachmentDescriptors(std::nullopt);
536 auto mipmaps_pipeline =
537 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
538 ASSERT_TRUE(mipmaps_pipeline);
539
540 TextureDescriptor texture_desc;
541 texture_desc.storage_mode = StorageMode::kHostVisible;
542 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
543 texture_desc.size = {800, 600};
544 texture_desc.mip_count = 1u;
545 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
546 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
547 ASSERT_TRUE(texture);
548
549 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
550 auto boston = CreateTextureForFixture("boston.jpg");
551 ASSERT_TRUE(bridge && boston);
552 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
553 ASSERT_TRUE(sampler);
554
555 // Vertex buffer.
556 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
557 vertex_builder.SetLabel("Box");
558 auto size = Point(boston->GetSize());
559 vertex_builder.AddVertices({
560 {{0, 0}, {0.0, 0.0}}, // 1
561 {{size.x, 0}, {1.0, 0.0}}, // 2
562 {{size.x, size.y}, {1.0, 1.0}}, // 3
563 {{0, 0}, {0.0, 0.0}}, // 1
564 {{size.x, size.y}, {1.0, 1.0}}, // 3
565 {{0, size.y}, {0.0, 1.0}}, // 4
566 });
567 auto vertex_buffer =
568 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
569 ASSERT_TRUE(vertex_buffer);
570
571 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
572 context->GetIdleWaiter());
573 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
574 auto buffer = context->CreateCommandBuffer();
575 if (!buffer) {
576 return false;
577 }
578 buffer->SetLabel("Playground Command Buffer");
579
580 {
581 auto pass = buffer->CreateBlitPass();
582 if (!pass) {
583 return false;
584 }
585 pass->SetLabel("Playground Blit Pass");
586
587 // Blit `bridge` to the top left corner of the texture.
588 pass->AddCopy(bridge, texture);
589
590 if (!pass->EncodeCommands()) {
591 return false;
592 }
593 }
594
595 {
596 auto pass = buffer->CreateRenderPass(render_target);
597 if (!pass) {
598 return false;
599 }
600 pass->SetLabel("Playground Render Pass");
601 {
602 pass->SetCommandLabel("Image");
603 pass->SetPipeline(mipmaps_pipeline);
604 pass->SetVertexBuffer(vertex_buffer);
605
606 VS::FrameInfo frame_info;
607 EXPECT_EQ(pass->GetOrthographicTransform(),
608 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
609 frame_info.mvp = pass->GetOrthographicTransform() *
610 Matrix::MakeScale(GetContentScale());
611 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
612
613 FS::FragInfo frag_info;
614 frag_info.lod = 0;
615 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
616
617 auto sampler = context->GetSamplerLibrary()->GetSampler({});
618 FS::BindTex(*pass, texture, sampler);
619
620 pass->Draw();
621 }
622 pass->EncodeCommands();
623 }
624
625 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
626 return false;
627 }
628 host_buffer->Reset();
629 return true;
630 };
631 OpenPlaygroundHere(callback);
632 }

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() [472/525]

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(context->GetResourceAllocator(),
82 context->GetIdleWaiter());
83 SinglePassCallback callback = [&](RenderPass& pass) {
84 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
85 static bool wireframe;
86 ImGui::Checkbox("Wireframe", &wireframe);
87 ImGui::End();
88
89 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
90 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
91
92 assert(pipeline && pipeline->IsValid());
93
94 pass.SetCommandLabel("Box");
95 pass.SetPipeline(pipeline);
96 pass.SetVertexBuffer(
97 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
98
99 VS::UniformBuffer uniforms;
100 EXPECT_EQ(pass.GetOrthographicTransform(),
101 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
102 uniforms.mvp =
103 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
104 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
105
106 FS::FrameInfo frame_info;
107 frame_info.current_time = GetSecondsElapsed();
108 frame_info.cursor_position = GetCursorPosition();
109 frame_info.window_size.x = GetWindowSize().width;
110 frame_info.window_size.y = GetWindowSize().height;
111
112 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
113 FS::BindContents1(pass, boston, sampler);
114 FS::BindContents2(pass, bridge, sampler);
115
116 host_buffer->Reset();
117 return pass.Draw().ok();
118 };
119 OpenPlaygroundHere(callback);
120 }

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() [473/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 764 of file renderer_unittests.cc.

764 {
765 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
766 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
767 }
768 auto context = GetContext();
769 ASSERT_TRUE(context);
770
771 using VS = MipmapsVertexShader;
772 using FS = MipmapsFragmentShader;
773 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
774 ASSERT_TRUE(desc.has_value());
775 desc->SetSampleCount(SampleCount::kCount4);
776 desc->SetStencilAttachmentDescriptors(std::nullopt);
777 auto mipmaps_pipeline =
778 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
779 ASSERT_TRUE(mipmaps_pipeline);
780
781 auto boston = CreateTextureForFixture("boston.jpg", true);
782 ASSERT_TRUE(boston);
783
784 // Vertex buffer.
785 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
786 vertex_builder.SetLabel("Box");
787 auto size = Point(boston->GetSize());
788 vertex_builder.AddVertices({
789 {{0, 0}, {0.0, 0.0}}, // 1
790 {{size.x, 0}, {1.0, 0.0}}, // 2
791 {{size.x, size.y}, {1.0, 1.0}}, // 3
792 {{0, 0}, {0.0, 0.0}}, // 1
793 {{size.x, size.y}, {1.0, 1.0}}, // 3
794 {{0, size.y}, {0.0, 1.0}}, // 4
795 });
796 auto vertex_buffer =
797 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
798 ASSERT_TRUE(vertex_buffer);
799
800 bool first_frame = true;
801 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
802 context->GetIdleWaiter());
803 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
804 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
805 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
806 MipFilter::kLinear};
807 const char* min_filter_names[] = {"Nearest", "Linear"};
808 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
809 MinMagFilter::kLinear};
810
811 // UI state.
812 static int selected_mip_filter = 1;
813 static int selected_min_filter = 0;
814 static float lod = 4.5;
815
816 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
817 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
818 sizeof(mip_filter_names) / sizeof(char*));
819 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
820 sizeof(min_filter_names) / sizeof(char*));
821 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
822 ImGui::End();
823
824 auto buffer = context->CreateCommandBuffer();
825 if (!buffer) {
826 return false;
827 }
828 buffer->SetLabel("Playground Command Buffer");
829
830 if (first_frame) {
831 auto pass = buffer->CreateBlitPass();
832 if (!pass) {
833 return false;
834 }
835 pass->SetLabel("Playground Blit Pass");
836
837 pass->GenerateMipmap(boston, "Boston Mipmap");
838
839 pass->EncodeCommands();
840 }
841
842 first_frame = false;
843
844 {
845 auto pass = buffer->CreateRenderPass(render_target);
846 if (!pass) {
847 return false;
848 }
849 pass->SetLabel("Playground Render Pass");
850 {
851 pass->SetCommandLabel("Image LOD");
852 pass->SetPipeline(mipmaps_pipeline);
853 pass->SetVertexBuffer(vertex_buffer);
854
855 VS::FrameInfo frame_info;
856 EXPECT_EQ(pass->GetOrthographicTransform(),
857 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
858 frame_info.mvp = pass->GetOrthographicTransform() *
859 Matrix::MakeScale(GetContentScale());
860 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
861
862 FS::FragInfo frag_info;
863 frag_info.lod = lod;
864 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
865
866 SamplerDescriptor sampler_desc;
867 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
868 sampler_desc.min_filter = min_filters[selected_min_filter];
869 raw_ptr<const Sampler> sampler =
870 context->GetSamplerLibrary()->GetSampler(sampler_desc);
871 FS::BindTex(*pass, boston, sampler);
872
873 pass->Draw();
874 }
875 pass->EncodeCommands();
876 }
877
878 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
879 return false;
880 }
881 host_buffer->Reset();
882 return true;
883 };
884 OpenPlaygroundHere(callback);
885 }
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() [474/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1363 of file renderer_unittests.cc.

1363 {
1364 auto context = GetContext();
1365 auto cmd_buffer = context->CreateCommandBuffer();
1366 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1367 GetContext()->GetResourceAllocator());
1368
1369 auto render_target = render_target_cache->CreateOffscreen(
1370 *context, {100, 100}, /*mip_count=*/1);
1371 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1372
1373 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1374 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1375 render_target.GetRenderTargetPixelFormat());
1376 EXPECT_EQ(render_pass->HasStencilAttachment(),
1377 render_target.GetStencilAttachment().has_value());
1378 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1379 render_target.GetRenderTargetSize());
1380 render_pass->EncodeCommands();
1381 }

## ◆ TEST_P() [475/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 465 of file renderer_unittests.cc.

465 {
466 if (GetParam() == PlaygroundBackend::kOpenGLES) {
467 GTEST_SKIP() << "Instancing is not supported on OpenGL.";
468 }
469 using VS = InstancedDrawVertexShader;
470 using FS = InstancedDrawFragmentShader;
471
472 VertexBufferBuilder<VS::PerVertexData> builder;
473 builder.AddVertices({
474 VS::PerVertexData{Point{10, 10}},
475 VS::PerVertexData{Point{10, 110}},
476 VS::PerVertexData{Point{110, 10}},
477 VS::PerVertexData{Point{10, 110}},
478 VS::PerVertexData{Point{110, 10}},
479 VS::PerVertexData{Point{110, 110}},
480 });
481
482 ASSERT_NE(GetContext(), nullptr);
483 auto pipeline =
484 GetContext()
485 ->GetPipelineLibrary()
486 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
487 *GetContext())
488 ->SetSampleCount(SampleCount::kCount4)
489 .SetStencilAttachmentDescriptors(std::nullopt))
490
491 .Get();
492 ASSERT_TRUE(pipeline && pipeline->IsValid());
493
494 static constexpr size_t kInstancesCount = 5u;
495 VS::InstanceInfo<kInstancesCount> instances;
496 for (size_t i = 0; i < kInstancesCount; i++) {
497 instances.colors[i] = Color::Random();
498 }
499
500 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
501 GetContext()->GetIdleWaiter());
502 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
503 pass.SetPipeline(pipeline);
504 pass.SetCommandLabel("InstancedDraw");
505
506 VS::FrameInfo frame_info;
507 EXPECT_EQ(pass.GetOrthographicTransform(),
508 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
509 frame_info.mvp =
510 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
511 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
512 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
513 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
514
515 pass.SetInstanceCount(kInstancesCount);
516 pass.Draw();
517
518 host_buffer->Reset();
519 return true;
520 }));
521 }

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() [476/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 289 of file renderer_unittests.cc.

289 {
290 using VS = BoxFadeVertexShader;
291 using FS = BoxFadeFragmentShader;
292 auto context = GetContext();
293 ASSERT_TRUE(context);
294 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
295 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
296 ASSERT_TRUE(desc.has_value());
297 desc->SetSampleCount(SampleCount::kCount4);
298 desc->SetStencilAttachmentDescriptors(std::nullopt);
299 auto box_pipeline =
300 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
301 ASSERT_TRUE(box_pipeline);
302
303 // Vertex buffer.
304 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
305 vertex_builder.SetLabel("Box");
306 vertex_builder.AddVertices({
307 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
308 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
309 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
310 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
311 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
312 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
313 });
314 auto vertex_buffer =
315 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
316 ASSERT_TRUE(vertex_buffer);
317
318 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
319 auto boston = CreateTextureForFixture("boston.jpg");
320 ASSERT_TRUE(bridge && boston);
321 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
322 ASSERT_TRUE(sampler);
323
324 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
325 context->GetIdleWaiter());
326 SinglePassCallback callback = [&](RenderPass& pass) {
327 for (size_t i = 0; i < 1; i++) {
328 for (size_t j = 0; j < 1; j++) {
329 pass.SetCommandLabel("Box");
330 pass.SetPipeline(box_pipeline);
331 pass.SetVertexBuffer(vertex_buffer);
332
333 FS::FrameInfo frame_info;
334 frame_info.current_time = GetSecondsElapsed();
335 frame_info.cursor_position = GetCursorPosition();
336 frame_info.window_size.x = GetWindowSize().width;
337 frame_info.window_size.y = GetWindowSize().height;
338
339 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
340 FS::BindContents1(pass, boston, sampler);
341 FS::BindContents2(pass, bridge, sampler);
342
343 VS::UniformBuffer uniforms;
344 EXPECT_EQ(pass.GetOrthographicTransform(),
345 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
346 uniforms.mvp = pass.GetOrthographicTransform() *
347 Matrix::MakeScale(GetContentScale()) *
348 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
349 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
350 if (!pass.Draw().ok()) {
351 return false;
352 }
353 }
354 }
355
356 host_buffer->Reset();
357 return true;
358 };
359 OpenPlaygroundHere(callback);
360 }

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() [477/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 177 of file renderer_unittests.cc.

177 {
178 using VS = ColorsVertexShader;
179 using FS = ColorsFragmentShader;
180 auto context = GetContext();
181 ASSERT_TRUE(context);
182 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
183 ASSERT_TRUE(desc.has_value());
184 desc->SetCullMode(CullMode::kBackFace);
185 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
186 desc->SetSampleCount(SampleCount::kCount4);
187 desc->ClearStencilAttachments();
188
189 // Setup the vertex layout to take two bindings. The first for positions and
190 // the second for colors.
191 auto vertex_desc = std::make_shared<VertexDescriptor>();
192 ShaderStageIOSlot position_slot = VS::kInputPosition;
193 ShaderStageIOSlot color_slot = VS::kInputColor;
194 position_slot.binding = 0;
195 position_slot.offset = 0;
196 color_slot.binding = 1;
197 color_slot.offset = 0;
198 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
199 const std::vector<ShaderStageBufferLayout> layouts = {
200 ShaderStageBufferLayout{.stride = 12u, .binding = 0},
201 ShaderStageBufferLayout{.stride = 16u, .binding = 1}};
202 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
203 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
204 vertex_desc->SetStageInputs(io_slots, layouts);
205 desc->SetVertexDescriptor(std::move(vertex_desc));
206 auto pipeline =
207 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
208 ASSERT_TRUE(pipeline);
209
210 struct Cube {
211 Vector3 positions[8] = {
212 // -Z
213 {-1, -1, -1},
214 {1, -1, -1},
215 {1, 1, -1},
216 {-1, 1, -1},
217 // +Z
218 {-1, -1, 1},
219 {1, -1, 1},
220 {1, 1, 1},
221 {-1, 1, 1},
222 };
223 Color colors[8] = {
224 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
225 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
226 };
227 uint16_t indices[36] = {
228 1, 5, 2, 2, 5, 6, // +X
229 4, 0, 7, 7, 0, 3, // -X
230 4, 5, 0, 0, 5, 1, // +Y
231 3, 2, 7, 7, 2, 6, // -Y
232 5, 4, 6, 6, 4, 7, // +Z
233 0, 1, 3, 3, 1, 2, // -Z
234 };
235 } cube;
236
237 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
238 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
239
240 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
241 ASSERT_TRUE(sampler);
242
243 Vector3 euler_angles;
244 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
245 context->GetIdleWaiter());
246 SinglePassCallback callback = [&](RenderPass& pass) {
247 static Degrees fov_y(60);
248 static Scalar distance = 10;
249
250 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
251 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
252 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
253 ImGui::End();
254
255 pass.SetCommandLabel("Perspective Cube");
256 pass.SetPipeline(pipeline);
257
258 std::array<BufferView, 2> vertex_buffers = {
259 BufferView(device_buffer,
260 Range(offsetof(Cube, positions), sizeof(Cube::positions))),
261 BufferView(device_buffer,
262 Range(offsetof(Cube, colors), sizeof(Cube::colors))),
263 };
264
265 BufferView index_buffer(
266 device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
267 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
268 pass.SetElementCount(36);
269 pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
270
271 VS::UniformBuffer uniforms;
272 Scalar time = GetSecondsElapsed();
273 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
274
275 uniforms.mvp =
276 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
277 Matrix::MakeTranslation({0, 0, distance}) *
278 Matrix::MakeRotationX(Radians(euler_angles.x)) *
279 Matrix::MakeRotationY(Radians(euler_angles.y)) *
280 Matrix::MakeRotationZ(Radians(euler_angles.z));
281 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
282
283 host_buffer->Reset();
284 return pass.Draw().ok();
285 };
286 OpenPlaygroundHere(callback);
287 }

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() [478/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 362 of file renderer_unittests.cc.

362 {
363 using VS = BoxFadeVertexShader;
364 using FS = BoxFadeFragmentShader;
365 auto context = GetContext();
366 ASSERT_TRUE(context);
367 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
368 auto pipeline_desc =
369 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
370 pipeline_desc->SetSampleCount(SampleCount::kCount1);
371 pipeline_desc->ClearDepthAttachment();
372 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
373
374 ASSERT_TRUE(pipeline_desc.has_value());
375 auto box_pipeline =
376 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
377 ASSERT_TRUE(box_pipeline);
378 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
379 context->GetIdleWaiter());
380
381 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
382 vertex_builder.SetLabel("Box");
383 vertex_builder.AddVertices({
384 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
385 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
386 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
387 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
388 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
389 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
390 });
391 auto vertex_buffer =
392 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
393 ASSERT_TRUE(vertex_buffer);
394
395 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
396 auto boston = CreateTextureForFixture("boston.jpg");
397 ASSERT_TRUE(bridge && boston);
398 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
399 ASSERT_TRUE(sampler);
400
401 std::shared_ptr<RenderPass> r2t_pass;
402 auto cmd_buffer = context->CreateCommandBuffer();
403 ASSERT_TRUE(cmd_buffer);
404 {
405 ColorAttachment color0;
406 color0.load_action = LoadAction::kClear;
407 color0.store_action = StoreAction::kStore;
408
409 TextureDescriptor texture_descriptor;
410 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
411 texture_descriptor.format =
412 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
413 texture_descriptor.storage_mode = StorageMode::kHostVisible;
414 texture_descriptor.size = {400, 400};
415 texture_descriptor.mip_count = 1u;
416 texture_descriptor.usage = TextureUsage::kRenderTarget;
417
418 color0.texture =
419 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
420
421 ASSERT_TRUE(color0.IsValid());
422
423 color0.texture->SetLabel("r2t_target");
424
425 StencilAttachment stencil0;
426 stencil0.load_action = LoadAction::kClear;
427 stencil0.store_action = StoreAction::kDontCare;
428 TextureDescriptor stencil_texture_desc;
429 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
430 stencil_texture_desc.size = texture_descriptor.size;
431 stencil_texture_desc.format = PixelFormat::kS8UInt;
432 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
433 stencil0.texture =
434 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
435
436 RenderTarget r2t_desc;
437 r2t_desc.SetColorAttachment(color0, 0u);
438 r2t_desc.SetStencilAttachment(stencil0);
439 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
440 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
441 }
442
443 r2t_pass->SetCommandLabel("Box");
444 r2t_pass->SetPipeline(box_pipeline);
445 r2t_pass->SetVertexBuffer(vertex_buffer);
446
447 FS::FrameInfo frame_info;
448 frame_info.current_time = GetSecondsElapsed();
449 frame_info.cursor_position = GetCursorPosition();
450 frame_info.window_size.x = GetWindowSize().width;
451 frame_info.window_size.y = GetWindowSize().height;
452
453 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
454 FS::BindContents1(*r2t_pass, boston, sampler);
455 FS::BindContents2(*r2t_pass, bridge, sampler);
456
457 VS::UniformBuffer uniforms;
458 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
459 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
460 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
461 ASSERT_TRUE(r2t_pass->Draw().ok());
462 ASSERT_TRUE(r2t_pass->EncodeCommands());
463 }

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() [479/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1505 of file renderer_unittests.cc.

1505 {
1506 // Define shader types
1507 using TextureVS = TextureVertexShader;
1508 using TextureFS = TextureFragmentShader;
1509
1510 using SwizzleVS = SepiaVertexShader;
1511 using SwizzleFS = SwizzleFragmentShader;
1512
1513 using SepiaVS = SepiaVertexShader;
1514 using SepiaFS = SepiaFragmentShader;
1515
1516 auto context = GetContext();
1517 ASSERT_TRUE(context);
1518
1519 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1520 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1521 "support it.";
1522 return;
1523 }
1524
1525 // Create pipelines.
1526 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1527 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1528 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1529
1530 ASSERT_TRUE(texture_pipeline);
1531 ASSERT_TRUE(swizzle_pipeline);
1532 ASSERT_TRUE(sepia_pipeline);
1533
1534 // Vertex buffer builders.
1535 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1536 texture_vtx_builder.AddVertices({
1537 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1538 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1539 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1540 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1541 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1542 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1543 });
1544
1545 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1546 sepia_vtx_builder.AddVertices({
1547 {{100, 100, 0.0}}, // 1
1548 {{800, 100, 0.0}}, // 2
1549 {{800, 800, 0.0}}, // 3
1550 {{100, 100, 0.0}}, // 1
1551 {{800, 800, 0.0}}, // 3
1552 {{100, 800, 0.0}}, // 4
1553 });
1554
1555 auto boston = CreateTextureForFixture("boston.jpg");
1556 ASSERT_TRUE(boston);
1557
1558 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1559 ASSERT_TRUE(sampler);
1560
1561 SinglePassCallback callback = [&](RenderPass& pass) {
1562 auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
1563 context->GetIdleWaiter());
1564
1565 // Draw the texture.
1566 {
1567 pass.SetPipeline(texture_pipeline);
1568 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1569 *context->GetResourceAllocator()));
1570 TextureVS::UniformBuffer uniforms;
1571 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1572 Matrix::MakeScale(GetContentScale());
1573 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1574 TextureFS::BindTextureContents(pass, boston, sampler);
1575 if (!pass.Draw().ok()) {
1576 return false;
1577 }
1578 }
1579
1580 // Draw the sepia toner.
1581 {
1582 pass.SetPipeline(sepia_pipeline);
1583 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1584 *context->GetResourceAllocator()));
1585 SepiaVS::UniformBuffer uniforms;
1586 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1587 Matrix::MakeScale(GetContentScale());
1588 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1589 if (!pass.Draw().ok()) {
1590 return false;
1591 }
1592 }
1593
1594 // Draw the swizzle.
1595 {
1596 pass.SetPipeline(swizzle_pipeline);
1597 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1598 *context->GetResourceAllocator()));
1599 SwizzleVS::UniformBuffer uniforms;
1600 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1601 Matrix::MakeScale(GetContentScale());
1602 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1603 if (!pass.Draw().ok()) {
1604 return false;
1605 }
1606 }
1607
1608 return true;
1609 };
1610 OpenPlaygroundHere(callback);
1611 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [480/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1416 of file renderer_unittests.cc.

1416 {
1417 // Define shader types
1418 using TextureVS = TextureVertexShader;
1419 using TextureFS = TextureFragmentShader;
1420
1421 using SepiaVS = SepiaVertexShader;
1422 using SepiaFS = SepiaFragmentShader;
1423
1424 auto context = GetContext();
1425 ASSERT_TRUE(context);
1426
1427 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1428 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1429 "support it.";
1430 return;
1431 }
1432
1433 // Create pipelines.
1434 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1435 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1436
1437 ASSERT_TRUE(texture_pipeline);
1438 ASSERT_TRUE(sepia_pipeline);
1439
1440 // Vertex buffer builders.
1441 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1442 texture_vtx_builder.AddVertices({
1443 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1444 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1445 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1446 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1447 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1448 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1449 });
1450
1451 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1452 sepia_vtx_builder.AddVertices({
1453 {{100, 100, 0.0}}, // 1
1454 {{800, 100, 0.0}}, // 2
1455 {{800, 800, 0.0}}, // 3
1456 {{100, 100, 0.0}}, // 1
1457 {{800, 800, 0.0}}, // 3
1458 {{100, 800, 0.0}}, // 4
1459 });
1460
1461 auto boston = CreateTextureForFixture("boston.jpg");
1462 ASSERT_TRUE(boston);
1463
1464 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1465 ASSERT_TRUE(sampler);
1466
1467 SinglePassCallback callback = [&](RenderPass& pass) {
1468 auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
1469 context->GetIdleWaiter());
1470
1471 // Draw the texture.
1472 {
1473 pass.SetPipeline(texture_pipeline);
1474 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1475 *context->GetResourceAllocator()));
1476 TextureVS::UniformBuffer uniforms;
1477 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1478 Matrix::MakeScale(GetContentScale());
1479 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1480 TextureFS::BindTextureContents(pass, boston, sampler);
1481 if (!pass.Draw().ok()) {
1482 return false;
1483 }
1484 }
1485
1486 // Draw the sepia toner.
1487 {
1488 pass.SetPipeline(sepia_pipeline);
1489 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1490 *context->GetResourceAllocator()));
1491 SepiaVS::UniformBuffer uniforms;
1492 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1493 Matrix::MakeScale(GetContentScale());
1494 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1495 if (!pass.Draw().ok()) {
1496 return false;
1497 }
1498 }
1499
1500 return true;
1501 };
1502 OpenPlaygroundHere(callback);
1503 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [481/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1133 of file renderer_unittests.cc.

1133 {
1134 using VS = BoxFadeVertexShader;
1135
1136 // Do not create any index buffer if no indices were provided.
1137 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1138 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1139 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [482/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1123 of file renderer_unittests.cc.

1123 {
1124 using VS = BoxFadeVertexShader;
1125
1126 // Default to 16bit index buffer size, as this is a reasonable default and
1127 // supported on all backends without extensions.
1128 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1129 vertex_builder.AppendIndex(0u);
1130 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1131 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [483/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 1075 of file renderer_unittests.cc.

1075 {
1076 using VS = InactiveUniformsVertexShader;
1077 using FS = InactiveUniformsFragmentShader;
1078
1079 auto context = GetContext();
1080 auto pipeline_descriptor =
1081 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1082 ASSERT_TRUE(pipeline_descriptor.has_value());
1083 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1084 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1085 auto pipeline =
1086 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1087 ASSERT_TRUE(pipeline && pipeline->IsValid());
1088
1089 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1090 context->GetIdleWaiter());
1091 SinglePassCallback callback = [&](RenderPass& pass) {
1092 auto size = pass.GetRenderTargetSize();
1093
1094 pass.SetPipeline(pipeline);
1095 pass.SetCommandLabel("Inactive Uniform");
1096
1097 VertexBufferBuilder<VS::PerVertexData> builder;
1098 builder.AddVertices({{Point()},
1099 {Point(0, size.height)},
1100 {Point(size.width, 0)},
1101 {Point(size.width, 0)},
1102 {Point(0, size.height)},
1103 {Point(size.width, size.height)}});
1104 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1105
1106 VS::FrameInfo frame_info;
1107 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1108 frame_info.mvp =
1109 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1110 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1111
1112 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1113 .color = Color::Green()};
1114 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1115
1116 pass.Draw().ok();
1117 host_buffer->Reset();
1118 return true;
1119 };
1120 OpenPlaygroundHere(callback);
1121 }

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() [484/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | Planet |
| ) |  |

Definition at line 950 of file renderer_unittests.cc.

950 {
951 using VS = PlanetVertexShader;
952 using FS = PlanetFragmentShader;
953
954 auto context = GetContext();
955 auto pipeline_descriptor =
956 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
957 ASSERT_TRUE(pipeline_descriptor.has_value());
958 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
959 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
960 auto pipeline =
961 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
962 ASSERT_TRUE(pipeline && pipeline->IsValid());
963
964 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
965 context->GetIdleWaiter());
966
967 SinglePassCallback callback = [&](RenderPass& pass) {
968 static Scalar speed = 0.1;
969 static Scalar planet_size = 550.0;
970 static bool show_normals = false;
971 static bool show_noise = false;
972 static Scalar seed_value = 42.0;
973
974 auto size = pass.GetRenderTargetSize();
975
976 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
977 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
978 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
979 ImGui::Checkbox("Show Normals", &show_normals);
980 ImGui::Checkbox("Show Noise", &show_noise);
981 ImGui::InputFloat("Seed Value", &seed_value);
982 ImGui::End();
983
984 pass.SetPipeline(pipeline);
985 pass.SetCommandLabel("Planet scene");
986 VertexBufferBuilder<VS::PerVertexData> builder;
987 builder.AddVertices({{Point()},
988 {Point(0, size.height)},
989 {Point(size.width, 0)},
990 {Point(size.width, 0)},
991 {Point(0, size.height)},
992 {Point(size.width, size.height)}});
993 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
994
995 VS::FrameInfo frame_info;
996 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
997 frame_info.mvp = pass.GetOrthographicTransform();
998 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
999
1000 FS::FragInfo fs_uniform;
1001 fs_uniform.resolution = Point(size);
1002 fs_uniform.time = GetSecondsElapsed();
1003 fs_uniform.speed = speed;
1004 fs_uniform.planet_size = planet_size;
1005 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1006 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1007 fs_uniform.seed_value = seed_value;
1008 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1009
1010 pass.Draw().ok();
1011 host_buffer->Reset();
1012 return true;
1013 };
1014 OpenPlaygroundHere(callback);
1015 }

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() [485/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1383 of file renderer_unittests.cc.

1384 {
1385 auto context = GetContext();
1386 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1387 GetContext()->GetResourceAllocator());
1388
1389 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1390 *context, {100, 100}, /*mip_count=*/1);
1391 EXPECT_EQ(render_target.GetDepthAttachment()
1392 ->texture->GetTextureDescriptor()
1393 .format,
1394 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1395 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [486/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1211 of file renderer_unittests.cc.

1211 {
1212 using VS = BoxFadeVertexShader;
1213 using FS = BoxFadeFragmentShader;
1214 auto context = GetContext();
1215 ASSERT_TRUE(context);
1216 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1217 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1218 ASSERT_TRUE(desc.has_value());
1219
1220 // Vertex buffer.
1221 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1222 vertex_builder.SetLabel("Box");
1223 vertex_builder.AddVertices({
1224 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1225 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1226 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1227 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1228 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1229 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1230 });
1231 auto vertex_buffer =
1232 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1233 ASSERT_TRUE(vertex_buffer);
1234
1235 desc->SetSampleCount(SampleCount::kCount4);
1236 desc->SetStencilAttachmentDescriptors(std::nullopt);
1237
1238 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1239 auto boston = CreateTextureForFixture("boston.jpg");
1240 ASSERT_TRUE(bridge && boston);
1241 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1242 ASSERT_TRUE(sampler);
1243
1244 static bool mirror = false;
1245 static int stencil_reference_write = 0xFF;
1246 static int stencil_reference_read = 0x1;
1247 std::vector<uint8_t> stencil_contents;
1248 static int last_stencil_contents_reference_value = 0;
1249 static int current_front_compare =
1250 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1251 static int current_back_compare =
1252 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1253
1254 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
1255 context->GetIdleWaiter());
1256 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1257 auto buffer = context->CreateCommandBuffer();
1258 if (!buffer) {
1259 return false;
1260 }
1261 buffer->SetLabel("Playground Command Buffer");
1262
1263 {
1264 // Configure the stencil attachment for the test.
1265 RenderTarget::AttachmentConfig stencil_config;
1266 stencil_config.load_action = LoadAction::kLoad;
1267 stencil_config.store_action = StoreAction::kDontCare;
1268 stencil_config.storage_mode = StorageMode::kHostVisible;
1269 render_target.SetupDepthStencilAttachments(
1270 *context, *context->GetResourceAllocator(),
1271 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1272 // Fill the stencil buffer with an checkerboard pattern.
1273 const auto target_width = render_target.GetRenderTargetSize().width;
1274 const auto target_height = render_target.GetRenderTargetSize().height;
1275 const size_t target_size = target_width * target_height;
1276 if (stencil_contents.size() != target_size ||
1277 last_stencil_contents_reference_value != stencil_reference_write) {
1278 stencil_contents.resize(target_size);
1279 last_stencil_contents_reference_value = stencil_reference_write;
1280 for (int y = 0; y < target_height; y++) {
1281 for (int x = 0; x < target_width; x++) {
1282 const auto index = y * target_width + x;
1283 const auto kCheckSize = 64;
1284 const auto value =
1285 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1286 stencil_reference_write;
1287 stencil_contents[index] = value;
1288 }
1289 }
1290 }
1291 if (!render_target.GetStencilAttachment()->texture->SetContents(
1292 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1293 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1294 return false;
1295 }
1296 auto pass = buffer->CreateRenderPass(render_target);
1297 if (!pass) {
1298 return false;
1299 }
1300 pass->SetLabel("Stencil Buffer");
1301 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1302 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1303 0xFF);
1304 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1305 0xFF);
1306 ImGui::Checkbox("Back face mode", &mirror);
1307 ImGui::ListBox("Front face compare function", &current_front_compare,
1308 CompareFunctionUI().labels(), CompareFunctionUI().size());
1309 ImGui::ListBox("Back face compare function", &current_back_compare,
1310 CompareFunctionUI().labels(), CompareFunctionUI().size());
1311 ImGui::End();
1312
1313 StencilAttachmentDescriptor front;
1314 front.stencil_compare =
1315 CompareFunctionUI().FunctionOf(current_front_compare);
1316 StencilAttachmentDescriptor back;
1317 back.stencil_compare =
1318 CompareFunctionUI().FunctionOf(current_back_compare);
1319 desc->SetStencilAttachmentDescriptors(front, back);
1320 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1321
1322 assert(pipeline && pipeline->IsValid());
1323
1324 pass->SetCommandLabel("Box");
1325 pass->SetPipeline(pipeline);
1326 pass->SetStencilReference(stencil_reference_read);
1327 pass->SetVertexBuffer(vertex_buffer);
1328
1329 VS::UniformBuffer uniforms;
1330 EXPECT_EQ(pass->GetOrthographicTransform(),
1331 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1332 uniforms.mvp = pass->GetOrthographicTransform() *
1333 Matrix::MakeScale(GetContentScale());
1334 if (mirror) {
1335 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1336 }
1337 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1338
1339 FS::FrameInfo frame_info;
1340 frame_info.current_time = GetSecondsElapsed();
1341 frame_info.cursor_position = GetCursorPosition();
1342 frame_info.window_size.x = GetWindowSize().width;
1343 frame_info.window_size.y = GetWindowSize().height;
1344
1345 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1346 FS::BindContents1(*pass, boston, sampler);
1347 FS::BindContents2(*pass, bridge, sampler);
1348 if (!pass->Draw().ok()) {
1349 return false;
1350 }
1351 pass->EncodeCommands();
1352 }
1353
1354 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1355 return false;
1356 }
1357 host_buffer->Reset();
1358 return true;
1359 };
1360 OpenPlaygroundHere(callback);
1361 }
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1199
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1189
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1206

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() [487/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 887 of file renderer_unittests.cc.

887 {
888 using VS = ImpellerVertexShader;
889 using FS = ImpellerFragmentShader;
890
891 auto context = GetContext();
892 auto pipeline_descriptor =
893 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
894 ASSERT_TRUE(pipeline_descriptor.has_value());
895 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
896 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
897 auto pipeline =
898 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
899 ASSERT_TRUE(pipeline && pipeline->IsValid());
900
901 auto blue_noise = CreateTextureForFixture("blue_noise.png");
902 SamplerDescriptor noise_sampler_desc;
903 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
904 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
905 raw_ptr<const Sampler> noise_sampler =
906 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
907
908 auto cube_map = CreateTextureCubeForFixture(
909 {"table_mountain_px.png", "table_mountain_nx.png",
910 "table_mountain_py.png", "table_mountain_ny.png",
911 "table_mountain_pz.png", "table_mountain_nz.png"});
912 raw_ptr<const Sampler> cube_map_sampler =
913 context->GetSamplerLibrary()->GetSampler({});
914 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
915 context->GetIdleWaiter());
916
917 SinglePassCallback callback = [&](RenderPass& pass) {
918 auto size = pass.GetRenderTargetSize();
919
920 pass.SetPipeline(pipeline);
921 pass.SetCommandLabel("Impeller SDF scene");
922 VertexBufferBuilder<VS::PerVertexData> builder;
923 builder.AddVertices({{Point()},
924 {Point(0, size.height)},
925 {Point(size.width, 0)},
926 {Point(size.width, 0)},
927 {Point(0, size.height)},
928 {Point(size.width, size.height)}});
929 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
930
931 VS::FrameInfo frame_info;
932 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
933 frame_info.mvp = pass.GetOrthographicTransform();
934 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
935
936 FS::FragInfo fs_uniform;
937 fs_uniform.texture_size = Point(size);
938 fs_uniform.time = GetSecondsElapsed();
939 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
940 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
941 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
942
943 pass.Draw().ok();
944 host_buffer->Reset();
945 return true;
946 };
947 OpenPlaygroundHere(callback);
948 }

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() [488/525]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1141 of file renderer_unittests.cc.

1141 {
1142 // Does not create index buffer if one is provided.
1143 using VS = BoxFadeVertexShader;
1144 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1145 vertex_builder.SetLabel("Box");
1146 vertex_builder.AddVertices({
1147 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1148 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1149 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1150 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1151 });
1152 vertex_builder.AppendIndex(0);
1153 vertex_builder.AppendIndex(1);
1154 vertex_builder.AppendIndex(2);
1155 vertex_builder.AppendIndex(1);
1156 vertex_builder.AppendIndex(2);
1157 vertex_builder.AppendIndex(3);
1158
1159 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1160 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1161 }

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() [489/525]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachedTextureGetsNewAttachmentConfig |
| ) |  |

Definition at line 122 of file render_target_cache_unittests.cc.

122 {
123 auto render_target_cache = RenderTargetCache(
124 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
125
126 render_target_cache.Start();
127 RenderTarget::AttachmentConfig color_attachment_config =
128 RenderTarget::kDefaultColorAttachmentConfig;
129 RenderTarget target1 = render_target_cache.CreateOffscreen(
130 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
131 render_target_cache.End();
132
133 render_target_cache.Start();
134 color_attachment_config.clear_color = Color::Red();
135 RenderTarget target2 = render_target_cache.CreateOffscreen(
136 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
137 render_target_cache.End();
138
139 ColorAttachment color1 = target1.GetColorAttachment(0);
140 ColorAttachment color2 = target2.GetColorAttachment(0);
141 // The second color attachment should reuse the first attachment's texture
142 // but with attributes from the second AttachmentConfig.
143 EXPECT_EQ(color2.texture, color1.texture);
144 EXPECT_EQ(color2.clear_color, Color::Red());
145 }

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() [490/525]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFrames |
| ) |  |

Definition at line 52 of file render_target_cache_unittests.cc.

52 {
53 auto render_target_cache = RenderTargetCache(
54 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
55
56 render_target_cache.Start();
57 // Create two render targets of the same exact size/shape. Both should be
58 // marked as used this frame, so the cached data set will contain two.
59 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
60 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
61
62 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
63
64 render_target_cache.End();
65 render_target_cache.Start();
66
67 // Next frame, only create one texture. The set will still contain two,
68 // but one will be removed at the end of the frame.
69 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
70 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
71
72 render_target_cache.End();
73 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
74 }

## ◆ TEST_P() [491/525]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFramesWithKeepAlive |
| ) |  |

Definition at line 76 of file render_target_cache_unittests.cc.

76 {
77 auto render_target_cache = RenderTargetCache(
78 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/3);
79
80 render_target_cache.Start();
81 // Create two render targets of the same exact size/shape. Both should be
82 // marked as used this frame, so the cached data set will contain two.
83 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85
86 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
87
88 render_target_cache.End();
89 render_target_cache.Start();
90
91 // The unused texture is kept alive until the keep alive countdown
92 // reaches 0.
93 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
94
95 for (auto i = 0; i < 3; i++) {
96 render_target_cache.Start();
97 render_target_cache.End();
98 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
99 }
100 // After the countdown has elapsed the texture is removed.
101 render_target_cache.Start();
102 render_target_cache.End();
103 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
104 }

## ◆ TEST_P() [492/525]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CreateWithEmptySize |
| ) |  |

Definition at line 147 of file render_target_cache_unittests.cc.

147 {
148 auto render_target_cache = RenderTargetCache(
149 GetContext()->GetResourceAllocator(), /*keep_alive_frame_count=*/0);
150
151 render_target_cache.Start();
152 RenderTarget empty_target =
153 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
154 RenderTarget empty_target_msaa =
155 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
156 render_target_cache.End();
157
158 {
159 ScopedValidationDisable disable_validation;
160 EXPECT_FALSE(empty_target.IsValid());
161 EXPECT_FALSE(empty_target_msaa.IsValid());
162 }
163 }

References impeller::RenderTarget::IsValid().

## ◆ TEST_P() [493/525]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | DoesNotPersistFailedAllocations |
| ) |  |

Definition at line 106 of file render_target_cache_unittests.cc.

106 {
107 ScopedValidationDisable disable;
108 auto allocator = std::make_shared<TestAllocator>();
109 auto render_target_cache =
110 RenderTargetCache(allocator, /*keep_alive_frame_count=*/0);
111
112 render_target_cache.Start();
113 allocator->should_fail = true;
114
115 auto render_target =
116 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
117
118 EXPECT_FALSE(render_target.IsValid());
119 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
120 }

## ◆ TEST_P() [494/525]

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() [495/525]

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() [496/525]

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() [497/525]

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() [498/525]

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() [499/525]

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() [500/525]

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() [501/525]

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() [502/525]

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() [503/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | MaintainsShape |
| ) |  |

Definition at line 182 of file text_contents_unittests.cc.

182 {
183 std::shared_ptr<TextFrame> text_frame =
184 MakeTextFrame("th", "ahem.ttf", TextOptions{.font_size = 50});
185
186 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
187 std::shared_ptr<GlyphAtlasContext> atlas_context =
188 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
189 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
190 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
191 ASSERT_TRUE(context && context->IsValid());
192
193 for (int i = 0; i <= 1000; ++i) {
194 Rational font_scale(440 + i, 1000.0);
195 Rect position_rect[2];
196 Rect uv_rect[2];
197
198 {
199 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(12);
200
201 std::shared_ptr<GlyphAtlas> atlas =
202 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
203 GlyphAtlas::Type::kAlphaBitmap, font_scale,
204 atlas_context, text_frame, /*offset=*/{0, 0});
205 ISize texture_size = atlas->GetTexture()->GetSize();
206
207 TextContents::ComputeVertexData(
208 data.data(), text_frame, static_cast<Scalar>(font_scale),
209 /*entity_transform=*/
210 Matrix::MakeScale({static_cast<Scalar>(font_scale),
211 static_cast<Scalar>(font_scale), 1}),
212 /*offset=*/Vector2(0, 0),
213 /*glyph_properties=*/std::nullopt, atlas);
214 position_rect[0] = PerVertexDataPositionToRect(data.begin());
215 uv_rect[0] = PerVertexDataUVToRect(data.begin(), texture_size);
216 position_rect[1] = PerVertexDataPositionToRect(data.begin() + 4);
217 uv_rect[1] = PerVertexDataUVToRect(data.begin() + 4, texture_size);
218 }
219 EXPECT_NEAR(GetAspectRatio(position_rect[1]), GetAspectRatio(uv_rect[1]),
220 0.001)
221 << i;
222 }
223 }
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() [504/525]

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 ASSERT_TRUE(context && context->IsValid());
126 std::shared_ptr<GlyphAtlas> atlas =
127 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
128 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1, 1),
129 atlas_context, text_frame, /*offset=*/{0, 0});
130
131 ISize texture_size = atlas->GetTexture()->GetSize();
132 TextContents::ComputeVertexData(data.data(), text_frame, /*scale=*/1.0,
133 /*entity_transform=*/Matrix(),
134 /*offset=*/Vector2(0, 0),
135 /*glyph_properties=*/std::nullopt, atlas);
136
137 Rect position_rect = PerVertexDataPositionToRect(data.begin());
138 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
139 // The -1 offset comes from Skia in `ComputeGlyphSize`. So since the font size
140 // is 50, the math appears to be to get back a 50x50 rect and apply 1 pixel
141 // of padding.
142 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
143 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
144 }

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() [505/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleComputeVertexData2x |
| ) |  |

Definition at line 146 of file text_contents_unittests.cc.

146 {
147 #ifndef FML_OS_MACOSX
148 GTEST_SKIP() << "Results aren't stable across linux and macos.";
149 #endif
150
151 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
152 std::shared_ptr<TextFrame> text_frame =
153 MakeTextFrame("1", "ahem.ttf", TextOptions{.font_size = 50});
154
155 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
156 std::shared_ptr<GlyphAtlasContext> atlas_context =
157 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
158 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
159 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
160 ASSERT_TRUE(context && context->IsValid());
161 Rational font_scale(2, 1);
162 std::shared_ptr<GlyphAtlas> atlas =
163 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
164 GlyphAtlas::Type::kAlphaBitmap, font_scale,
165 atlas_context, text_frame, /*offset=*/{0, 0});
166
167 ISize texture_size = atlas->GetTexture()->GetSize();
168 TextContents::ComputeVertexData(
169 data.data(), text_frame, static_cast<Scalar>(font_scale),
170 /*entity_transform=*/
171 Matrix::MakeScale({static_cast<Scalar>(font_scale),
172 static_cast<Scalar>(font_scale), 1}),
173 /*offset=*/Vector2(0, 0),
174 /*glyph_properties=*/std::nullopt, atlas);
175
176 Rect position_rect = PerVertexDataPositionToRect(data.begin());
177 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
178 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -81, 102, 102));
179 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 102, 102));
180 }

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() [506/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel |
| ) |  |

Definition at line 225 of file text_contents_unittests.cc.

225 {
226 #ifndef FML_OS_MACOSX
227 GTEST_SKIP() << "Results aren't stable across linux and macos.";
228 #endif
229
230 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
231
232 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
233 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
234
235 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
236 std::shared_ptr<GlyphAtlasContext> atlas_context =
237 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
238 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
239 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
240 ASSERT_TRUE(context && context->IsValid());
241 Point offset = Point(0.5, 0);
242 std::shared_ptr<GlyphAtlas> atlas =
243 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
244 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
245 atlas_context, text_frame, offset);
246
247 ISize texture_size = atlas->GetTexture()->GetSize();
248 TextContents::ComputeVertexData(
249 data.data(), text_frame, /*scale=*/1.0,
250 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
251 /*glyph_properties=*/std::nullopt, atlas);
252
253 Rect position_rect = PerVertexDataPositionToRect(data.begin());
254 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
255 // The values at Point(0, 0).
256 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
257 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
258 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
259 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
260 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and offset.

## ◆ TEST_P() [507/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel26 |
| ) |  |

Definition at line 306 of file text_contents_unittests.cc.

306 {
307 #ifndef FML_OS_MACOSX
308 GTEST_SKIP() << "Results aren't stable across linux and macos.";
309 #endif
310
311 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
312
313 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
314 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
315
316 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
317 std::shared_ptr<GlyphAtlasContext> atlas_context =
318 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
319 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
320 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
321 ASSERT_TRUE(context && context->IsValid());
322 Point offset = Point(0.26, 0);
323 std::shared_ptr<GlyphAtlas> atlas =
324 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
325 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
326 atlas_context, text_frame, offset);
327
328 ISize texture_size = atlas->GetTexture()->GetSize();
329 TextContents::ComputeVertexData(
330 data.data(), text_frame, /*scale=*/1.0,
331 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
332 /*glyph_properties=*/std::nullopt, atlas);
333
334 Rect position_rect = PerVertexDataPositionToRect(data.begin());
335 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
336 // The values without subpixel.
337 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
338 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
339 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
340 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
341 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and offset.

## ◆ TEST_P() [508/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel3x |
| ) |  |

Definition at line 262 of file text_contents_unittests.cc.

262 {
263 #ifndef FML_OS_MACOSX
264 GTEST_SKIP() << "Results aren't stable across linux and macos.";
265 #endif
266
267 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
268
269 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
270 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
271
272 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
273 std::shared_ptr<GlyphAtlasContext> atlas_context =
274 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
275 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
276 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
277 ASSERT_TRUE(context && context->IsValid());
278 Rational font_scale(3, 1);
279 Point offset = {0.16667, 0};
280 std::shared_ptr<GlyphAtlas> atlas =
281 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
282 GlyphAtlas::Type::kAlphaBitmap, font_scale,
283 atlas_context, text_frame, offset);
284
285 ISize texture_size = atlas->GetTexture()->GetSize();
286 TextContents::ComputeVertexData(
287 data.data(), text_frame, static_cast<Scalar>(font_scale),
288 /*entity_transform=*/
289 Matrix::MakeTranslation(offset) *
290 Matrix::MakeScale({static_cast<Scalar>(font_scale),
291 static_cast<Scalar>(font_scale), 1}),
292 offset,
293 /*glyph_properties=*/std::nullopt, atlas);
294
295 Rect position_rect = PerVertexDataPositionToRect(data.begin());
296 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
297 // Values at Point(0, 0)
298 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -121, 152, 152));
299 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 152, 152));
300 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -121, 154, 152))
301 << "position size:" << position_rect.GetSize();
302 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 154, 152))
303 << "position size:" << position_rect.GetSize();
304 }

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(), impeller::TRect< Scalar >::MakeXYWH(), and offset.

## ◆ TEST_P() [509/525]

impeller::testing::TEST_P | ( | TextContentsTest | ,
|  | SimpleSubpixel80 |
| ) |  |

Definition at line 343 of file text_contents_unittests.cc.

343 {
344 #ifndef FML_OS_MACOSX
345 GTEST_SKIP() << "Results aren't stable across linux and macos.";
346 #endif
347
348 std::vector<GlyphAtlasPipeline::VertexShader::PerVertexData> data(4);
349
350 std::shared_ptr<TextFrame> text_frame = MakeTextFrame(
351 "1", "ahem.ttf", TextOptions{.font_size = 50, .is_subpixel = true});
352
353 std::shared_ptr<TypographerContext> context = TypographerContextSkia::Make();
354 std::shared_ptr<GlyphAtlasContext> atlas_context =
355 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
356 std::shared_ptr<HostBuffer> host_buffer = HostBuffer::Create(
357 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter());
358 ASSERT_TRUE(context && context->IsValid());
359 Point offset = Point(0.80, 0);
360 std::shared_ptr<GlyphAtlas> atlas =
361 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
362 GlyphAtlas::Type::kAlphaBitmap, /*scale=*/Rational(1),
363 atlas_context, text_frame, offset);
364
365 ISize texture_size = atlas->GetTexture()->GetSize();
366 TextContents::ComputeVertexData(
367 data.data(), text_frame, /*scale=*/1.0,
368 /*entity_transform=*/Matrix::MakeTranslation(offset), offset,
369 /*glyph_properties=*/std::nullopt, atlas);
370
371 Rect position_rect = PerVertexDataPositionToRect(data.begin());
372 Rect uv_rect = PerVertexDataUVToRect(data.begin(), texture_size);
373 // The values without subpixel.
374 // EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-1, -41, 52, 52));
375 // EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 52, 52));
376 EXPECT_RECT_NEAR(position_rect, Rect::MakeXYWH(-2, -41, 54, 52));
377 EXPECT_RECT_NEAR(uv_rect, Rect::MakeXYWH(1.0, 1.0, 54, 52));
378 }

References impeller::TextContents::ComputeVertexData(), impeller::HostBuffer::Create(), CreateGlyphAtlas(), data, EXPECT_RECT_NEAR, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and offset.

## ◆ TEST_P() [510/525]

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() [511/525]

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(GetContext()->GetResourceAllocator(),
85 GetContext()->GetIdleWaiter());
86 ASSERT_TRUE(context && context->IsValid());
87 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
88 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
89 ASSERT_TRUE(blob);
90 auto atlas =
91 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
92 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
93 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
94
95 ASSERT_NE(atlas, nullptr);
96 ASSERT_NE(atlas->GetTexture(), nullptr);
97 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
98 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
99
100 std::optional<impeller::ScaledFont> first_scaled_font;
101 std::optional<impeller::SubpixelGlyph> first_glyph;
102 Rect first_rect;
103 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
104 const SubpixelGlyph& glyph,
105 const Rect& rect) -> bool {
106 first_scaled_font = scaled_font;
107 first_glyph = glyph;
108 first_rect = rect;
109 return false;
110 });
111
112 ASSERT_TRUE(first_scaled_font.has_value());
113 ASSERT_TRUE(atlas
114 ->FindFontGlyphBounds(
115 {first_scaled_font.value(), first_glyph.value()})
116 .has_value());
117 }
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() [512/525]

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() [513/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 180 of file typographer_unittests.cc.

180 {
181 auto context = TypographerContextSkia::Make();
182 auto atlas_context =
183 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
184 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
185 GetContext()->GetIdleWaiter());
186 ASSERT_TRUE(context && context->IsValid());
187 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
188 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
189 ASSERT_TRUE(blob);
190 auto atlas =
191 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
192 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
193 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
194 ASSERT_NE(atlas, nullptr);
195 ASSERT_NE(atlas->GetTexture(), nullptr);
196 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
197
198 // now attempt to re-create an atlas with the same text blob.
199
200 auto next_atlas =
201 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
202 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
203 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
204 ASSERT_EQ(atlas, next_atlas);
205 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
206 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [514/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 257 of file typographer_unittests.cc.

257 {
258 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
259 GetContext()->GetIdleWaiter());
260 auto context = TypographerContextSkia::Make();
261 auto atlas_context =
262 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
263 ASSERT_TRUE(context && context->IsValid());
264 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
265 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
266 ASSERT_TRUE(blob);
267 auto atlas =
268 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
269 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
270 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
271 auto old_packer = atlas_context->GetRectPacker();
272
273 ASSERT_NE(atlas, nullptr);
274 ASSERT_NE(atlas->GetTexture(), nullptr);
275 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
276
277 auto* first_texture = atlas->GetTexture().get();
278
279 // Now create a new glyph atlas with a nearly identical blob.
280
281 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
282 auto next_atlas =
283 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
284 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
285 atlas_context, MakeTextFrameFromTextBlobSkia(blob2));
286 ASSERT_EQ(atlas, next_atlas);
287 auto* second_texture = next_atlas->GetTexture().get();
288
289 auto new_packer = atlas_context->GetRectPacker();
290
291 ASSERT_EQ(second_texture, first_texture);
292 ASSERT_EQ(old_packer, new_packer);
293 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [515/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureWillGrowTilMaxTextureSize |
| ) |  |

Definition at line 426 of file typographer_unittests.cc.

426 {
427 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
428 GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
429 }
430
431 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
432 GetContext()->GetIdleWaiter());
433 auto context = TypographerContextSkia::Make();
434 auto atlas_context =
435 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
436 ASSERT_TRUE(context && context->IsValid());
437 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
438 auto blob = SkTextBlob::MakeFromString("A", sk_font);
439 ASSERT_TRUE(blob);
440 auto atlas =
441 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
442 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
443 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
444 // Continually append new glyphs until the glyph size grows to the maximum.
445 // Note that the sizes here are more or less experimentally determined, but
446 // the important expectation is that the atlas size will shrink again after
447 // growing to the maximum size.
448 constexpr ISize expected_sizes[13] = {
449 {4096, 4096}, //
450 {4096, 4096}, //
451 {4096, 8192}, //
452 {4096, 8192}, //
453 {4096, 8192}, //
454 {4096, 8192}, //
455 {4096, 16384}, //
456 {4096, 16384}, //
457 {4096, 16384}, //
458 {4096, 16384}, //
459 {4096, 16384}, //
460 {4096, 16384}, //
461 {4096, 4096} // Shrinks!
462 };
463
464 SkFont sk_font_small = flutter::testing::CreateTestFontOfSize(10);
465
466 for (int i = 0; i < 13; i++) {
467 SkTextBlobBuilder builder;
468
469 auto add_char = [&](const SkFont& sk_font, char c) {
470 int count = sk_font.countText(&c, 1, SkTextEncoding::kUTF8);
471 auto buffer = builder.allocRunPos(sk_font, count);
472 sk_font.textToGlyphs(&c, 1, SkTextEncoding::kUTF8, buffer.glyphs, count);
473 sk_font.getPos(buffer.glyphs, count, buffer.points(), {0, 0});
474 };
475
476 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
477 add_char(sk_font, 'A');
478 add_char(sk_font_small, 'B');
479 auto blob = builder.make();
480
481 atlas =
482 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
483 GlyphAtlas::Type::kAlphaBitmap, Rational(50 + i, 1),
484 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
485 ASSERT_TRUE(!!atlas);
486 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
487 expected_sizes[i]);
488 }
489
490 // The final atlas should contain both the "A" glyph (which was not present
491 // in the previous atlas) and the "B" glyph (which existed in the previous
492 // atlas).
493 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
494 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [516/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 208 of file typographer_unittests.cc.

208 {
209 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
210 GetContext()->GetIdleWaiter());
211 auto context = TypographerContextSkia::Make();
212 auto atlas_context =
213 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
214 ASSERT_TRUE(context && context->IsValid());
215
216 const char* test_string =
217 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
218 "2134567890-=!@#$%^&*()_+"
219 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
220 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
221
222 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
223 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
224 ASSERT_TRUE(blob);
225
226 size_t size_count = 8;
227 std::vector<std::shared_ptr<TextFrame>> frames;
228 for (size_t index = 0; index < size_count; index += 1) {
229 frames.push_back(MakeTextFrameFromTextBlobSkia(blob));
230 frames.back()->SetPerFrameData(Rational(6 * index, 10), {0, 0}, Matrix(),
231 {});
232 };
233 auto atlas =
234 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
235 *host_buffer, atlas_context, frames);
236 ASSERT_NE(atlas, nullptr);
237 ASSERT_NE(atlas->GetTexture(), nullptr);
238
239 std::set<uint16_t> unique_glyphs;
240 std::vector<uint16_t> total_glyphs;
241 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
242 const SubpixelGlyph& glyph, const Rect& rect) {
243 unique_glyphs.insert(glyph.glyph.index);
244 total_glyphs.push_back(glyph.glyph.index);
245 return true;
246 });
247
248 // These numbers may be different due to subpixel positions.
249 EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
250 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
251
252 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
253 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
254 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
255 }

References impeller::HostBuffer::Create(), impeller::SubpixelGlyph::glyph, impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [517/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithOddUniqueGlyphSize |
| ) |  |

Definition at line 159 of file typographer_unittests.cc.

159 {
160 auto context = TypographerContextSkia::Make();
161 auto atlas_context =
162 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
163 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
164 GetContext()->GetIdleWaiter());
165 ASSERT_TRUE(context && context->IsValid());
166 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
167 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
168 ASSERT_TRUE(blob);
169 auto atlas =
170 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
171 GlyphAtlas::Type::kAlphaBitmap, Rational(1),
172 atlas_context, MakeTextFrameFromTextBlobSkia(blob));
173 ASSERT_NE(atlas, nullptr);
174 ASSERT_NE(atlas->GetTexture(), nullptr);
175
176 EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
177 EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
178 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [518/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsIgnoredForNonEmojiFonts |
| ) |  |

Definition at line 330 of file typographer_unittests.cc.

330 {
331 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
332 GetContext()->GetIdleWaiter());
333 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
334 sk_sp<SkTypeface> typeface =
335 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
336 SkFont sk_font(typeface, 0.5f);
337
338 auto context = TypographerContextSkia::Make();
339 auto atlas_context =
340 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
341
342 // Create two frames with the same character and a different color, but as a
343 // non-emoji font the text frame constructor will ignore it.
344 auto frame =
345 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
346 auto frame_2 =
347 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
348 std::vector<std::optional<GlyphProperties>> properties = {
349 GlyphProperties{},
350 GlyphProperties{},
351 };
352
353 auto next_atlas =
354 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
355 GlyphAtlas::Type::kColorBitmap, Rational(1),
356 atlas_context, {frame, frame_2}, properties);
357
358 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
359 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [519/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsPartOfCacheKey |
| ) |  |

Definition at line 295 of file typographer_unittests.cc.

295 {
296 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
297 GetContext()->GetIdleWaiter());
298 #if FML_OS_MACOSX
299 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
300 #else
301 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
302 #endif
303 ASSERT_TRUE(mapping);
304 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
305 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
306
307 auto context = TypographerContextSkia::Make();
308 auto atlas_context =
309 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
310
311 // Create two frames with the same character and a different color, expect
312 // that it adds a character.
313 auto frame = MakeTextFrameFromTextBlobSkia(
314 SkTextBlob::MakeFromString("😂", emoji_font));
315 auto frame_2 = MakeTextFrameFromTextBlobSkia(
316 SkTextBlob::MakeFromString("😂", emoji_font));
317 std::vector<std::optional<GlyphProperties>> properties = {
318 GlyphProperties{.color = Color::Red()},
319 GlyphProperties{.color = Color::Blue()},
320 };
321
322 auto next_atlas =
323 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
324 GlyphAtlas::Type::kColorBitmap, Rational(1),
325 atlas_context, {frame, frame_2}, properties);
326
327 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
328 }

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() [520/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | InvalidAtlasForcesRepopulation |
| ) |  |

Definition at line 616 of file typographer_unittests.cc.

616 {
617 SkFont font = flutter::testing::CreateTestFontOfSize(12);
618 auto blob = SkTextBlob::MakeFromString(
619 "the quick brown fox jumped over the lazy dog.", font);
620 ASSERT_TRUE(blob);
621 auto frame = MakeTextFrameFromTextBlobSkia(blob);
622
623 EXPECT_FALSE(frame->IsFrameComplete());
624
625 auto context = TypographerContextSkia::Make();
626 auto atlas_context =
627 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
628 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
629 GetContext()->GetIdleWaiter());
630
631 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
632 GlyphAtlas::Type::kAlphaBitmap,
633 /*scale=*/Rational(1), atlas_context, frame);
634
635 // The glyph position in the atlas was not known when this value
636 // was recorded. It is marked as a placeholder.
637 EXPECT_TRUE(frame->IsFrameComplete());
638 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
639 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
640 // OpenGLES must always increase the atlas backend if the texture grows.
641 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
642 } else {
643 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
644 }
645
646 auto second_context = TypographerContextSkia::Make();
647 auto second_atlas_context =
648 second_context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
649
650 EXPECT_FALSE(second_atlas_context->GetGlyphAtlas()->IsValid());
651
652 atlas = CreateGlyphAtlas(*GetContext(), second_context.get(), *host_buffer,
653 GlyphAtlas::Type::kAlphaBitmap,
654 /*scale=*/Rational(1), second_atlas_context, frame);
655
656 EXPECT_TRUE(second_atlas_context->GetGlyphAtlas()->IsValid());
657 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [521/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 119 of file typographer_unittests.cc.

119 {
120 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
121 GetContext()->GetIdleWaiter());
122 #if FML_OS_MACOSX
123 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
124 #else
125 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
126 #endif
127 ASSERT_TRUE(mapping);
128 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
129 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
130 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
131
132 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
133 ASSERT_TRUE(blob);
134 auto frame = MakeTextFrameFromTextBlobSkia(blob);
135
136 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
137
138 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
139
140 lazy_atlas.AddTextFrame(frame, Rational(1), {0, 0}, Matrix(), {});
141
142 frame = MakeTextFrameFromTextBlobSkia(
143 SkTextBlob::MakeFromString("😀 ", emoji_font));
144
145 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
146
147 lazy_atlas.AddTextFrame(frame, Rational(1), {0, 0}, Matrix(), {});
148
149 // Creates different atlases for color and red bitmap.
150 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
151 *GetContext(), *host_buffer, GlyphAtlas::Type::kColorBitmap);
152
153 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
154 *GetContext(), *host_buffer, GlyphAtlas::Type::kAlphaBitmap);
155
156 ASSERT_FALSE(color_atlas == bitmap_atlas);
157 }

References impeller::LazyGlyphAtlas::AddTextFrame(), impeller::HostBuffer::Create(), impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [522/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 361 of file typographer_unittests.cc.

361 {
362 auto packer = RectanglePacker::Factory(200, 100);
363 ASSERT_NE(packer, nullptr);
364 ASSERT_EQ(packer->PercentFull(), 0);
365
366 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
367
368 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
369 ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
370 // Make sure the rectangle is placed such that it is inside the bounds of
371 // the packer's area.
372 const SkIRect first_rect =
373 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
374 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
375
376 // Initial area was 200 x 100 = 20_000
377 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
378 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.02));
379
380 IPoint16 second_output = {-1, -1};
381 ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
382 const SkIRect second_rect =
383 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
384 // Make sure the rectangle is placed such that it is inside the bounds of
385 // the packer's area but not in the are of the first rectangle.
386 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
387 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
388
389 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
390 // 13_000 / 20_000 == 0.65 == 65%
391 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
392
393 // There's enough area to add this rectangle, but no space big enough for
394 // the 50 units of width.
395 IPoint16 output;
396 ASSERT_FALSE(packer->AddRect(50, 50, &output));
397 // Should be unchanged.
398 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
399
400 packer->Reset();
401 // Should be empty now.
402 ASSERT_EQ(packer->PercentFull(), 0);
403 }
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() [523/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameAtlasGenerationTracksState |
| ) |  |

Definition at line 564 of file typographer_unittests.cc.

564 {
565 SkFont font = flutter::testing::CreateTestFontOfSize(12);
566 auto blob = SkTextBlob::MakeFromString(
567 "the quick brown fox jumped over the lazy dog.", font);
568 ASSERT_TRUE(blob);
569 auto frame = MakeTextFrameFromTextBlobSkia(blob);
570
571 EXPECT_FALSE(frame->IsFrameComplete());
572
573 auto context = TypographerContextSkia::Make();
574 auto atlas_context =
575 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
576 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
577 GetContext()->GetIdleWaiter());
578
579 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
580 GlyphAtlas::Type::kAlphaBitmap,
581 /*scale=*/Rational(1), atlas_context, frame);
582
583 // The glyph position in the atlas was not known when this value
584 // was recorded. It is marked as a placeholder.
585 EXPECT_TRUE(frame->IsFrameComplete());
586 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
587 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
588 // OpenGLES must always increase the atlas backend if the texture grows.
589 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
590 } else {
591 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
592 }
593
594 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
595 GlyphAtlas::Type::kAlphaBitmap,
596 /*scale=*/Rational(1), atlas_context, frame);
597
598 // The second time the glyph is rendered, the bounds are correcly known.
599 EXPECT_TRUE(frame->IsFrameComplete());
600 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
601 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
602 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 1u);
603 } else {
604 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 0u);
605 }
606
607 // Force increase the generation.
608 atlas_context->GetGlyphAtlas()->SetAtlasGeneration(2u);
609 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
610 GlyphAtlas::Type::kAlphaBitmap,
611 /*scale=*/Rational(1), atlas_context, frame);
612
613 EXPECT_EQ(frame->GetAtlasGenerationAndID().first, 2u);
614 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [524/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInitialBoundsArePlaceholder |
| ) |  |

Definition at line 496 of file typographer_unittests.cc.

496 {
497 SkFont font = flutter::testing::CreateTestFontOfSize(12);
498 auto blob = SkTextBlob::MakeFromString(
499 "the quick brown fox jumped over the lazy dog.", font);
500 ASSERT_TRUE(blob);
501 auto frame = MakeTextFrameFromTextBlobSkia(blob);
502
503 EXPECT_FALSE(frame->IsFrameComplete());
504
505 auto context = TypographerContextSkia::Make();
506 auto atlas_context =
507 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
508 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
509 GetContext()->GetIdleWaiter());
510
511 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
512 GlyphAtlas::Type::kAlphaBitmap,
513 /*scale=*/Rational(1), atlas_context, frame);
514
515 // The glyph position in the atlas was not known when this value
516 // was recorded. It is marked as a placeholder.
517 EXPECT_TRUE(frame->IsFrameComplete());
518 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
519
520 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
521 GlyphAtlas::Type::kAlphaBitmap,
522 /*scale=*/Rational(1), atlas_context, frame);
523
524 // The second time the glyph is rendered, the bounds are correcly known.
525 EXPECT_TRUE(frame->IsFrameComplete());
526 EXPECT_FALSE(frame->GetFrameBounds(0).is_placeholder);
527 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [525/525]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | TextFrameInvalidationWithScale |
| ) |  |

Definition at line 529 of file typographer_unittests.cc.

529 {
530 SkFont font = flutter::testing::CreateTestFontOfSize(12);
531 auto blob = SkTextBlob::MakeFromString(
532 "the quick brown fox jumped over the lazy dog.", font);
533 ASSERT_TRUE(blob);
534 auto frame = MakeTextFrameFromTextBlobSkia(blob);
535
536 EXPECT_FALSE(frame->IsFrameComplete());
537
538 auto context = TypographerContextSkia::Make();
539 auto atlas_context =
540 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
541 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
542 GetContext()->GetIdleWaiter());
543
544 auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
545 GlyphAtlas::Type::kAlphaBitmap,
546 /*scale=*/Rational(1), atlas_context, frame);
547
548 // The glyph position in the atlas was not known when this value
549 // was recorded. It is marked as a placeholder.
550 EXPECT_TRUE(frame->IsFrameComplete());
551 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
552
553 // Change the scale and the glyph data will still be a placeholder, as the
554 // old data is no longer valid.
555 atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
556 GlyphAtlas::Type::kAlphaBitmap,
557 /*scale=*/Rational(2), atlas_context, frame);
558
559 // The second time the glyph is rendered, the bounds are correcly known.
560 EXPECT_TRUE(frame->IsFrameComplete());
561 EXPECT_TRUE(frame->GetFrameBounds(0).is_placeholder);
562 }

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 37 of file dl_unittests.cc.

37 {
38 return flutter::DlColor(Color::ToIColor(
39 Color(components[0], components[1], components[2], components[3])));
40 }

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 16 of file golden_paths.h.

## ◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
| static constexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 374 of file aiks_dl_text_unittests.cc.

Referenced by TEST_P().

## ◆ kMagicFailingAllocation

constexpr const size_t impeller::testing::kMagicFailingAllocation = 1024000 * 2
| static constexpr

Definition at line 191 of file host_buffer_unittests.cc.

Referenced by impeller::testing::FailingAllocator::OnCreateBuffer(), and TEST_P().

## ◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
| static

Definition at line 585 of file aiks_dl_blur_unittests.cc.